summaryrefslogtreecommitdiff
path: root/firmware/target/arm/rk27xx/lcdif-rk27xx.c
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2013-05-11 12:55:23 +0200
committerMarcin Bukat <marcin.bukat@gmail.com>2013-05-11 12:55:23 +0200
commit440872bb4277c882ece20339fa4b2525c1c4ed2a (patch)
tree3a64dfdb95e3efe6859b02c0881a8ef5aa53970d /firmware/target/arm/rk27xx/lcdif-rk27xx.c
parentca8154741fd01e4b11461ce522da7d5e30a12d6e (diff)
downloadrockbox-440872bb4277c882ece20339fa4b2525c1c4ed2a.tar.gz
rockbox-440872bb4277c882ece20339fa4b2525c1c4ed2a.zip
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
Diffstat (limited to 'firmware/target/arm/rk27xx/lcdif-rk27xx.c')
-rw-r--r--firmware/target/arm/rk27xx/lcdif-rk27xx.c87
1 files changed, 58 insertions, 29 deletions
diff --git a/firmware/target/arm/rk27xx/lcdif-rk27xx.c b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
index 560ab4708e..e6af0d978a 100644
--- a/firmware/target/arm/rk27xx/lcdif-rk27xx.c
+++ b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
@@ -68,6 +68,33 @@ static uint32_t lcd_data_transform(uint32_t data)
68 return (r | g | b); 68 return (r | g | b);
69} 69}
70 70
71static void lcdctrl_buff_setup(int width, int height)
72{
73 /* Warning: datasheet addresses and OF addresses
74 * don't match for HOR_ACT and VERT_ACT
75 */
76 HOR_ACT = width + 3; /* define horizonatal active region */
77 VERT_ACT = height; /* define vertical active region */
78
79 /* This lines define layout of data in lcdif internal buffer
80 * LINEx_UVADDR = LINEx_YADDR + 1
81 * buffer is organized as 2048 x 32bit
82 * we use RGB565 (16 bits per pixel) so we pack 2 pixels
83 * in every lcdbuffer mem cell
84 */
85 width = width >> 1;
86
87 LINE0_YADDR = 0;
88 LINE1_YADDR = 1 * width;
89 LINE2_YADDR = 2 * width;
90 LINE3_YADDR = 3 * width;
91
92 LINE0_UVADDR = LINE0_YADDR + 1;
93 LINE1_UVADDR = LINE1_YADDR + 1;
94 LINE2_UVADDR = LINE2_YADDR + 1;
95 LINE3_UVADDR = LINE3_YADDR + 1;
96}
97
71static void lcdctrl_init(void) 98static void lcdctrl_init(void)
72{ 99{
73 int i; 100 int i;
@@ -80,31 +107,11 @@ static void lcdctrl_init(void)
80 LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B; 107 LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B;
81 MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS; 108 MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS;
82 109
83 /* Warning: datasheet addresses and OF addresses
84 * don't match for HOR_ACT and VERT_ACT
85 */
86 HOR_ACT = LCD_WIDTH + 3; /* define horizonatal active region */
87 VERT_ACT = LCD_HEIGHT; /* define vertical active region */
88 VERT_PERIOD = (1<<7)|(1<<5)|1; /* CSn/WEn/RDn signal timings */ 110 VERT_PERIOD = (1<<7)|(1<<5)|1; /* CSn/WEn/RDn signal timings */
89 111
90 lcd_display_init(); 112 lcd_display_init();
91 lcdctrl_bypass(0); 113 lcdctrl_bypass(0);
92 114 lcdctrl_buff_setup(LCD_WIDTH, LCD_HEIGHT);
93 /* This lines define layout of data in lcdif internal buffer
94 * LINEx_UVADDR = LINEx_YADDR + 1
95 * buffer is organized as 2048 x 32bit
96 * we use RGB565 (16 bits per pixel) so we pack 2 pixels
97 * in every lcdbuffer mem cell
98 */
99 LINE0_YADDR = 0;
100 LINE1_YADDR = 1 * LCD_WIDTH/2;
101 LINE2_YADDR = 2 * LCD_WIDTH/2;
102 LINE3_YADDR = 3 * LCD_WIDTH/2;
103
104 LINE0_UVADDR = 1;
105 LINE1_UVADDR = (1 * LCD_WIDTH/2) + 1;
106 LINE2_UVADDR = (2 * LCD_WIDTH/2) + 1;
107 LINE3_UVADDR = (3 * LCD_WIDTH/2) + 1;
108 115
109 LCDC_INTR_MASK = INTR_MASK_EVENLINE; 116 LCDC_INTR_MASK = INTR_MASK_EVENLINE;
110 117
@@ -185,18 +192,20 @@ static void dwdma_start(uint8_t ch, struct llp_t *llp, uint8_t handshake)
185 DWDMA_DMA_CHEN = (0x101<<ch); 192 DWDMA_DMA_CHEN = (0x101<<ch);
186} 193}
187 194
188static void create_llp(void) 195static void create_llp(int x, int y, int width, int height)
189{ 196{
190 int i; 197 int i;
191 198
199 width = width>>1;
200
192 /* build LLPs */ 201 /* build LLPs */
193 for (i=0; i<LCD_HEIGHT; i++) 202 for (i=0; i<height; i++)
194 llp_setup((void *)FBADDR(0,i), 203 llp_setup((void *)FBADDR(x,y+i),
195 (void*)(LCD_BUFF+((i%4)*4*LCD_WIDTH/2)), 204 (void*)(LCD_BUFF+((i%4)*4*width)),
196 &(scr_llp[i]), 205 &(scr_llp[i]),
197 LCD_WIDTH/2); 206 width);
198 207
199 llp_end(&scr_llp[LCD_HEIGHT-1]); 208 llp_end(&scr_llp[height-1]);
200} 209}
201 210
202/* Public functions */ 211/* Public functions */
@@ -244,15 +253,30 @@ void lcd_init_device(void)
244 lcdctrl_init(); /* basic lcdc module configuration */ 253 lcdctrl_init(); /* basic lcdc module configuration */
245} 254}
246 255
247void lcd_update() 256void lcd_update_rect(int x, int y, int width, int height)
248{ 257{
249 lcd_set_gram_area(0, 0, LCD_WIDTH-1, LCD_HEIGHT-1); 258 int x_end, y_end, x_align, y_align;
259
260 /* min alowed transfer seems to be 4x4 pixels */
261 x_align = x & 3;
262 y_align = y & 3;
263 x = x - x_align;
264 y = y - y_align;
265 width = (width + x_align + 3) & ~3;
266 height = (height + y_align + 3) & ~3;
267 x_end = x + width - 1;
268 y_end = y + height - 1;
269
270 lcd_set_gram_area(x, y, x_end, y_end);
271 create_llp(x, y, width, height);
250 lcdctrl_bypass(0); 272 lcdctrl_bypass(0);
251 273
274 /* whole framebuffer for now */
252 commit_discard_dcache_range(FBADDR(0,0), 2*LCD_WIDTH*LCD_HEIGHT); 275 commit_discard_dcache_range(FBADDR(0,0), 2*LCD_WIDTH*LCD_HEIGHT);
253 276
254 while (!(LCDC_STA & LCDC_MCU_IDLE)); 277 while (!(LCDC_STA & LCDC_MCU_IDLE));
255 278
279 lcdctrl_buff_setup(width, height);
256 dwdma_start(0, scr_llp, 6); 280 dwdma_start(0, scr_llp, 6);
257 udelay(10); 281 udelay(10);
258 282
@@ -262,3 +286,8 @@ void lcd_update()
262 /* Wait for DMA transfer to finish */ 286 /* Wait for DMA transfer to finish */
263 while (DWDMA_CTL_L(0) & (1<<27)); 287 while (DWDMA_CTL_L(0) & (1<<27));
264} 288}
289
290void lcd_update()
291{
292 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
293}