diff options
| author | Karl Kurbjun <kkurbjun@gmail.com> | 2008-05-14 00:26:28 +0000 |
|---|---|---|
| committer | Karl Kurbjun <kkurbjun@gmail.com> | 2008-05-14 00:26:28 +0000 |
| commit | 6e322c878695e9b6dbf5620feda76315a523cc43 (patch) | |
| tree | fa752c8f5419c4c27dabcc53dedba2b0ad4f9f97 | |
| parent | f7e0e6bb1cfc079cfbf18ce3224442be26ba46f2 (diff) | |
| download | rockbox-6e322c878695e9b6dbf5620feda76315a523cc43.zip rockbox-6e322c878695e9b6dbf5620feda76315a523cc43.tar.gz rockbox-6e322c878695e9b6dbf5620feda76315a523cc43.tar.bz2 rockbox-6e322c878695e9b6dbf5620feda76315a523cc43.tar.xz | |
Reduce power consumed on the F/X by as much as 12% when the LCD is disabled. Timing is tighter on the SPI interface, if the screen does not come up let me know and we can space it out more - Works on the devices I tested. There will be a brief time (around 15ms) that the screen is all white after coming back on.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17498 a1c6a512-1295-4272-9138-f99709370657
| -rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | 249 |
1 files changed, 144 insertions, 105 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c index 90ab145..5c666b4 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c +++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c @@ -66,17 +66,55 @@ inline void delay_cycles(volatile int delay) while(delay>0) delay--; } -void SPI_LCD_CS(bool select) +void LCD_CTRL_setup(void) { - delay_cycles(0x4FFF); + /* ENVID = 0, BPPMODE = 16 bpp, PNRMODE = TFT, MMODE = Each Frame, CLKVAL = 8 */ + LCDCON1 = 0x878; - GPBCON&=~0x30000; - GPBCON|=0x10000; + /* VCPW = 1, VFPD = 5, LINEVAL = 319, VBPD = 7 */ + LCDCON2 = 0x74FC141; + + /* HFPD = 9, HOZVAL = 239, HBPD = 7 */ + LCDCON3 = 0x38EF09; - if(select) - GPBDAT|=0x100; - else - GPBDAT&=~0x100; + /* HSPW = 7 */ + LCDCON4 = 7; + + /* HWSWP = 1, INVVFRAM = 1, INVVLINE = 1, FRM565 = 1, All others = 0 */ + LCDCON5 = 0xB01; + + LCDSADDR1 = (LCDBANK((unsigned)FRAME) << 21) | (LCDBASEU((unsigned)FRAME)); + LCDSADDR2 = LCDBASEL((unsigned)FRAME); + LCDSADDR3 = 0x000000F0; +} + +void LCD_CTRL_clock(bool onoff) +{ + if(onoff) + { + GPCCON &= ~0xFFF000FC; + GPDCON &= ~0xFFF0FFF0; + + GPCCON |= 0xAAA000A8; + GPCUP |= 0xFC0E; + + GPDCON |= 0xAAA0AAA0; + GPDUP |= 0xFCFC; + + s3c_regset(&CLKCON, 0x20); /* enable LCD clock */ + LCDCON1 |=0x01; + } + else + { + GPCCON &= ~0xFFF000FC; + GPCUP &= ~0xFC0E; + + GPDCON &= ~0xFFF0FFF0; + GPDUP &= ~0xFCFC; + + LCDCON1 &= ~1; /* Must diable first or bus may freeze */ + s3c_regclr(&CLKCON, 0x20); /* disable LCD clock */ + } } void reset_LCD(bool reset) @@ -89,7 +127,7 @@ void reset_LCD(bool reset) GPBDAT&=~0x80; } -void SPI_Send_Bytes(const unsigned char *array, int count) +void LCD_SPI_send(const unsigned char *array, int count) { while (count--) { @@ -98,97 +136,80 @@ void SPI_Send_Bytes(const unsigned char *array, int count) } } -void Setup_LCD_SPI(void) +void LCD_SPI_SS(bool select) { - s3c_regset(&CLKCON, 0x40000); - SPI_LCD_CS(false); - SPCON0=0x3E; - SPPRE0=24; -} + delay_cycles(0x4FFF); -void Setup_LCD_CTRL(void) -{ - /* ENVID = 0, BPPMODE = 16 bpp, PNRMODE = TFT, MMODE = Each Frame, CLKVAL = 8 */ - LCDCON1 = 0x878; + GPBCON&=~0x30000; + GPBCON|=0x10000; - /* VCPW = 1, VFPD = 5, LINEVAL = 319, VBPD = 7 */ - LCDCON2 = 0x74FC141; - - /* HFPD = 9, HOZVAL = 239, HBPD = 7 */ - LCDCON3 = 0x38EF09; + if(select) + GPBDAT|=0x100; + else + GPBDAT&=~0x100; +} - /* HSPW = 7 */ - LCDCON4 = 7; - - /* HWSWP = 1, INVVFRAM = 1, INVVLINE = 1, FRM565 = 1, All others = 0 */ - LCDCON5 = 0xB01; +void LCD_SPI_start(void) +{ + s3c_regset(&CLKCON, 0x40000); /* enable SPI clock */ + LCD_SPI_SS(false); + SPCON0=0x3E; + SPPRE0=24; - LCDSADDR1 = (LCDBANK((unsigned)FRAME) << 21) | (LCDBASEU((unsigned)FRAME)); - LCDSADDR2 = LCDBASEL((unsigned)FRAME); - LCDSADDR3 = 0x000000F0; + reset_LCD(true); + LCD_SPI_SS(true); } -/* LCD init */ -void lcd_init_device(void) +void LCD_SPI_stop(void) { -#ifdef BOOTLOADER - int i; - /* When the Rockbox bootloader starts, we are changing framebuffer address, - but we don't want what's shown on the LCD to change until we do an - lcd_update(), so copy the data from the old framebuffer to the new one */ - unsigned short *buf = (unsigned short*)FRAME; - - memcpy(FRAME, (short *)((LCDSADDR1)<<1), 320*240*2); - - /* The Rockbox bootloader is transitioning from RGB555I to RGB565 mode - so convert the frambuffer data accordingly */ - for(i=0; i< 320*240; i++){ - *buf = ((*buf>>1) & 0x1F) | (*buf & 0xffc0); - buf++; - } -#endif - - /* Set pins up */ - GPCCON |= 0xAAA000A8; - GPCUP |= 0xFC0E; + LCD_SPI_SS(false); - GPDCON |= 0xAAA0AAA0; - GPDUP |= 0xFCFC; + SPCON0 &= ~0x10; + s3c_regclr(&CLKCON, 0x40000); /* disable SPI clock */ +} - GPHUP &= 0x600; +void LCD_SPI_powerdown(void) +{ + const unsigned char powerdncmd[] = + { + 0,0x04,1,0x00 + }; - GPECON |= 0x0A800000; - GPEUP |= 0x3800; + LCD_SPI_start(); - GPBUP |= 0x181; + LCD_SPI_send(powerdncmd, sizeof(powerdncmd)); -#if !defined(BOOTLOADER) - lcd_poweroff = false; -#endif + LCD_SPI_stop(); - s3c_regset(&CLKCON, 0x20); /* enable LCD clock */ + reset_LCD(false); /* This makes a big difference on power */ + LCD_CTRL_clock(false); +} - Setup_LCD_SPI(); +void LCD_SPI_powerup(void) +{ + const unsigned char powerupcmd[] = + { + 0,0x04,1,0x01 + }; - Setup_LCD_CTRL(); + LCD_CTRL_clock(true); - delay_cycles(0xA000); + LCD_SPI_start(); - reset_LCD(true); - LCDCON1|=0x01; + LCD_SPI_send(powerupcmd, sizeof(powerupcmd)); - delay_cycles(0x80000); + LCD_SPI_stop(); +} -#if 0 - /* Setup the appropriate screen modes */ - TCONSEL= 0xCE6; -#endif - - /* SPI data - Right now we are not sure what each of these SPI writes is actually - * telling the lcd. Many thanks to Alex Gerchanovsky for discovering them. +void LCD_SPI_init(void) +{ + /* SPI data - Right now we are not sure what each of these SPI writes is + * actually telling the lcd. Many thanks to Alex Gerchanovsky for + * discovering them. * - * This looks like a register, data combination, 0 denoting a register address, - * 1 denoting data. Addr 0x04 is used more than once and may be an enable. + * This looks like a register, data combination, 0 denoting a register + * address, 1 denoting data. Addr 0x04 is used more than once is + * an enable. */ const unsigned char initbuf[] = { @@ -219,11 +240,51 @@ void lcd_init_device(void) 0,0x04,1,0x01, }; - SPI_LCD_CS(true); - SPI_Send_Bytes(initbuf, sizeof(initbuf)); - SPI_LCD_CS(false); + LCD_CTRL_clock(true); - s3c_regclr(&CLKCON, 0x40000); /* disable SPI clock */ + LCD_SPI_start(); + + LCD_SPI_send(initbuf, sizeof(initbuf)); + + LCD_SPI_stop(); +} + +/* LCD init */ +void lcd_init_device(void) +{ + /* Set pins up */ + + GPHUP &= 0x600; + + GPECON |= 0x0A800000; + GPEUP |= 0x3800; + + GPBUP |= 0x181; + + s3c_regset(&CLKCON, 0x20); /* enable LCD clock */ + + LCD_CTRL_setup(); + LCD_SPI_init(); +} + +void lcd_enable(bool state) +{ + if(state) + { + if(!lcd_on) + { + lcd_on = true; + lcd_update(); + LCD_SPI_powerup(); + } + } + else + { + if(lcd_on) { + lcd_on = false; + LCD_SPI_powerdown(); + } + } } /* Update a fraction of the display. */ @@ -266,28 +327,6 @@ void lcd_update_rect(int x, int y, int width, int height) } } -void lcd_enable(bool state) -{ - if(!lcd_poweroff) - return; - if(state) - { - if(!lcd_on) - { - lcd_on = true; - lcd_update(); - LCDCON1 |= 1; - } - } - else - { - if(lcd_on) { - lcd_on = false; - LCDCON1 &= ~1; - } - } -} - /* Update the display. This must be called after all other LCD functions that change the display. */ void lcd_update(void) |