summaryrefslogtreecommitdiff
path: root/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/sandisk/sansa-e200/lcd-e200.c')
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/lcd-e200.c152
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
30extern void lcd_set_active(bool active);
31 31
32/* Power and display status */ 32/* Power and display status */
33static bool power_on = false; /* Is the power turned on? */ 33static bool power_on = false; /* Is the power turned on? */
34static bool display_on SHAREDBSS_ATTR = false; /* Is the display turned on? */
35static 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. */
115static fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] 113fb_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)
318bool lcd_active(void)
319{
320 return display_on;
321}
322
323/* Turn off visible display operations */ 316/* Turn off visible display operations */
324static void lcd_display_off(void) 317static 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)
441void lcd_enable(bool on) 434void 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. */
489extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
490 int width, int height);
491void 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
528void 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
541void lcd_set_contrast(int val) 481void 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
608void 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. */
614extern void lcd_write_yuv420_lines(fb_data *dst,
615 unsigned char const * const src[3],
616 int width,
617 int stride);
618extern 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 */
627void 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}