From 7027c6a0f8ed85c176e77ceb019a282b6b3d69ac Mon Sep 17 00:00:00 2001 From: Barry Wardell Date: Mon, 23 Apr 2007 23:26:23 +0000 Subject: FS#7036: Power saving improvements for Sansa. Shutdown LCD controller when backlight is off and shutdown ATA controller when the disk isn't being accessed. Frequency scaling is not enabled yet as it was apparently causing some problems. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13250 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/config-e200.h | 5 +- firmware/export/pp5020.h | 2 + firmware/target/arm/sandisk/sansa-e200/ata-e200.c | 23 ++++-- .../target/arm/sandisk/sansa-e200/backlight-e200.c | 12 ++++ .../arm/sandisk/sansa-e200/backlight-target.h | 1 + firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | 84 ++++++++++++++-------- 6 files changed, 93 insertions(+), 34 deletions(-) diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h index 87d7e78fbb..c61b1376d5 100644 --- a/firmware/export/config-e200.h +++ b/firmware/export/config-e200.h @@ -16,6 +16,9 @@ /* define this if you have a colour LCD */ #define HAVE_LCD_COLOR +/* define this if you have LCD enable function */ +#define HAVE_LCD_ENABLE + #define HAVE_BACKLIGHT_BRIGHTNESS /* Main LCD backlight brightness range and defaults */ #define MIN_BRIGHTNESS_SETTING 1 @@ -125,7 +128,7 @@ #define CONFIG_LED LED_VIRTUAL /* Define this if you have adjustable CPU frequency */ -/*#define HAVE_ADJUSTABLE_CPU_FREQ Let's say we don't for now*/ +/*#define HAVE_ADJUSTABLE_CPU_FREQ*/ #define BOOTFILE_EXT "mi4" #define BOOTFILE "rockbox." BOOTFILE_EXT diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h index 8f70794c79..7475cc7b61 100644 --- a/firmware/export/pp5020.h +++ b/firmware/export/pp5020.h @@ -123,11 +123,13 @@ #define DEV_SER1 0x80 #define DEV_I2S 0x800 #define DEV_I2C 0x1000 +#define DEV_ATA 0x4000 #define DEV_OPTO 0x10000 #define DEV_PIEZO 0x10000 #define DEV_USB 0x400000 #define DEV_FIREWIRE 0x800000 #define DEV_IDE0 0x2000000 +#define DEV_LCD 0x4000000 /* Processors Control */ #define CPU_CTL (*(volatile unsigned long *)(0x60007000)) diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c index 3d6cb23d9c..b66984bec4 100644 --- a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c @@ -22,6 +22,7 @@ #include "system.h" #include #include "thread.h" +#include "pp5024.h" #define NOINLINE_ATTR __attribute__((noinline)) /* don't inline the loops */ @@ -359,9 +360,9 @@ void sd_init_device(void) GPIOD_ENABLE |= (0x1f); GPIOD_OUTPUT_EN |= (0x1f); GPIOD_OUTPUT_VAL |= (0x1f); - DEV_EN |= (1 << 14); /* Enable controller */ - DEV_RS |= (1 << 14); /* Reset controller */ - DEV_RS &=~(1 << 14); /* Clear Reset */ + DEV_EN |= DEV_ATA; /* Enable controller */ + DEV_RS |= DEV_ATA; /* Reset controller */ + DEV_RS &=~DEV_ATA; /* Clear Reset */ outl(0, 0x6000b000); outl(0, 0x6000a000); /* Init DMA controller? */ @@ -478,6 +479,7 @@ int ata_read_sectors(IF_MV2(int drive,) last_disk_activity = current_tick; spinup_start = current_tick; + ata_enable(true); ata_led(true); timeout = current_tick + READ_TIMEOUT; @@ -528,6 +530,7 @@ int ata_read_sectors(IF_MV2(int drive,) break; } ata_led(false); + ata_enable(false); mutex_unlock(&sd_mtx); @@ -551,6 +554,7 @@ int ata_write_sectors(IF_MV2(int drive,) tSDCardInfo *card = &card_info[current_card]; mutex_lock(&sd_mtx); + ata_enable(true); ata_led(true); if(current_card == 0) { @@ -603,8 +607,10 @@ retry: sd_read_response(&response, 1); sd_wait_for_state(card, TRAN); - mutex_unlock(&sd_mtx); ata_led(false); + ata_enable(false); + mutex_unlock(&sd_mtx); + return ret; } @@ -667,7 +673,14 @@ int ata_soft_reset(void) void ata_enable(bool on) { - (void)on; + if(on) + { + DEV_EN |= DEV_ATA; /* Enable controller */ + } + else + { + DEV_EN &= ~DEV_ATA; /* Disable controller */ + } } unsigned short* ata_get_identify(void) diff --git a/firmware/target/arm/sandisk/sansa-e200/backlight-e200.c b/firmware/target/arm/sandisk/sansa-e200/backlight-e200.c index 19ef7dd8ed..bb67b5b489 100644 --- a/firmware/target/arm/sandisk/sansa-e200/backlight-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/backlight-e200.c @@ -18,25 +18,37 @@ ****************************************************************************/ #include "backlight-target.h" #include "system.h" +#include "lcd.h" #include "backlight.h" #include "i2c-pp.h" static unsigned short backlight_brightness; +static bool backlight_is_on; + +int __backlight_is_on(void) +{ + return (int)backlight_is_on; +} void __backlight_set_brightness(int brightness) { backlight_brightness = brightness; pp_i2c_send( 0x46, 0x23, backlight_brightness); + backlight_is_on = true; } void __backlight_on(void) { + lcd_enable(true); /* power on lcd */ pp_i2c_send( 0x46, 0x23, backlight_brightness); + backlight_is_on = true; } void __backlight_off(void) { pp_i2c_send( 0x46, 0x23, 0x0); + lcd_enable(false); /* power off lcd */ + backlight_is_on = false; } diff --git a/firmware/target/arm/sandisk/sansa-e200/backlight-target.h b/firmware/target/arm/sandisk/sansa-e200/backlight-target.h index 2227278985..ac256036b9 100644 --- a/firmware/target/arm/sandisk/sansa-e200/backlight-target.h +++ b/firmware/target/arm/sandisk/sansa-e200/backlight-target.h @@ -23,6 +23,7 @@ void __backlight_on(void); void __backlight_off(void); void __backlight_set_brightness(int brightness); +int __backlight_is_on(void); void __button_backlight_on(void); void __button_backlight_off(void); diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c index 9f6cf7fc11..07bc72c3c1 100644 --- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c @@ -23,6 +23,8 @@ #include "lcd.h" #include "system.h" #include +#include "backlight-target.h" +#include "pp5024.h" #define LCD_DATA_IN_GPIO GPIOB_INPUT_VAL #define LCD_DATA_IN_PIN 6 @@ -141,12 +143,12 @@ inline void lcd_init_device(void) outl(((inl(0x70000010) & (0x03ffffff)) | (0x15 << 26)), 0x70000010); outl(((inl(0x70000014) & (0x0fffffff)) | (0x5 << 28)), 0x70000014); outl((inl(0x70000020) & ~(0x3 << 10)), 0x70000020); - DEV_EN |= (1 << 26); /* Enable controller */ + DEV_EN |= DEV_LCD; /* Enable controller */ outl(0x6, 0x600060d0); - DEV_RS |= (1 << 26); /* Reset controller */ + DEV_RS |= DEV_LCD; /* Reset controller */ outl((inl(0x70000020) & ~(1 << 14)), 0x70000020); lcd_bus_idle(); - DEV_RS &=~(1 << 26); /* Clear reset */ + DEV_RS &=~DEV_LCD; /* Clear reset */ udelay(1000); LCD_REG_0 = (LCD_REG_0 & (0x00ffffff)) | (0x22 << 24); @@ -247,40 +249,66 @@ inline void lcd_init_device(void) lcd_send_msg(0x70, 34); } +void lcd_enable(bool on) +{ + if(on) + { + DEV_EN |= DEV_LCD; /* Enable LCD controller */ + LCD_REG_6 |= 1; /* Enable DMA */ + } + else + { + if(DEV_EN & DEV_LCD) + { + LCD_REG_6 &= ~1; /* Disable DMA */ + udelay(20000); /* Wait for dma end (assuming 50Hz) */ + DEV_EN &= ~DEV_LCD; /* Disable LCD controller */ + } + } +} + inline void lcd_update_rect(int x, int y, int width, int height) { (void)x; (void)width; - /* Turn off DMA and wait for the transfer to complete */ - /* TODO: Work out the proper delay */ - LCD_REG_6 &= ~1; - udelay(1000); - - /* Copy the Rockbox framebuffer to the second framebuffer */ - /* TODO: Move the second framebuffer into uncached SDRAM */ - memcpy(((char*)&lcd_driver_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), - ((char *)&lcd_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), - ((height * sizeof(fb_data) * LCD_WIDTH))); - flush_icache(); - /* Restart DMA */ - LCD_REG_6 |= 1; + if(__backlight_is_on()) + { + /* Turn off DMA and wait for the transfer to complete */ + /* TODO: Work out the proper delay */ + LCD_REG_6 &= ~1; + udelay(1000); + + /* Copy the Rockbox framebuffer to the second framebuffer */ + /* TODO: Move the second framebuffer into uncached SDRAM */ + memcpy(((char*)&lcd_driver_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), + ((char *)&lcd_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), + ((height * sizeof(fb_data) * LCD_WIDTH))); + flush_icache(); + + /* Restart DMA */ + LCD_REG_6 |= 1; + } } inline void lcd_update(void) { - /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer - * and lcd_framebuffer */ - /* Turn off DMA and wait for the transfer to complete */ - LCD_REG_6 &= ~1; - udelay(1000); - - /* Copy the Rockbox framebuffer to the second framebuffer */ - memcpy(lcd_driver_framebuffer, lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT); - flush_icache(); - - /* Restart DMA */ - LCD_REG_6 |= 1; + if(__backlight_is_on()) + { + /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer + * and lcd_framebuffer */ + /* Turn off DMA and wait for the transfer to complete */ + LCD_REG_6 &= ~1; + udelay(1000); + + /* Copy the Rockbox framebuffer to the second framebuffer */ + memcpy(lcd_driver_framebuffer, lcd_framebuffer, + sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT); + flush_icache(); + + /* Restart DMA */ + LCD_REG_6 |= 1; + } } -- cgit v1.2.3