summaryrefslogtreecommitdiff
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
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
-rw-r--r--firmware/target/arm/rk27xx/lcd-hifiman.c44
-rw-r--r--firmware/target/arm/rk27xx/lcdif-rk27xx.c87
-rw-r--r--firmware/target/arm/rk27xx/ma/lcd-ma.c14
-rw-r--r--firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c14
4 files changed, 58 insertions, 101 deletions
diff --git a/firmware/target/arm/rk27xx/lcd-hifiman.c b/firmware/target/arm/rk27xx/lcd-hifiman.c
index 1adc6e36ed..bde1d3546f 100644
--- a/firmware/target/arm/rk27xx/lcd-hifiman.c
+++ b/firmware/target/arm/rk27xx/lcd-hifiman.c
@@ -175,19 +175,6 @@ static void lcd_v1_set_gram_area(int x_start, int y_start,
175 LCDC_CTRL &= ~RGB24B; 175 LCDC_CTRL &= ~RGB24B;
176} 176}
177 177
178static void lcd_v1_update_rect(int x, int y, int width, int height)
179{
180 int px = x, py = y;
181 int pxmax = x + width, pymax = y + height;
182
183 lcd_v1_set_gram_area(x, y, pxmax-1, pymax-1);
184
185 for (py=y; py<pymax; py++)
186 for (px=x; px<pxmax; px++)
187 LCD_DATA = (*FBADDR(px, py));
188}
189
190
191#ifdef HM60X 178#ifdef HM60X
192 179
193enum lcd_type_t lcd_type; 180enum lcd_type_t lcd_type;
@@ -312,19 +299,6 @@ static void lcd_v2_set_gram_area(int x_start, int y_start,
312 LCDC_CTRL &= ~RGB24B; 299 LCDC_CTRL &= ~RGB24B;
313} 300}
314 301
315static void lcd_v2_update_rect(int x, int y, int width, int height)
316{
317 int px = x, py = y;
318 int pxmax = x + width, pymax = y + height;
319
320 lcd_v2_set_gram_area(x, y, pxmax-1, pymax-1);
321
322 for (py=y; py<pymax; py++)
323 for (px=x; px<pxmax; px++)
324 LCD_DATA = (*FBADDR(px, py));
325
326}
327
328void lcd_display_init(void) 302void lcd_display_init(void)
329{ 303{
330 reset_lcd(); 304 reset_lcd();
@@ -352,16 +326,6 @@ void lcd_set_gram_area(int x_start, int y_start,
352 lcd_v2_set_gram_area(x_start, y_start, x_end, y_end); 326 lcd_v2_set_gram_area(x_start, y_start, x_end, y_end);
353} 327}
354 328
355void lcd_update_rect(int x, int y, int width, int height)
356{
357 if (lcd_type == LCD_V1)
358 lcd_v1_update_rect(x, y, width, height);
359 else
360 lcd_v2_update_rect(x, y, width, height);
361}
362
363
364
365#else /* HM801 */ 329#else /* HM801 */
366 330
367void lcd_display_init(void) 331void lcd_display_init(void)
@@ -380,16 +344,8 @@ void lcd_set_gram_area(int x_start, int y_start,
380{ 344{
381 lcd_v1_set_gram_area(x_start, y_start, x_end, y_end); 345 lcd_v1_set_gram_area(x_start, y_start, x_end, y_end);
382} 346}
383
384void lcd_update_rect(int x, int y, int width, int height)
385{
386 lcd_v1_update_rect(x, y, width, height);
387}
388
389#endif 347#endif
390 348
391
392
393bool lcd_active() 349bool lcd_active()
394{ 350{
395 return display_on; 351 return display_on;
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}
diff --git a/firmware/target/arm/rk27xx/ma/lcd-ma.c b/firmware/target/arm/rk27xx/ma/lcd-ma.c
index 3c3d9fb097..a35f13ba3a 100644
--- a/firmware/target/arm/rk27xx/ma/lcd-ma.c
+++ b/firmware/target/arm/rk27xx/ma/lcd-ma.c
@@ -172,20 +172,6 @@ void lcd_set_gram_area(int x_start, int y_start,
172 LCDC_CTRL &= ~RGB24B; 172 LCDC_CTRL &= ~RGB24B;
173} 173}
174 174
175void lcd_update_rect(int x, int y, int width, int height)
176{
177 int px = x, py = y;
178 int pxmax = x + width, pymax = y + height;
179
180 lcd_set_gram_area(x, y, pxmax-1, pymax-1);
181
182 for (py = y; py < pymax; py++)
183 for (px = x; px < pxmax; px++)
184 LCD_DATA = (*FBADDR(px, py));
185
186}
187
188
189bool lcd_active() 175bool lcd_active()
190{ 176{
191 return display_on; 177 return display_on;
diff --git a/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c b/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c
index 75911614ab..b40f2860d7 100644
--- a/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c
+++ b/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c
@@ -179,20 +179,6 @@ void lcd_set_gram_area(int x_start, int y_start,
179 LCDC_CTRL &= ~RGB24B; 179 LCDC_CTRL &= ~RGB24B;
180} 180}
181 181
182void lcd_update_rect(int x, int y, int width, int height)
183{
184 int px = x, py = y;
185 int pxmax = x + width, pymax = y + height;
186
187 lcd_set_gram_area(x, y, pxmax-1, pymax-1);
188
189 for (py=y; py<pymax; py++)
190 {
191 for (px=x; px<pxmax; px++)
192 LCD_DATA = *FBADDR(px,py);
193 }
194}
195
196/* Blit a YUV bitmap directly to the LCD 182/* Blit a YUV bitmap directly to the LCD
197 * provided by generic fallback in lcd-16bit-common.c 183 * provided by generic fallback in lcd-16bit-common.c
198 */ 184 */