From 97bdfce5b6174db24fd947feb78ed31b83858e8f Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Fri, 10 Aug 2007 08:09:53 +0000 Subject: iPod greyscale LCD driver: * Further speedup (timeout check turned out to be unnecessary, as well as setting the LCD control register every time on Mini G2. Put lcd_write_data() in IRAM on PP5002). * Better blacklevel stability on 1st...3rd gen. * lcd_enable() function in preparation for suspend on 1st/2nd gen, and shutdown without a black line remaining. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14264 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/ipod/lcd-gray.c | 84 ++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 10 deletions(-) (limited to 'firmware') diff --git a/firmware/target/arm/ipod/lcd-gray.c b/firmware/target/arm/ipod/lcd-gray.c index 9a229a4725..265cc447d7 100644 --- a/firmware/target/arm/ipod/lcd-gray.c +++ b/firmware/target/arm/ipod/lcd-gray.c @@ -28,6 +28,7 @@ #include "lcd.h" #include "kernel.h" #include "system.h" +#include "hwcompat.h" /*** hardware configuration ***/ @@ -68,6 +69,20 @@ static bool lcd_backlit = false; static void invert_display(void); #endif +#if defined(IPOD_1G2G) || defined(IPOD_3G) +static unsigned short power_reg_h; +#define POWER_REG_H power_reg_h +#else +#define POWER_REG_H 0x1200 +#endif + +#ifdef IPOD_1G2G +static unsigned short contrast_reg_h; +#define CONTRAST_REG_H contrast_reg_h +#else +#define CONTRAST_REG_H 0x400 +#endif + /* needed for flip */ static int addr_offset; #if defined(IPOD_MINI) || defined(IPOD_MINI2G) @@ -82,19 +97,18 @@ static const unsigned char dibits[16] ICONST_ATTR = { /* wait for LCD with timeout */ static inline void lcd_wait_write(void) { - long timeout = USEC_TIMER + 1000; /* 1 ms */ - - while ((inl(IPOD_LCD_BASE) & LCD_BUSY_MASK) - && TIME_BEFORE(USEC_TIMER, timeout)); + while (inl(IPOD_LCD_BASE) & LCD_BUSY_MASK); } - /* send LCD data */ +#if CONFIG_CPU == PP5002 +STATICIRAM void ICODE_ATTR lcd_send_data(unsigned data) +#else static void lcd_send_data(unsigned data) +#endif { 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); @@ -108,7 +122,6 @@ 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); @@ -127,6 +140,38 @@ static void lcd_cmd_and_data(unsigned cmd, unsigned data) /* LCD init */ void lcd_init_device(void) { +#ifdef IPOD_1G2G + if ((IPOD_HW_REVISION >> 16) == 1) + { + power_reg_h = 0x1500; + contrast_reg_h = 0x700; + } + else /* 2nd gen */ + { + if (inl(0xcf00404c) & 0x01) /* check bit 0 */ + { + power_reg_h = 0x1520; /* Set step-up frequency to f/8 instead of + * f/32, for better blacklevel stability */ + contrast_reg_h = 0x400; + } + else + { + power_reg_h = 0x1100; + contrast_reg_h = 0x300; + } + } +#elif defined IPOD_3G + if (inl(0xcf00404c) & 0x01) /* check bit 0 */ + power_reg_h = 0x1520; /* Set step-up frequency to f/8 instead of + * f/32, for better blacklevel stability */ + else + power_reg_h = 0x1100; +#elif defined IPOD_MINI2G + lcd_wait_write(); + outl((inl(IPOD_LCD_BASE) & ~0x1f00000) | 0x1700000, IPOD_LCD_BASE); +#endif + + lcd_cmd_and_data(R_POWER_CONTROL, POWER_REG_H | 0xc); #ifdef HAVE_BACKLIGHT_INVERSION invert_display(); #else @@ -150,10 +195,10 @@ void lcd_init_device(void) int lcd_default_contrast(void) { #ifdef IPOD_1G2G - return 30; + return 28; #elif defined(IPOD_MINI) || defined(IPOD_MINI2G) || defined(IPOD_3G) return 42; -#else +#elif defined(IPOD_4G) return 35; #endif } @@ -164,7 +209,7 @@ 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)); + lcd_cmd_and_data(R_CONTRAST_CONTROL, CONTRAST_REG_H | (val + 64)); } #ifdef HAVE_BACKLIGHT_INVERSION @@ -229,6 +274,25 @@ void lcd_set_flip(bool yesno) #endif } +void lcd_enable(bool on) +{ + if (on) + { + lcd_cmd_and_data(R_START_OSC, 1); /* start oscillation */ + sleep(HZ/10); /* wait 10ms */ + lcd_cmd_and_data(R_POWER_CONTROL, POWER_REG_H); /*clear standby mode */ + lcd_cmd_and_data(R_POWER_CONTROL, POWER_REG_H | 0xc); + /* enable opamp & booster */ + } + else + { + lcd_cmd_and_data(R_POWER_CONTROL, POWER_REG_H); + /* switch off opamp & booster */ + lcd_cmd_and_data(R_POWER_CONTROL, POWER_REG_H | 0x1); + /* enter standby mode */ + } +} + /*** update functions ***/ /* Performance function that works with an external buffer -- cgit v1.2.3