mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-08 20:55:17 -05:00
rk27xx: Use DMA for lcd_update_rect()
This speeds up partial updates quite a bit but what is more important it opens up a way to efficiently implement lcd_blit_yuv() using hw colorspace conversion. Tested on rk27generic, hm60x v1 and v2 and on ma9. Benchmark for hm60x v1 (by mortalis): HEAD patched 1/1 141fps 138fps 1/4 315fps 395fps Change-Id: I4cc115786c3139000fc14c49a7290e289cfd6c42
This commit is contained in:
parent
ca8154741f
commit
440872bb42
4 changed files with 60 additions and 103 deletions
|
|
@ -175,19 +175,6 @@ static void lcd_v1_set_gram_area(int x_start, int y_start,
|
||||||
LCDC_CTRL &= ~RGB24B;
|
LCDC_CTRL &= ~RGB24B;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcd_v1_update_rect(int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
int px = x, py = y;
|
|
||||||
int pxmax = x + width, pymax = y + height;
|
|
||||||
|
|
||||||
lcd_v1_set_gram_area(x, y, pxmax-1, pymax-1);
|
|
||||||
|
|
||||||
for (py=y; py<pymax; py++)
|
|
||||||
for (px=x; px<pxmax; px++)
|
|
||||||
LCD_DATA = (*FBADDR(px, py));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HM60X
|
#ifdef HM60X
|
||||||
|
|
||||||
enum lcd_type_t lcd_type;
|
enum lcd_type_t lcd_type;
|
||||||
|
|
@ -312,19 +299,6 @@ static void lcd_v2_set_gram_area(int x_start, int y_start,
|
||||||
LCDC_CTRL &= ~RGB24B;
|
LCDC_CTRL &= ~RGB24B;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcd_v2_update_rect(int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
int px = x, py = y;
|
|
||||||
int pxmax = x + width, pymax = y + height;
|
|
||||||
|
|
||||||
lcd_v2_set_gram_area(x, y, pxmax-1, pymax-1);
|
|
||||||
|
|
||||||
for (py=y; py<pymax; py++)
|
|
||||||
for (px=x; px<pxmax; px++)
|
|
||||||
LCD_DATA = (*FBADDR(px, py));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcd_display_init(void)
|
void lcd_display_init(void)
|
||||||
{
|
{
|
||||||
reset_lcd();
|
reset_lcd();
|
||||||
|
|
@ -352,16 +326,6 @@ void lcd_set_gram_area(int x_start, int y_start,
|
||||||
lcd_v2_set_gram_area(x_start, y_start, x_end, y_end);
|
lcd_v2_set_gram_area(x_start, y_start, x_end, y_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_update_rect(int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
if (lcd_type == LCD_V1)
|
|
||||||
lcd_v1_update_rect(x, y, width, height);
|
|
||||||
else
|
|
||||||
lcd_v2_update_rect(x, y, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#else /* HM801 */
|
#else /* HM801 */
|
||||||
|
|
||||||
void lcd_display_init(void)
|
void lcd_display_init(void)
|
||||||
|
|
@ -380,16 +344,8 @@ void lcd_set_gram_area(int x_start, int y_start,
|
||||||
{
|
{
|
||||||
lcd_v1_set_gram_area(x_start, y_start, x_end, y_end);
|
lcd_v1_set_gram_area(x_start, y_start, x_end, y_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_update_rect(int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
lcd_v1_update_rect(x, y, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool lcd_active()
|
bool lcd_active()
|
||||||
{
|
{
|
||||||
return display_on;
|
return display_on;
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,33 @@ static uint32_t lcd_data_transform(uint32_t data)
|
||||||
return (r | g | b);
|
return (r | g | b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lcdctrl_buff_setup(int width, int height)
|
||||||
|
{
|
||||||
|
/* Warning: datasheet addresses and OF addresses
|
||||||
|
* don't match for HOR_ACT and VERT_ACT
|
||||||
|
*/
|
||||||
|
HOR_ACT = width + 3; /* define horizonatal active region */
|
||||||
|
VERT_ACT = height; /* define vertical active region */
|
||||||
|
|
||||||
|
/* This lines define layout of data in lcdif internal buffer
|
||||||
|
* LINEx_UVADDR = LINEx_YADDR + 1
|
||||||
|
* buffer is organized as 2048 x 32bit
|
||||||
|
* we use RGB565 (16 bits per pixel) so we pack 2 pixels
|
||||||
|
* in every lcdbuffer mem cell
|
||||||
|
*/
|
||||||
|
width = width >> 1;
|
||||||
|
|
||||||
|
LINE0_YADDR = 0;
|
||||||
|
LINE1_YADDR = 1 * width;
|
||||||
|
LINE2_YADDR = 2 * width;
|
||||||
|
LINE3_YADDR = 3 * width;
|
||||||
|
|
||||||
|
LINE0_UVADDR = LINE0_YADDR + 1;
|
||||||
|
LINE1_UVADDR = LINE1_YADDR + 1;
|
||||||
|
LINE2_UVADDR = LINE2_YADDR + 1;
|
||||||
|
LINE3_UVADDR = LINE3_YADDR + 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void lcdctrl_init(void)
|
static void lcdctrl_init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -80,31 +107,11 @@ static void lcdctrl_init(void)
|
||||||
LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B;
|
LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B;
|
||||||
MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS;
|
MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS;
|
||||||
|
|
||||||
/* Warning: datasheet addresses and OF addresses
|
|
||||||
* don't match for HOR_ACT and VERT_ACT
|
|
||||||
*/
|
|
||||||
HOR_ACT = LCD_WIDTH + 3; /* define horizonatal active region */
|
|
||||||
VERT_ACT = LCD_HEIGHT; /* define vertical active region */
|
|
||||||
VERT_PERIOD = (1<<7)|(1<<5)|1; /* CSn/WEn/RDn signal timings */
|
VERT_PERIOD = (1<<7)|(1<<5)|1; /* CSn/WEn/RDn signal timings */
|
||||||
|
|
||||||
lcd_display_init();
|
lcd_display_init();
|
||||||
lcdctrl_bypass(0);
|
lcdctrl_bypass(0);
|
||||||
|
lcdctrl_buff_setup(LCD_WIDTH, LCD_HEIGHT);
|
||||||
/* This lines define layout of data in lcdif internal buffer
|
|
||||||
* LINEx_UVADDR = LINEx_YADDR + 1
|
|
||||||
* buffer is organized as 2048 x 32bit
|
|
||||||
* we use RGB565 (16 bits per pixel) so we pack 2 pixels
|
|
||||||
* in every lcdbuffer mem cell
|
|
||||||
*/
|
|
||||||
LINE0_YADDR = 0;
|
|
||||||
LINE1_YADDR = 1 * LCD_WIDTH/2;
|
|
||||||
LINE2_YADDR = 2 * LCD_WIDTH/2;
|
|
||||||
LINE3_YADDR = 3 * LCD_WIDTH/2;
|
|
||||||
|
|
||||||
LINE0_UVADDR = 1;
|
|
||||||
LINE1_UVADDR = (1 * LCD_WIDTH/2) + 1;
|
|
||||||
LINE2_UVADDR = (2 * LCD_WIDTH/2) + 1;
|
|
||||||
LINE3_UVADDR = (3 * LCD_WIDTH/2) + 1;
|
|
||||||
|
|
||||||
LCDC_INTR_MASK = INTR_MASK_EVENLINE;
|
LCDC_INTR_MASK = INTR_MASK_EVENLINE;
|
||||||
|
|
||||||
|
|
@ -185,18 +192,20 @@ static void dwdma_start(uint8_t ch, struct llp_t *llp, uint8_t handshake)
|
||||||
DWDMA_DMA_CHEN = (0x101<<ch);
|
DWDMA_DMA_CHEN = (0x101<<ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_llp(void)
|
static void create_llp(int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* build LLPs */
|
width = width>>1;
|
||||||
for (i=0; i<LCD_HEIGHT; i++)
|
|
||||||
llp_setup((void *)FBADDR(0,i),
|
|
||||||
(void*)(LCD_BUFF+((i%4)*4*LCD_WIDTH/2)),
|
|
||||||
&(scr_llp[i]),
|
|
||||||
LCD_WIDTH/2);
|
|
||||||
|
|
||||||
llp_end(&scr_llp[LCD_HEIGHT-1]);
|
/* build LLPs */
|
||||||
|
for (i=0; i<height; i++)
|
||||||
|
llp_setup((void *)FBADDR(x,y+i),
|
||||||
|
(void*)(LCD_BUFF+((i%4)*4*width)),
|
||||||
|
&(scr_llp[i]),
|
||||||
|
width);
|
||||||
|
|
||||||
|
llp_end(&scr_llp[height-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Public functions */
|
/* Public functions */
|
||||||
|
|
@ -244,15 +253,30 @@ void lcd_init_device(void)
|
||||||
lcdctrl_init(); /* basic lcdc module configuration */
|
lcdctrl_init(); /* basic lcdc module configuration */
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_update()
|
void lcd_update_rect(int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
lcd_set_gram_area(0, 0, LCD_WIDTH-1, LCD_HEIGHT-1);
|
int x_end, y_end, x_align, y_align;
|
||||||
|
|
||||||
|
/* min alowed transfer seems to be 4x4 pixels */
|
||||||
|
x_align = x & 3;
|
||||||
|
y_align = y & 3;
|
||||||
|
x = x - x_align;
|
||||||
|
y = y - y_align;
|
||||||
|
width = (width + x_align + 3) & ~3;
|
||||||
|
height = (height + y_align + 3) & ~3;
|
||||||
|
x_end = x + width - 1;
|
||||||
|
y_end = y + height - 1;
|
||||||
|
|
||||||
|
lcd_set_gram_area(x, y, x_end, y_end);
|
||||||
|
create_llp(x, y, width, height);
|
||||||
lcdctrl_bypass(0);
|
lcdctrl_bypass(0);
|
||||||
|
|
||||||
|
/* whole framebuffer for now */
|
||||||
commit_discard_dcache_range(FBADDR(0,0), 2*LCD_WIDTH*LCD_HEIGHT);
|
commit_discard_dcache_range(FBADDR(0,0), 2*LCD_WIDTH*LCD_HEIGHT);
|
||||||
|
|
||||||
while (!(LCDC_STA & LCDC_MCU_IDLE));
|
while (!(LCDC_STA & LCDC_MCU_IDLE));
|
||||||
|
|
||||||
|
lcdctrl_buff_setup(width, height);
|
||||||
dwdma_start(0, scr_llp, 6);
|
dwdma_start(0, scr_llp, 6);
|
||||||
udelay(10);
|
udelay(10);
|
||||||
|
|
||||||
|
|
@ -262,3 +286,8 @@ void lcd_update()
|
||||||
/* Wait for DMA transfer to finish */
|
/* Wait for DMA transfer to finish */
|
||||||
while (DWDMA_CTL_L(0) & (1<<27));
|
while (DWDMA_CTL_L(0) & (1<<27));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lcd_update()
|
||||||
|
{
|
||||||
|
lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,20 +172,6 @@ void lcd_set_gram_area(int x_start, int y_start,
|
||||||
LCDC_CTRL &= ~RGB24B;
|
LCDC_CTRL &= ~RGB24B;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_update_rect(int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
int px = x, py = y;
|
|
||||||
int pxmax = x + width, pymax = y + height;
|
|
||||||
|
|
||||||
lcd_set_gram_area(x, y, pxmax-1, pymax-1);
|
|
||||||
|
|
||||||
for (py = y; py < pymax; py++)
|
|
||||||
for (px = x; px < pxmax; px++)
|
|
||||||
LCD_DATA = (*FBADDR(px, py));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool lcd_active()
|
bool lcd_active()
|
||||||
{
|
{
|
||||||
return display_on;
|
return display_on;
|
||||||
|
|
|
||||||
|
|
@ -179,20 +179,6 @@ void lcd_set_gram_area(int x_start, int y_start,
|
||||||
LCDC_CTRL &= ~RGB24B;
|
LCDC_CTRL &= ~RGB24B;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_update_rect(int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
int px = x, py = y;
|
|
||||||
int pxmax = x + width, pymax = y + height;
|
|
||||||
|
|
||||||
lcd_set_gram_area(x, y, pxmax-1, pymax-1);
|
|
||||||
|
|
||||||
for (py=y; py<pymax; py++)
|
|
||||||
{
|
|
||||||
for (px=x; px<pxmax; px++)
|
|
||||||
LCD_DATA = *FBADDR(px,py);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Blit a YUV bitmap directly to the LCD
|
/* Blit a YUV bitmap directly to the LCD
|
||||||
* provided by generic fallback in lcd-16bit-common.c
|
* provided by generic fallback in lcd-16bit-common.c
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue