diff options
Diffstat (limited to 'firmware/target/arm/tcc780x')
-rw-r--r-- | firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c | 139 |
1 files changed, 117 insertions, 22 deletions
diff --git a/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c b/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c index 7514f93886..097dec31d3 100644 --- a/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c +++ b/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c | |||
@@ -52,6 +52,10 @@ | |||
52 | /* Power and display status */ | 52 | /* Power and display status */ |
53 | static bool display_on = false; /* Is the display turned on? */ | 53 | static bool display_on = false; /* Is the display turned on? */ |
54 | 54 | ||
55 | static unsigned lcd_yuv_options = 0; | ||
56 | |||
57 | /* Framebuffer copy as seen by the hardware */ | ||
58 | fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]; | ||
55 | 59 | ||
56 | int lcd_default_contrast(void) | 60 | int lcd_default_contrast(void) |
57 | { | 61 | { |
@@ -60,8 +64,8 @@ int lcd_default_contrast(void) | |||
60 | 64 | ||
61 | void lcd_set_contrast(int val) | 65 | void lcd_set_contrast(int val) |
62 | { | 66 | { |
63 | /* iirc there is an ltv250qv command to do this */ | 67 | /* TODO: This won't be implemented until the S6F2002 controller |
64 | #warning function not implemented | 68 | is better understood (nb: registers 16-23 control gamma). */ |
65 | (void)val; | 69 | (void)val; |
66 | } | 70 | } |
67 | 71 | ||
@@ -265,7 +269,7 @@ void lcd_init_device(void) | |||
265 | LCDC_VTIME1 = LCDC_VTIME3 = (0<<16) | 239; | 269 | LCDC_VTIME1 = LCDC_VTIME3 = (0<<16) | 239; |
266 | LCDC_VTIME2 = LCDC_VTIME4 = (1<<16) | 3; | 270 | LCDC_VTIME2 = LCDC_VTIME4 = (1<<16) | 3; |
267 | 271 | ||
268 | LCDC_I1BASE = (unsigned int)lcd_framebuffer; /* dirty, dirty hack */ | 272 | LCDC_I1BASE = (unsigned int)lcd_driver_framebuffer; |
269 | LCDC_I1SIZE = (LCD_HEIGHT<<16) | LCD_WIDTH; /* image 1 size */ | 273 | LCDC_I1SIZE = (LCD_HEIGHT<<16) | LCD_WIDTH; /* image 1 size */ |
270 | LCDC_I1POS = (0<<16) | 0; /* position */ | 274 | LCDC_I1POS = (0<<16) | 0; /* position */ |
271 | LCDC_I1OFF = 0; /* address offset */ | 275 | LCDC_I1OFF = 0; /* address offset */ |
@@ -295,42 +299,81 @@ void lcd_init_device(void) | |||
295 | /*** Update functions ***/ | 299 | /*** Update functions ***/ |
296 | 300 | ||
297 | 301 | ||
302 | /* Copies a rectangle from one framebuffer to another. Can be used in | ||
303 | single transfer mode with width = num pixels, and height = 1 which | ||
304 | allows a full-width rectangle to be copied more efficiently. */ | ||
305 | extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, | ||
306 | int width, int height); | ||
307 | |||
298 | /* Update the display. | 308 | /* Update the display. |
299 | This must be called after all other LCD functions that change the display. */ | 309 | This must be called after all other LCD functions that change the display. */ |
300 | void lcd_update(void) ICODE_ATTR; | 310 | void lcd_update(void) ICODE_ATTR; |
301 | void lcd_update(void) | 311 | void lcd_update(void) |
302 | { | 312 | { |
303 | #warning function not implemented | 313 | if (!display_on) |
304 | /* currently lcd_framebuffer is accessed directly by the hardware */ | 314 | return; |
315 | |||
316 | lcd_copy_buffer_rect(&lcd_driver_framebuffer[0][0], | ||
317 | &lcd_framebuffer[0][0], LCD_WIDTH*LCD_HEIGHT, 1); | ||
305 | } | 318 | } |
306 | 319 | ||
307 | /* Update a fraction of the display. */ | 320 | /* Update a fraction of the display. */ |
308 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; | 321 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; |
309 | void lcd_update_rect(int x, int y, int width, int height) | 322 | void lcd_update_rect(int x, int y, int width, int height) |
310 | { | 323 | { |
311 | #warning function not implemented | 324 | fb_data *dst, *src; |
312 | (void)x; | 325 | |
313 | (void)y; | 326 | if (!display_on) |
314 | (void)width; | 327 | return; |
315 | (void)height; | 328 | |
329 | if (x + width > LCD_WIDTH) | ||
330 | width = LCD_WIDTH - x; /* Clip right */ | ||
331 | if (x < 0) | ||
332 | width += x, x = 0; /* Clip left */ | ||
333 | if (width <= 0) | ||
334 | return; /* nothing left to do */ | ||
335 | |||
336 | if (y + height > LCD_HEIGHT) | ||
337 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
338 | if (y < 0) | ||
339 | height += y, y = 0; /* Clip top */ | ||
340 | if (height <= 0) | ||
341 | return; /* nothing left to do */ | ||
342 | |||
343 | /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer | ||
344 | * and lcd_framebuffer */ | ||
345 | dst = &lcd_driver_framebuffer[y][x]; | ||
346 | src = &lcd_framebuffer[y][x]; | ||
347 | |||
348 | /* Copy part of the Rockbox framebuffer to the second framebuffer */ | ||
349 | if (width < LCD_WIDTH) | ||
350 | { | ||
351 | /* Not full width - do line-by-line */ | ||
352 | lcd_copy_buffer_rect(dst, src, width, height); | ||
353 | } | ||
354 | else | ||
355 | { | ||
356 | /* Full width - copy as one line */ | ||
357 | lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); | ||
358 | } | ||
316 | } | 359 | } |
317 | 360 | ||
318 | void lcd_set_flip(bool yesno) | 361 | void lcd_set_flip(bool yesno) |
319 | { | 362 | { |
320 | #warning function not implemented | 363 | // TODO |
321 | (void)yesno; | 364 | (void)yesno; |
322 | } | 365 | } |
323 | 366 | ||
324 | void lcd_set_invert_display(bool yesno) | 367 | void lcd_set_invert_display(bool yesno) |
325 | { | 368 | { |
326 | #warning function not implemented | 369 | // TODO |
327 | (void)yesno; | 370 | (void)yesno; |
328 | } | 371 | } |
329 | 372 | ||
330 | void lcd_blit(const fb_data* data, int bx, int y, int bwidth, | 373 | void lcd_blit(const fb_data* data, int bx, int y, int bwidth, |
331 | int height, int stride) | 374 | int height, int stride) |
332 | { | 375 | { |
333 | #warning function not implemented | 376 | // TODO |
334 | (void)data; | 377 | (void)data; |
335 | (void)bx; | 378 | (void)bx; |
336 | (void)y; | 379 | (void)y; |
@@ -339,17 +382,69 @@ void lcd_blit(const fb_data* data, int bx, int y, int bwidth, | |||
339 | (void)stride; | 382 | (void)stride; |
340 | } | 383 | } |
341 | 384 | ||
385 | void lcd_yuv_set_options(unsigned options) | ||
386 | { | ||
387 | lcd_yuv_options = options; | ||
388 | } | ||
389 | |||
390 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
391 | extern void lcd_write_yuv420_lines(fb_data *dst, | ||
392 | unsigned char const * const src[3], | ||
393 | int width, | ||
394 | int stride); | ||
395 | extern void lcd_write_yuv420_lines_odither(fb_data *dst, | ||
396 | unsigned char const * const src[3], | ||
397 | int width, | ||
398 | int stride, | ||
399 | int x_screen, /* To align dither pattern */ | ||
400 | int y_screen); | ||
401 | |||
402 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
342 | void lcd_yuv_blit(unsigned char * const src[3], | 403 | void lcd_yuv_blit(unsigned char * const src[3], |
343 | int src_x, int src_y, int stride, | 404 | int src_x, int src_y, int stride, |
344 | int x, int y, int width, int height) | 405 | int x, int y, int width, int height) |
345 | { | 406 | { |
346 | #warning function not implemented | 407 | unsigned char const * yuv_src[3]; |
347 | (void)src; | 408 | off_t z; |
348 | (void)src_x; | 409 | |
349 | (void)src_y; | 410 | if (!display_on) |
350 | (void)stride; | 411 | return; |
351 | (void)x; | 412 | |
352 | (void)y; | 413 | /* Sorry, but width and height must be >= 2 or else */ |
353 | (void)width; | 414 | width &= ~1; |
354 | (void)height; | 415 | height >>= 1; |
416 | |||
417 | y = LCD_WIDTH - 1 - y; | ||
418 | fb_data *dst = &lcd_driver_framebuffer[x][y]; | ||
419 | |||
420 | z = stride*src_y; | ||
421 | yuv_src[0] = src[0] + z + src_x; | ||
422 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
423 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
424 | |||
425 | if (lcd_yuv_options & LCD_YUV_DITHER) | ||
426 | { | ||
427 | do | ||
428 | { | ||
429 | lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x); | ||
430 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
431 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
432 | yuv_src[2] += stride >> 1; | ||
433 | dst -= 2; | ||
434 | y -= 2; | ||
435 | } | ||
436 | while (--height > 0); | ||
437 | } | ||
438 | else | ||
439 | { | ||
440 | do | ||
441 | { | ||
442 | lcd_write_yuv420_lines(dst, yuv_src, width, stride); | ||
443 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
444 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
445 | yuv_src[2] += stride >> 1; | ||
446 | dst -= 2; | ||
447 | } | ||
448 | while (--height > 0); | ||
449 | } | ||
355 | } | 450 | } |