diff options
Diffstat (limited to 'firmware/target/arm/sandisk/sansa-e200/lcd-e200.c')
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | 152 |
1 files changed, 11 insertions, 141 deletions
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c index 0f9ca9b046..87765802c3 100644 --- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | |||
@@ -22,17 +22,15 @@ | |||
22 | * KIND, either express or implied. | 22 | * KIND, either express or implied. |
23 | * | 23 | * |
24 | ****************************************************************************/ | 24 | ****************************************************************************/ |
25 | #include <sys/types.h> /* off_t */ | 25 | #include "config.h" |
26 | #include <string.h> | ||
27 | #include "cpu.h" | ||
28 | #include "system.h" | 26 | #include "system.h" |
29 | #include "backlight-target.h" | ||
30 | #include "lcd.h" | 27 | #include "lcd.h" |
28 | #include "lcd-target.h" | ||
29 | |||
30 | extern void lcd_set_active(bool active); | ||
31 | 31 | ||
32 | /* Power and display status */ | 32 | /* Power and display status */ |
33 | static bool power_on = false; /* Is the power turned on? */ | 33 | static bool power_on = false; /* Is the power turned on? */ |
34 | static bool display_on SHAREDBSS_ATTR = false; /* Is the display turned on? */ | ||
35 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; | ||
36 | 34 | ||
37 | /* Reverse Flag */ | 35 | /* Reverse Flag */ |
38 | #define R_DISP_CONTROL_NORMAL 0x0004 | 36 | #define R_DISP_CONTROL_NORMAL 0x0004 |
@@ -112,7 +110,7 @@ static unsigned short r_drv_output_control = R_DRV_OUTPUT_CONTROL_NORMAL; | |||
112 | /* We don't know how to receive a DMA finished signal from the LCD controller. | 110 | /* We don't know how to receive a DMA finished signal from the LCD controller. |
113 | * To avoid problems with flickering, we double-buffer the framebuffer. | 111 | * To avoid problems with flickering, we double-buffer the framebuffer. |
114 | * Align as in lcd-16bit.c and not cached. */ | 112 | * Align as in lcd-16bit.c and not cached. */ |
115 | static fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] | 113 | fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] |
116 | __attribute__((aligned(16))) NOCACHEBSS_ATTR; | 114 | __attribute__((aligned(16))) NOCACHEBSS_ATTR; |
117 | 115 | ||
118 | #ifdef BOOTLOADER | 116 | #ifdef BOOTLOADER |
@@ -310,21 +308,16 @@ static void lcd_display_on(void) | |||
310 | lcd_send_msg(0x70, R_RAM_WRITE_DATA); | 308 | lcd_send_msg(0x70, R_RAM_WRITE_DATA); |
311 | 309 | ||
312 | /* tell that we're on now */ | 310 | /* tell that we're on now */ |
313 | display_on = true; | 311 | lcd_set_active(true); |
314 | } | 312 | } |
315 | 313 | ||
316 | 314 | ||
317 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) | 315 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) |
318 | bool lcd_active(void) | ||
319 | { | ||
320 | return display_on; | ||
321 | } | ||
322 | |||
323 | /* Turn off visible display operations */ | 316 | /* Turn off visible display operations */ |
324 | static void lcd_display_off(void) | 317 | static void lcd_display_off(void) |
325 | { | 318 | { |
326 | /* block drawing operations and changing of first */ | 319 | /* block drawing operations and changing of first */ |
327 | display_on = false; | 320 | lcd_set_active(false); |
328 | 321 | ||
329 | /* NO2-0=01, SDT1-0=00, EQ1-0=00, DIV1-0=00, RTN3-0=0000 */ | 322 | /* NO2-0=01, SDT1-0=00, EQ1-0=00, DIV1-0=00, RTN3-0=0000 */ |
330 | lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x4000); | 323 | lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x4000); |
@@ -428,7 +421,7 @@ void lcd_init_device(void) | |||
428 | LCD_FB_BASE_REG = (long)lcd_driver_framebuffer; | 421 | LCD_FB_BASE_REG = (long)lcd_driver_framebuffer; |
429 | 422 | ||
430 | power_on = true; | 423 | power_on = true; |
431 | display_on = true; | 424 | lcd_set_active(true); |
432 | 425 | ||
433 | lcd_set_invert_display(false); | 426 | lcd_set_invert_display(false); |
434 | lcd_set_flip(false); | 427 | lcd_set_flip(false); |
@@ -440,7 +433,7 @@ void lcd_init_device(void) | |||
440 | #if defined(HAVE_LCD_ENABLE) | 433 | #if defined(HAVE_LCD_ENABLE) |
441 | void lcd_enable(bool on) | 434 | void lcd_enable(bool on) |
442 | { | 435 | { |
443 | if (on == display_on) | 436 | if (on == lcd_active()) |
444 | return; | 437 | return; |
445 | 438 | ||
446 | if (on) | 439 | if (on) |
@@ -471,7 +464,7 @@ void lcd_sleep(void) | |||
471 | if (power_on) | 464 | if (power_on) |
472 | { | 465 | { |
473 | /* Turn off display */ | 466 | /* Turn off display */ |
474 | if (display_on) | 467 | if (lcd_active()) |
475 | lcd_display_off(); | 468 | lcd_display_off(); |
476 | 469 | ||
477 | power_on = false; | 470 | power_on = false; |
@@ -483,59 +476,6 @@ void lcd_sleep(void) | |||
483 | } | 476 | } |
484 | #endif | 477 | #endif |
485 | 478 | ||
486 | /* Copies a rectangle from one framebuffer to another. Can be used in | ||
487 | single transfer mode with width = num pixels, and height = 1 which | ||
488 | allows a full-width rectangle to be copied more efficiently. */ | ||
489 | extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, | ||
490 | int width, int height); | ||
491 | void lcd_update_rect(int x, int y, int width, int height) | ||
492 | { | ||
493 | fb_data *dst, *src; | ||
494 | |||
495 | if (!display_on) | ||
496 | return; | ||
497 | |||
498 | if (x + width > LCD_WIDTH) | ||
499 | width = LCD_WIDTH - x; /* Clip right */ | ||
500 | if (x < 0) | ||
501 | width += x, x = 0; /* Clip left */ | ||
502 | if (width <= 0) | ||
503 | return; /* nothing left to do */ | ||
504 | |||
505 | if (y + height > LCD_HEIGHT) | ||
506 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
507 | if (y < 0) | ||
508 | height += y, y = 0; /* Clip top */ | ||
509 | if (height <= 0) | ||
510 | return; /* nothing left to do */ | ||
511 | |||
512 | dst = &lcd_driver_framebuffer[y][x]; | ||
513 | src = &lcd_framebuffer[y][x]; | ||
514 | |||
515 | /* Copy part of the Rockbox framebuffer to the second framebuffer */ | ||
516 | if (width < LCD_WIDTH) | ||
517 | { | ||
518 | /* Not full width - do line-by-line */ | ||
519 | lcd_copy_buffer_rect(dst, src, width, height); | ||
520 | } | ||
521 | else | ||
522 | { | ||
523 | /* Full width - copy as one line */ | ||
524 | lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | void lcd_update(void) | ||
529 | { | ||
530 | if (!display_on) | ||
531 | return; | ||
532 | |||
533 | /* Copy the Rockbox framebuffer to the second framebuffer */ | ||
534 | lcd_copy_buffer_rect(&lcd_driver_framebuffer[0][0], | ||
535 | &lcd_framebuffer[0][0], LCD_WIDTH*LCD_HEIGHT, 1); | ||
536 | } | ||
537 | |||
538 | |||
539 | /*** hardware configuration ***/ | 479 | /*** hardware configuration ***/ |
540 | 480 | ||
541 | void lcd_set_contrast(int val) | 481 | void lcd_set_contrast(int val) |
@@ -558,7 +498,7 @@ void lcd_set_invert_display(bool yesno) | |||
558 | r_disp_control_rev = yesno ? R_DISP_CONTROL_REV : | 498 | r_disp_control_rev = yesno ? R_DISP_CONTROL_REV : |
559 | R_DISP_CONTROL_NORMAL; | 499 | R_DISP_CONTROL_NORMAL; |
560 | 500 | ||
561 | if (display_on) | 501 | if (lcd_active()) |
562 | { | 502 | { |
563 | /* PT1-0=00, VLE2-1=00, SPT=0, IB6(??)=1, GON=1, CL=0, | 503 | /* PT1-0=00, VLE2-1=00, SPT=0, IB6(??)=1, GON=1, CL=0, |
564 | DTE=1, REV=x, D1-0=11 */ | 504 | DTE=1, REV=x, D1-0=11 */ |
@@ -602,73 +542,3 @@ void lcd_set_flip(bool yesno) | |||
602 | LCD_REG_6 |= 1; /* Restart DMA */ | 542 | LCD_REG_6 |= 1; /* Restart DMA */ |
603 | } | 543 | } |
604 | } | 544 | } |
605 | |||
606 | /* Blitting functions */ | ||
607 | |||
608 | void lcd_yuv_set_options(unsigned options) | ||
609 | { | ||
610 | lcd_yuv_options = options; | ||
611 | } | ||
612 | |||
613 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
614 | extern void lcd_write_yuv420_lines(fb_data *dst, | ||
615 | unsigned char const * const src[3], | ||
616 | int width, | ||
617 | int stride); | ||
618 | extern void lcd_write_yuv420_lines_odither(fb_data *dst, | ||
619 | unsigned char const * const src[3], | ||
620 | int width, | ||
621 | int stride, | ||
622 | int x_screen, /* To align dither pattern */ | ||
623 | int y_screen); | ||
624 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
625 | /* For the e200 - show it rotated */ | ||
626 | /* So the LCD_WIDTH is now the height */ | ||
627 | void lcd_blit_yuv(unsigned char * const src[3], | ||
628 | int src_x, int src_y, int stride, | ||
629 | int x, int y, int width, int height) | ||
630 | { | ||
631 | unsigned char const * yuv_src[3]; | ||
632 | off_t z; | ||
633 | |||
634 | if (!display_on) | ||
635 | return; | ||
636 | |||
637 | /* Sorry, but width and height must be >= 2 or else */ | ||
638 | width &= ~1; | ||
639 | height >>= 1; | ||
640 | |||
641 | y = LCD_WIDTH - 1 - y; | ||
642 | fb_data *dst = &lcd_driver_framebuffer[x][y]; | ||
643 | |||
644 | z = stride*src_y; | ||
645 | yuv_src[0] = src[0] + z + src_x; | ||
646 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
647 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
648 | |||
649 | if (lcd_yuv_options & LCD_YUV_DITHER) | ||
650 | { | ||
651 | do | ||
652 | { | ||
653 | lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x); | ||
654 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
655 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
656 | yuv_src[2] += stride >> 1; | ||
657 | dst -= 2; | ||
658 | y -= 2; | ||
659 | } | ||
660 | while (--height > 0); | ||
661 | } | ||
662 | else | ||
663 | { | ||
664 | do | ||
665 | { | ||
666 | lcd_write_yuv420_lines(dst, yuv_src, width, stride); | ||
667 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
668 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
669 | yuv_src[2] += stride >> 1; | ||
670 | dst -= 2; | ||
671 | } | ||
672 | while (--height > 0); | ||
673 | } | ||
674 | } | ||