diff options
author | Jens Arnold <amiconn@rockbox.org> | 2007-02-25 13:11:02 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2007-02-25 13:11:02 +0000 |
commit | 2906c36df3403b8c8146718beedfc480766a9d6c (patch) | |
tree | 9ded4dc9a8bbf6760337cabdc0c87465108b4037 /firmware/drivers | |
parent | b7486fb4a99304b3fc41882cecdff33562c3bfc0 (diff) |
Moved ipod LCD code to target tree.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12479 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/lcd-ipod.c | 749 | ||||
-rw-r--r-- | firmware/drivers/lcd-ipodvideo.c | 389 |
2 files changed, 0 insertions, 1138 deletions
diff --git a/firmware/drivers/lcd-ipod.c b/firmware/drivers/lcd-ipod.c deleted file mode 100644 index e65d500654..0000000000 --- a/firmware/drivers/lcd-ipod.c +++ /dev/null @@ -1,749 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Rockbox driver for iPod LCDs - * - * Based on code from the ipodlinux project - http://ipodlinux.org/ - * Adapted for Rockbox in November 2005 - * - * Original file: linux/arch/armnommu/mach-ipod/fb.c - * - * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "cpu.h" -#include "lcd.h" -#include "kernel.h" -#include "system.h" - - -/* check if number of useconds has past */ -static inline bool timer_check(int clock_start, int usecs) -{ - return ((int)(USEC_TIMER - clock_start)) >= usecs; -} - -#if (CONFIG_LCD == LCD_IPOD2BPP) || (CONFIG_LCD == LCD_IPODMINI) - -/*** hardware configuration ***/ - -#if CONFIG_CPU == PP5002 -#define IPOD_LCD_BASE 0xc0001000 -#define IPOD_LCD_BUSY_MASK 0x80000000 -#else /* PP5020 */ -#define IPOD_LCD_BASE 0x70003000 -#define IPOD_LCD_BUSY_MASK 0x00008000 -#endif - -/* LCD command codes for HD66753 */ - -#define LCD_CMD 0x08 -#define LCD_DATA 0x10 - -#define R_START_OSC 0x00 -#define R_DRV_OUTPUT_CONTROL 0x01 -#define R_DRV_WAVEFORM_CONTROL 0x02 -#define R_POWER_CONTROL 0x03 -#define R_CONTRAST_CONTROL 0x04 -#define R_ENTRY_MODE 0x05 -#define R_ROTATION 0x06 -#define R_DISPLAY_CONTROL 0x07 -#define R_CURSOR_CONTROL 0x08 -#define R_HORIZONTAL_CURSOR_POS 0x0b -#define R_VERTICAL_CURSOR_POS 0x0c -#define R_1ST_SCR_DRV_POS 0x0d -#define R_2ND_SCR_DRV_POS 0x0e -#define R_RAM_WRITE_MASK 0x10 -#define R_RAM_ADDR_SET 0x11 -#define R_RAM_DATA 0x12 - -/* needed for flip */ -static int addr_offset; -#if defined(IPOD_MINI) || defined(IPOD_MINI2G) -static int pix_offset; -#endif - -static const unsigned char dibits[16] ICONST_ATTR = { - 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, - 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF -}; - -/* wait for LCD with timeout */ -static inline void lcd_wait_write(void) -{ - int start = USEC_TIMER; - - do { - if ((inl(IPOD_LCD_BASE) & 0x8000) == 0) break; - } while (timer_check(start, 1000) == 0); -} - - -/* send LCD data */ -static void lcd_send_data(unsigned data) -{ - lcd_wait_write(); -#ifdef IPOD_MINI2G - outl((inl(IPOD_LCD_BASE) & ~0x1f00000) | 0x1700000, IPOD_LCD_BASE); - outl(data | 0x760000, IPOD_LCD_BASE+8); -#else - outl(data >> 8, IPOD_LCD_BASE + LCD_DATA); - lcd_wait_write(); - outl(data & 0xff, IPOD_LCD_BASE + LCD_DATA); -#endif -} - -/* send LCD command */ -static void lcd_prepare_cmd(unsigned cmd) -{ - lcd_wait_write(); -#ifdef IPOD_MINI2G - outl((inl(IPOD_LCD_BASE) & ~0x1f00000) | 0x1700000, IPOD_LCD_BASE); - outl(cmd | 0x740000, IPOD_LCD_BASE+8); -#else - outl(0x0, IPOD_LCD_BASE + LCD_CMD); - lcd_wait_write(); - outl(cmd, IPOD_LCD_BASE + LCD_CMD); -#endif -} - -/* send LCD command and data */ -static void lcd_cmd_and_data(unsigned cmd, unsigned data) -{ - lcd_prepare_cmd(cmd); - lcd_send_data(data); -} - -/* LCD init */ -void lcd_init_device(void) -{ - lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0009); - lcd_set_flip(false); - lcd_cmd_and_data(R_ENTRY_MODE, 0x0000); - -#ifdef IPOD_4G - outl(inl(0x6000d004) | 0x4, 0x6000d004); /* B02 enable */ - outl(inl(0x6000d004) | 0x8, 0x6000d004); /* B03 enable */ - outl(inl(0x70000084) | 0x2000000, 0x70000084); /* D01 enable */ - outl(inl(0x70000080) | 0x2000000, 0x70000080); /* D01 =1 */ - - outl(inl(0x6000600c) | 0x20000, 0x6000600c); /* PWM enable */ -#endif -} - -/*** hardware configuration ***/ - -int lcd_default_contrast(void) -{ -#if defined(IPOD_MINI) || defined(IPOD_MINI2G) || defined(IPOD_3G) - return 42; -#else - return 35; -#endif -} - -/* Rockbox stores the contrast as 0..63 - we add 64 to it */ -void lcd_set_contrast(int val) -{ - if (val < 0) val = 0; - else if (val > 63) val = 63; - - lcd_cmd_and_data(R_CONTRAST_CONTROL, 0x400 | (val + 64)); -} - -void lcd_set_invert_display(bool yesno) -{ - if (yesno) - lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0023); - else - lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0009); -} - -/* turn the display upside down (call lcd_update() afterwards) */ -void lcd_set_flip(bool yesno) -{ -#if defined(IPOD_MINI) || defined(IPOD_MINI2G) - if (yesno) { - /* 168x112, inverse COM order */ - lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x020d); - lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x8316); /* 22..131 */ - addr_offset = (22 << 5) | (20 - 4); - pix_offset = -2; - } else { - /* 168x112, inverse SEG order */ - lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x010d); - lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x6d00); /* 0..109 */ - addr_offset = 20; - pix_offset = 0; - } -#else - if (yesno) { - /* 168x128, inverse SEG & COM order */ - lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x030f); - lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x8304); /* 4..131 */ - addr_offset = (4 << 5) | (20 - 1); - } else { - /* 168x128 */ - lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x000f); - lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x7f00); /* 0..127 */ - addr_offset = 20; - } -#endif -} - -/*** update functions ***/ - -/* Performance function that works with an external buffer - note that x, bwidtht and stride are in 8-pixel units! */ -void lcd_blit(const unsigned char* data, int bx, int y, int bwidth, - int height, int stride) -{ - const unsigned char *src, *src_end; - - while (height--) { - src = data; - src_end = data + bwidth; - lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx); - lcd_prepare_cmd(R_RAM_DATA); - do { - unsigned byte = *src++; - lcd_send_data((dibits[byte>>4] << 8) | dibits[byte&0x0f]); - } while (src < src_end); - data += stride; - } -} - -void lcd_update_rect(int x, int y, int width, int height) -{ - int xmax, ymax; - - if (x + width > LCD_WIDTH) - width = LCD_WIDTH - x; - if (width <= 0) - return; - - ymax = y + height - 1; - if (ymax >= LCD_HEIGHT) - ymax = LCD_HEIGHT - 1; - -#if defined(IPOD_MINI) || defined(IPOD_MINI2G) - x += pix_offset; -#endif - /* writing is done in 16-bit units (8 pixels) */ - xmax = (x + width - 1) >> 3; - x >>= 3; - width = xmax - x + 1; - - for (; y <= ymax; y++) { - unsigned char *data, *data_end; - - lcd_cmd_and_data(R_RAM_ADDR_SET, (y << 5) + addr_offset - x); - lcd_prepare_cmd(R_RAM_DATA); - - data = &lcd_framebuffer[y][2*x]; - data_end = data + 2 * width; -#if defined(IPOD_MINI) || defined(IPOD_MINI2G) - if (pix_offset == -2) { - unsigned cur_word = *data++; - do { - cur_word = (cur_word << 8) | *data++; - cur_word = (cur_word << 8) | *data++; - lcd_send_data((cur_word >> 4) & 0xffff); - } while (data <= data_end); - } else -#endif - { - do { - unsigned highbyte = *data++; - lcd_send_data((highbyte << 8) | *data++); - } while (data < data_end); - } - } -} - -/* Update the display. */ -void lcd_update(void) -{ - lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); -} - -#else - -#define IPOD_LCD_BASE 0x70008a0c -#define IPOD_LCD_BUSY_MASK 0x80000000 - -/* LCD command codes for HD66789R */ -#define LCD_CNTL_RAM_ADDR_SET 0x21 -#define LCD_CNTL_WRITE_TO_GRAM 0x22 -#define LCD_CNTL_HORIZ_RAM_ADDR_POS 0x44 -#define LCD_CNTL_VERT_RAM_ADDR_POS 0x45 - -/*** globals ***/ -static int lcd_type = 1; /* 0 = "old" Color/Photo, 1 = "new" Color & Nano */ - -static void lcd_wait_write(void) -{ - if ((inl(IPOD_LCD_BASE) & IPOD_LCD_BUSY_MASK) != 0) { - int start = USEC_TIMER; - - do { - if ((inl(IPOD_LCD_BASE) & IPOD_LCD_BUSY_MASK) == 0) break; - } while (timer_check(start, 1000) == 0); - } -} - -static void lcd_send_lo(int v) -{ - lcd_wait_write(); - outl(v | 0x80000000, IPOD_LCD_BASE); -} - -static void lcd_send_hi(int v) -{ - lcd_wait_write(); - outl(v | 0x81000000, IPOD_LCD_BASE); -} - -static void lcd_cmd_data(int cmd, int data) -{ - if (lcd_type == 0) { - lcd_send_lo(cmd); - lcd_send_lo(data); - } else { - lcd_send_lo(0x0); - lcd_send_lo(cmd); - lcd_send_hi((data >> 8) & 0xff); - lcd_send_hi(data & 0xff); - } -} - -/*** hardware configuration ***/ - -void lcd_set_contrast(int val) -{ - /* TODO: Implement lcd_set_contrast() */ - (void)val; -} - -void lcd_set_invert_display(bool yesno) -{ - /* TODO: Implement lcd_set_invert_display() */ - (void)yesno; -} - -/* turn the display upside down (call lcd_update() afterwards) */ -void lcd_set_flip(bool yesno) -{ - /* TODO: Implement lcd_set_flip() */ - (void)yesno; -} - -/* LCD init */ -void lcd_init_device(void) -{ -#if CONFIG_LCD == LCD_IPODCOLOR - if (ipod_hw_rev == 0x60000) { - lcd_type = 0; - } else { - int gpio_a01, gpio_a04; - - /* A01 */ - gpio_a01 = (inl(0x6000D030) & 0x2) >> 1; - /* A04 */ - gpio_a04 = (inl(0x6000D030) & 0x10) >> 4; - - if (((gpio_a01 << 1) | gpio_a04) == 0 || ((gpio_a01 << 1) | gpio_a04) == 2) { - lcd_type = 0; - } else { - lcd_type = 1; - } - } - - outl(inl(0x6000d004) | 0x4, 0x6000d004); /* B02 enable */ - outl(inl(0x6000d004) | 0x8, 0x6000d004); /* B03 enable */ - outl(inl(0x70000084) | 0x2000000, 0x70000084); /* D01 enable */ - outl(inl(0x70000080) | 0x2000000, 0x70000080); /* D01 =1 */ - - outl(inl(0x6000600c) | 0x20000, 0x6000600c); /* PWM enable */ - -#elif CONFIG_LCD == LCD_IPODNANO - /* iPodLinux doesn't appear have any LCD init code for the Nano */ -#endif -} - -/*** update functions ***/ - -/* Performance function that works with an external buffer - note that by and bheight are in 4-pixel units! */ -void lcd_blit(const fb_data* data, int x, int by, int width, - int bheight, int stride) -{ - /* TODO: Implement lcd_blit() */ - (void)data; - (void)x; - (void)by; - (void)width; - (void)bheight; - (void)stride; -} - -#define CSUB_X 2 -#define CSUB_Y 2 - -#define RYFAC (31*257) -#define GYFAC (31*257) -#define BYFAC (31*257) -#define RVFAC 11170 /* 31 * 257 * 1.402 */ -#define GVFAC (-5690) /* 31 * 257 * -0.714136 */ -#define GUFAC (-2742) /* 31 * 257 * -0.344136 */ -#define BUFAC 14118 /* 31 * 257 * 1.772 */ - -#define ROUNDOFFS (127*257) -#define ROUNDOFFSG (63*257) - -/* Performance function to blit a YUV bitmap directly to the LCD */ -void lcd_yuv_blit(unsigned char * const src[3], - int src_x, int src_y, int stride, - int x, int y, int width, int height) -{ - int h; - int y0, x0, y1, x1; - - width = (width + 1) & ~1; - - /* calculate the drawing region */ -#if CONFIG_LCD == LCD_IPODNANO - y0 = x; /* start horiz */ - x0 = y; /* start vert */ - y1 = (x + width) - 1; /* max horiz */ - x1 = (y + height) - 1; /* max vert */ -#elif CONFIG_LCD == LCD_IPODCOLOR - y0 = y; /* start vert */ - x0 = (LCD_WIDTH - 1) - x; /* start horiz */ - y1 = (y + height) - 1; /* end vert */ - x1 = (x0 - width) + 1; /* end horiz */ -#endif - - /* setup the drawing region */ - if (lcd_type == 0) { - lcd_cmd_data(0x12, y0); /* start vert */ - lcd_cmd_data(0x13, x0); /* start horiz */ - lcd_cmd_data(0x15, y1); /* end vert */ - lcd_cmd_data(0x16, x1); /* end horiz */ - } else { - /* swap max horiz < start horiz */ - if (y1 < y0) { - int t; - t = y0; - y0 = y1; - y1 = t; - } - - /* swap max vert < start vert */ - if (x1 < x0) { - int t; - t = x0; - x0 = x1; - x1 = t; - } - - /* max horiz << 8 | start horiz */ - lcd_cmd_data(LCD_CNTL_HORIZ_RAM_ADDR_POS, (y1 << 8) | y0); - /* max vert << 8 | start vert */ - lcd_cmd_data(LCD_CNTL_VERT_RAM_ADDR_POS, (x1 << 8) | x0); - - /* start vert = max vert */ -#if CONFIG_LCD == LCD_IPODCOLOR - x0 = x1; -#endif - - /* position cursor (set AD0-AD15) */ - /* start vert << 8 | start horiz */ - lcd_cmd_data(LCD_CNTL_RAM_ADDR_SET, ((x0 << 8) | y0)); - - /* start drawing */ - lcd_send_lo(0x0); - lcd_send_lo(LCD_CNTL_WRITE_TO_GRAM); - } - - const int stride_div_csub_x = stride/CSUB_X; - - h=0; - while (1) { - /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ - const unsigned char *ysrc = src[0] + stride * src_y + src_x; - - const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + - (src_x/CSUB_X); - - const unsigned char *usrc = src[1] + uvoffset; - const unsigned char *vsrc = src[2] + uvoffset; - const unsigned char *row_end = ysrc + width; - - int y, u, v; - int red1, green1, blue1; - int red2, green2, blue2; - unsigned rbits, gbits, bbits; - - int rc, gc, bc; - int pixels_to_write; - fb_data pixel1,pixel2; - - if (h==0) { - while ((inl(0x70008a20) & 0x4000000) == 0); - outl(0x0, 0x70008a24); - - if (height == 0) break; - - pixels_to_write = (width * height) * 2; - h = height; - - /* calculate how much we can do in one go */ - if (pixels_to_write > 0x10000) { - h = (0x10000/2) / width; - pixels_to_write = (width * h) * 2; - } - - height -= h; - outl(0x10000080, 0x70008a20); - outl((pixels_to_write - 1) | 0xc0010000, 0x70008a24); - outl(0x34000000, 0x70008a20); - } - - do - { - u = *usrc++ - 128; - v = *vsrc++ - 128; - rc = RVFAC * v + ROUNDOFFS; - gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; - bc = BUFAC * u + ROUNDOFFS; - - /* Pixel 1 */ - y = *ysrc++; - - red1 = RYFAC * y + rc; - green1 = GYFAC * y + gc; - blue1 = BYFAC * y + bc; - - /* Pixel 2 */ - y = *ysrc++; - red2 = RYFAC * y + rc; - green2 = GYFAC * y + gc; - blue2 = BYFAC * y + bc; - - /* Since out of bounds errors are relatively rare, we check two - pixels at once to see if any components are out of bounds, and - then fix whichever is broken. This works due to high values and - negative values both becoming larger than the cutoff when - casted to unsigned. And ORing them together checks all of them - simultaneously. */ - if (((unsigned)(red1 | green1 | blue1 | - red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { - if (((unsigned)(red1 | green1 | blue1)) > - (RYFAC*255+ROUNDOFFS)) { - if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) - { - if (red1 < 0) - red1 = 0; - else - red1 = (RYFAC*255+ROUNDOFFS); - } - if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG)) - { - if (green1 < 0) - green1 = 0; - else - green1 = (GYFAC*255+ROUNDOFFSG); - } - if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS)) - { - if (blue1 < 0) - blue1 = 0; - else - blue1 = (BYFAC*255+ROUNDOFFS); - } - } - - if (((unsigned)(red2 | green2 | blue2)) > - (RYFAC*255+ROUNDOFFS)) { - if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS)) - { - if (red2 < 0) - red2 = 0; - else - red2 = (RYFAC*255+ROUNDOFFS); - } - if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG)) - { - if (green2 < 0) - green2 = 0; - else - green2 = (GYFAC*255+ROUNDOFFSG); - } - if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS)) - { - if (blue2 < 0) - blue2 = 0; - else - blue2 = (BYFAC*255+ROUNDOFFS); - } - } - } - - rbits = red1 >> 16 ; - gbits = green1 >> 15 ; - bbits = blue1 >> 16 ; - - pixel1 = swap16((rbits << 11) | (gbits << 5) | bbits); - - rbits = red2 >> 16 ; - gbits = green2 >> 15 ; - bbits = blue2 >> 16 ; - pixel2 = swap16((rbits << 11) | (gbits << 5) | bbits); - - while ((inl(0x70008a20) & 0x1000000) == 0); - - /* output 2 pixels */ - outl((pixel2<<16)|pixel1, 0x70008b00); - } - while (ysrc < row_end); - - src_y++; - h--; - } - - while ((inl(0x70008a20) & 0x4000000) == 0); - outl(0x0, 0x70008a24); -} - - -/* Update a fraction of the display. */ -void lcd_update_rect(int x, int y, int width, int height) -{ - int y0, x0, y1, x1; - int newx,newwidth; - - unsigned long *addr = (unsigned long *)lcd_framebuffer; - - /* Ensure x and width are both even - so we can read 32-bit aligned - data from lcd_framebuffer */ - newx=x&~1; - newwidth=width&~1; - if (newx+newwidth < x+width) { newwidth+=2; } - x=newx; width=newwidth; - - /* calculate the drawing region */ -#if CONFIG_LCD == LCD_IPODNANO - y0 = x; /* start horiz */ - x0 = y; /* start vert */ - y1 = (x + width) - 1; /* max horiz */ - x1 = (y + height) - 1; /* max vert */ -#elif CONFIG_LCD == LCD_IPODCOLOR - y0 = y; /* start vert */ - x0 = (LCD_WIDTH - 1) - x; /* start horiz */ - y1 = (y + height) - 1; /* end vert */ - x1 = (x0 - width) + 1; /* end horiz */ -#endif - /* setup the drawing region */ - if (lcd_type == 0) { - lcd_cmd_data(0x12, y0); /* start vert */ - lcd_cmd_data(0x13, x0); /* start horiz */ - lcd_cmd_data(0x15, y1); /* end vert */ - lcd_cmd_data(0x16, x1); /* end horiz */ - } else { - /* swap max horiz < start horiz */ - if (y1 < y0) { - int t; - t = y0; - y0 = y1; - y1 = t; - } - - /* swap max vert < start vert */ - if (x1 < x0) { - int t; - t = x0; - x0 = x1; - x1 = t; - } - - /* max horiz << 8 | start horiz */ - lcd_cmd_data(LCD_CNTL_HORIZ_RAM_ADDR_POS, (y1 << 8) | y0); - /* max vert << 8 | start vert */ - lcd_cmd_data(LCD_CNTL_VERT_RAM_ADDR_POS, (x1 << 8) | x0); - - /* start vert = max vert */ -#if CONFIG_LCD == LCD_IPODCOLOR - x0 = x1; -#endif - - /* position cursor (set AD0-AD15) */ - /* start vert << 8 | start horiz */ - lcd_cmd_data(LCD_CNTL_RAM_ADDR_SET, ((x0 << 8) | y0)); - - /* start drawing */ - lcd_send_lo(0x0); - lcd_send_lo(LCD_CNTL_WRITE_TO_GRAM); - } - - addr = (unsigned long*)&lcd_framebuffer[y][x]; - - while (height > 0) { - int c, r; - int h, pixels_to_write; - - pixels_to_write = (width * height) * 2; - h = height; - - /* calculate how much we can do in one go */ - if (pixels_to_write > 0x10000) { - h = (0x10000/2) / width; - pixels_to_write = (width * h) * 2; - } - - outl(0x10000080, 0x70008a20); - outl((pixels_to_write - 1) | 0xc0010000, 0x70008a24); - outl(0x34000000, 0x70008a20); - - /* for each row */ - for (r = 0; r < h; r++) { - /* for each column */ - for (c = 0; c < width; c += 2) { - while ((inl(0x70008a20) & 0x1000000) == 0); - - /* output 2 pixels */ - outl(*(addr++), 0x70008b00); - } - - addr += (LCD_WIDTH - width)/2; - } - - while ((inl(0x70008a20) & 0x4000000) == 0); - - outl(0x0, 0x70008a24); - - height = height - h; - } -} - -/* Update the display. - This must be called after all other LCD functions that change the display. */ -void lcd_update(void) -{ - lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); -} - -#endif diff --git a/firmware/drivers/lcd-ipodvideo.c b/firmware/drivers/lcd-ipodvideo.c deleted file mode 100644 index 237162b664..0000000000 --- a/firmware/drivers/lcd-ipodvideo.c +++ /dev/null @@ -1,389 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * LCD driver for iPod Video - * - * Based on code from the ipodlinux project - http://ipodlinux.org/ - * Adapted for Rockbox in December 2005 - * - * Original file: linux/arch/armnommu/mach-ipod/fb.c - * - * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "cpu.h" -#include "lcd.h" -#include "kernel.h" -#include "system.h" - -/*** hardware configuration ***/ - -void lcd_set_contrast(int val) -{ - /* TODO: Implement lcd_set_contrast() */ - (void)val; -} - -void lcd_set_invert_display(bool yesno) -{ - /* TODO: Implement lcd_set_invert_display() */ - (void)yesno; -} - -/* turn the display upside down (call lcd_update() afterwards) */ -void lcd_set_flip(bool yesno) -{ - /* TODO: Implement lcd_set_flip() */ - (void)yesno; -} - -/* LCD init */ -void lcd_init_device(void) -{ - /* iPodLinux doesn't appear have any LCD init code for the Video */ -} - -/*** update functions ***/ - -/* Performance function that works with an external buffer - note that by and bheight are in 4-pixel units! */ -void lcd_blit(const fb_data* data, int x, int by, int width, - int bheight, int stride) -{ - /* TODO: Implement lcd_blit() */ - (void)data; - (void)x; - (void)by; - (void)width; - (void)bheight; - (void)stride; -} - -static inline void lcd_bcm_write32(unsigned address, unsigned value) -{ - /* write out destination address as two 16bit values */ - outw(address, 0x30010000); - outw((address >> 16), 0x30010000); - - /* wait for it to be write ready */ - while ((inw(0x30030000) & 0x2) == 0); - - /* write out the value low 16, high 16 */ - outw(value, 0x30000000); - outw((value >> 16), 0x30000000); -} - -static void lcd_bcm_setup_rect(unsigned cmd, - unsigned start_horiz, - unsigned start_vert, - unsigned max_horiz, - unsigned max_vert, - unsigned count) -{ - lcd_bcm_write32(0x1F8, 0xFFFA0005); - lcd_bcm_write32(0xE0000, cmd); - lcd_bcm_write32(0xE0004, start_horiz); - lcd_bcm_write32(0xE0008, start_vert); - lcd_bcm_write32(0xE000C, max_horiz); - lcd_bcm_write32(0xE0010, max_vert); - lcd_bcm_write32(0xE0014, count); - lcd_bcm_write32(0xE0018, count); - lcd_bcm_write32(0xE001C, 0); -} - -static unsigned lcd_bcm_read32(unsigned address) { - while ((inw(0x30020000) & 1) == 0); - - /* write out destination address as two 16bit values */ - outw(address, 0x30020000); - outw((address >> 16), 0x30020000); - - /* wait for it to be read ready */ - while ((inw(0x30030000) & 0x10) == 0); - - /* read the value */ - return inw(0x30000000) | inw(0x30000000) << 16; -} - -static int finishup_needed = 0; - -/* Update a fraction of the display. */ -void lcd_update_rect(int x, int y, int width, int height) ICODE_ATTR; -void lcd_update_rect(int x, int y, int width, int height) -{ - { - int endy = x + width; - /* Ensure x and width are both even - so we can read 32-bit aligned - data from lcd_framebuffer */ - x &= ~1; - width &= ~1; - if (x + width < endy) { - width += 2; - } - } - - if (finishup_needed) { - unsigned int data; - /* Bottom-half of original lcd_bcm_finishup() function */ - do { - /* This function takes about 14ms to execute - so we yield() */ - yield(); - data = lcd_bcm_read32(0x1F8); - } while (data == 0xFFFA0005 || data == 0xFFFF); - } - - lcd_bcm_read32(0x1FC); - - { - int rect1, rect2, rect3, rect4; - int count = (width * height) << 1; - /* calculate the drawing region */ - rect1 = x; /* start horiz */ - rect2 = y; /* start vert */ - rect3 = (x + width) - 1; /* max horiz */ - rect4 = (y + height) - 1; /* max vert */ - - /* setup the drawing region */ - lcd_bcm_setup_rect(0x34, rect1, rect2, rect3, rect4, count); - } - - /* write out destination address as two 16bit values */ - outw((0xE0020 & 0xffff), 0x30010000); - outw((0xE0020 >> 16), 0x30010000); - - /* wait for it to be write ready */ - while ((inw(0x30030000) & 0x2) == 0); - - { - unsigned short *src = (unsigned short*)&lcd_framebuffer[y][x]; - unsigned short *end = &src[LCD_WIDTH * height]; - int line_rem = (LCD_WIDTH - width); - while (src < end) { - /* Duff's Device to unroll loop */ - register int count = width ; - register int n=( count + 7 ) / 8; - switch( count % 8 ) { - case 0: do{ outw(*(src++), 0x30000000); - case 7: outw(*(src++), 0x30000000); - case 6: outw(*(src++), 0x30000000); - case 5: outw(*(src++), 0x30000000); - case 4: outw(*(src++), 0x30000000); - case 3: outw(*(src++), 0x30000000); - case 2: outw(*(src++), 0x30000000); - case 1: outw(*(src++), 0x30000000); - } while(--n>0); - } - src += line_rem; - } - } - - /* Top-half of original lcd_bcm_finishup() function */ - outw(0x31, 0x30030000); - - lcd_bcm_read32(0x1FC); - - finishup_needed = 1; -} - -/* Update the display. - This must be called after all other LCD functions that change the display. */ -void lcd_update(void) -{ - lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); -} - -#define CSUB_X 2 -#define CSUB_Y 2 - -#define RYFAC (31*257) -#define GYFAC (31*257) -#define BYFAC (31*257) -#define RVFAC 11170 /* 31 * 257 * 1.402 */ -#define GVFAC (-5690) /* 31 * 257 * -0.714136 */ -#define GUFAC (-2742) /* 31 * 257 * -0.344136 */ -#define BUFAC 14118 /* 31 * 257 * 1.772 */ - -#define ROUNDOFFS (127*257) -#define ROUNDOFFSG (63*257) - -/* Performance function to blit a YUV bitmap directly to the LCD */ -void lcd_yuv_blit(unsigned char * const src[3], - int src_x, int src_y, int stride, - int x, int y, int width, int height) -{ - int ymax; - - width = (width + 1) & ~1; - - if (finishup_needed) { - unsigned int data; - /* Bottom-half of original lcd_bcm_finishup() function */ - data = lcd_bcm_read32(0x1F8); - while (data == 0xFFFA0005 || data == 0xFFFF) { - /* This loop can wait for up to 14ms - so we yield() */ - yield(); - data = lcd_bcm_read32(0x1F8); - } - } - - lcd_bcm_read32(0x1FC); - - { - int rect1, rect2, rect3, rect4; - int count = (width * height) << 1; - /* calculate the drawing region */ - rect1 = x; /* start horiz */ - rect2 = y; /* start vert */ - rect3 = (x + width) - 1; /* max horiz */ - rect4 = (y + height) - 1; /* max vert */ - - /* setup the drawing region */ - lcd_bcm_setup_rect(0x34, rect1, rect2, rect3, rect4, count); - } - - /* write out destination address as two 16bit values */ - outw((0xE0020 & 0xffff), 0x30010000); - outw((0xE0020 >> 16), 0x30010000); - - /* wait for it to be write ready */ - while ((inw(0x30030000) & 0x2) == 0); - - ymax = y + height - 1 ; - - const int stride_div_csub_x = stride/CSUB_X; - - for (; y <= ymax ; y++) - { - /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ - const unsigned char *ysrc = src[0] + stride * src_y + src_x; - - const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + - (src_x/CSUB_X); - - const unsigned char *usrc = src[1] + uvoffset; - const unsigned char *vsrc = src[2] + uvoffset; - const unsigned char *row_end = ysrc + width; - - int y, u, v; - int red1, green1, blue1; - int red2, green2, blue2; - unsigned rbits, gbits, bbits; - - int rc, gc, bc; - - do - { - u = *usrc++ - 128; - v = *vsrc++ - 128; - rc = RVFAC * v + ROUNDOFFS; - gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; - bc = BUFAC * u + ROUNDOFFS; - - /* Pixel 1 */ - y = *ysrc++; - - red1 = RYFAC * y + rc; - green1 = GYFAC * y + gc; - blue1 = BYFAC * y + bc; - - /* Pixel 2 */ - y = *ysrc++; - red2 = RYFAC * y + rc; - green2 = GYFAC * y + gc; - blue2 = BYFAC * y + bc; - - /* Since out of bounds errors are relatively rare, we check two - pixels at once to see if any components are out of bounds, and - then fix whichever is broken. This works due to high values and - negative values both becoming larger than the cutoff when - casted to unsigned. And ORing them together checks all of them - simultaneously. */ - if (((unsigned)(red1 | green1 | blue1 | - red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { - if (((unsigned)(red1 | green1 | blue1)) > - (RYFAC*255+ROUNDOFFS)) { - if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) - { - if (red1 < 0) - red1 = 0; - else - red1 = (RYFAC*255+ROUNDOFFS); - } - if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG)) - { - if (green1 < 0) - green1 = 0; - else - green1 = (GYFAC*255+ROUNDOFFSG); - } - if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS)) - { - if (blue1 < 0) - blue1 = 0; - else - blue1 = (BYFAC*255+ROUNDOFFS); - } - } - - if (((unsigned)(red2 | green2 | blue2)) > - (RYFAC*255+ROUNDOFFS)) { - if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS)) - { - if (red2 < 0) - red2 = 0; - else - red2 = (RYFAC*255+ROUNDOFFS); - } - if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG)) - { - if (green2 < 0) - green2 = 0; - else - green2 = (GYFAC*255+ROUNDOFFSG); - } - if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS)) - { - if (blue2 < 0) - blue2 = 0; - else - blue2 = (BYFAC*255+ROUNDOFFS); - } - } - } - - rbits = red1 >> 16 ; - gbits = green1 >> 15 ; - bbits = blue1 >> 16 ; - - outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); - - rbits = red2 >> 16 ; - gbits = green2 >> 15 ; - bbits = blue2 >> 16 ; - outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); - } - while (ysrc < row_end); - - src_y++; - } - - /* Top-half of original lcd_bcm_finishup() function */ - outw(0x31, 0x30030000); - - lcd_bcm_read32(0x1FC); - - finishup_needed = 1; -} |