diff options
author | Barry Wardell <rockbox@barrywardell.net> | 2007-04-23 23:26:23 +0000 |
---|---|---|
committer | Barry Wardell <rockbox@barrywardell.net> | 2007-04-23 23:26:23 +0000 |
commit | 7027c6a0f8ed85c176e77ceb019a282b6b3d69ac (patch) | |
tree | 872ff2cca2dc1ed957ca5508e86575bae54a171d /firmware/target/arm/sandisk/sansa-e200 | |
parent | 27b4a64f9b215bde49e2a50aba51698fd56dbd85 (diff) | |
download | rockbox-7027c6a0f8ed85c176e77ceb019a282b6b3d69ac.tar.gz rockbox-7027c6a0f8ed85c176e77ceb019a282b6b3d69ac.zip |
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
Diffstat (limited to 'firmware/target/arm/sandisk/sansa-e200')
4 files changed, 87 insertions, 33 deletions
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 @@ | |||
22 | #include "system.h" | 22 | #include "system.h" |
23 | #include <string.h> | 23 | #include <string.h> |
24 | #include "thread.h" | 24 | #include "thread.h" |
25 | #include "pp5024.h" | ||
25 | 26 | ||
26 | #define NOINLINE_ATTR __attribute__((noinline)) /* don't inline the loops */ | 27 | #define NOINLINE_ATTR __attribute__((noinline)) /* don't inline the loops */ |
27 | 28 | ||
@@ -359,9 +360,9 @@ void sd_init_device(void) | |||
359 | GPIOD_ENABLE |= (0x1f); | 360 | GPIOD_ENABLE |= (0x1f); |
360 | GPIOD_OUTPUT_EN |= (0x1f); | 361 | GPIOD_OUTPUT_EN |= (0x1f); |
361 | GPIOD_OUTPUT_VAL |= (0x1f); | 362 | GPIOD_OUTPUT_VAL |= (0x1f); |
362 | DEV_EN |= (1 << 14); /* Enable controller */ | 363 | DEV_EN |= DEV_ATA; /* Enable controller */ |
363 | DEV_RS |= (1 << 14); /* Reset controller */ | 364 | DEV_RS |= DEV_ATA; /* Reset controller */ |
364 | DEV_RS &=~(1 << 14); /* Clear Reset */ | 365 | DEV_RS &=~DEV_ATA; /* Clear Reset */ |
365 | outl(0, 0x6000b000); | 366 | outl(0, 0x6000b000); |
366 | outl(0, 0x6000a000); /* Init DMA controller? */ | 367 | outl(0, 0x6000a000); /* Init DMA controller? */ |
367 | 368 | ||
@@ -478,6 +479,7 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
478 | last_disk_activity = current_tick; | 479 | last_disk_activity = current_tick; |
479 | spinup_start = current_tick; | 480 | spinup_start = current_tick; |
480 | 481 | ||
482 | ata_enable(true); | ||
481 | ata_led(true); | 483 | ata_led(true); |
482 | 484 | ||
483 | timeout = current_tick + READ_TIMEOUT; | 485 | timeout = current_tick + READ_TIMEOUT; |
@@ -528,6 +530,7 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
528 | break; | 530 | break; |
529 | } | 531 | } |
530 | ata_led(false); | 532 | ata_led(false); |
533 | ata_enable(false); | ||
531 | 534 | ||
532 | mutex_unlock(&sd_mtx); | 535 | mutex_unlock(&sd_mtx); |
533 | 536 | ||
@@ -551,6 +554,7 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
551 | tSDCardInfo *card = &card_info[current_card]; | 554 | tSDCardInfo *card = &card_info[current_card]; |
552 | 555 | ||
553 | mutex_lock(&sd_mtx); | 556 | mutex_lock(&sd_mtx); |
557 | ata_enable(true); | ||
554 | ata_led(true); | 558 | ata_led(true); |
555 | if(current_card == 0) | 559 | if(current_card == 0) |
556 | { | 560 | { |
@@ -603,8 +607,10 @@ retry: | |||
603 | sd_read_response(&response, 1); | 607 | sd_read_response(&response, 1); |
604 | 608 | ||
605 | sd_wait_for_state(card, TRAN); | 609 | sd_wait_for_state(card, TRAN); |
606 | mutex_unlock(&sd_mtx); | ||
607 | ata_led(false); | 610 | ata_led(false); |
611 | ata_enable(false); | ||
612 | mutex_unlock(&sd_mtx); | ||
613 | |||
608 | return ret; | 614 | return ret; |
609 | } | 615 | } |
610 | 616 | ||
@@ -667,7 +673,14 @@ int ata_soft_reset(void) | |||
667 | 673 | ||
668 | void ata_enable(bool on) | 674 | void ata_enable(bool on) |
669 | { | 675 | { |
670 | (void)on; | 676 | if(on) |
677 | { | ||
678 | DEV_EN |= DEV_ATA; /* Enable controller */ | ||
679 | } | ||
680 | else | ||
681 | { | ||
682 | DEV_EN &= ~DEV_ATA; /* Disable controller */ | ||
683 | } | ||
671 | } | 684 | } |
672 | 685 | ||
673 | unsigned short* ata_get_identify(void) | 686 | 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 @@ | |||
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include "backlight-target.h" | 19 | #include "backlight-target.h" |
20 | #include "system.h" | 20 | #include "system.h" |
21 | #include "lcd.h" | ||
21 | #include "backlight.h" | 22 | #include "backlight.h" |
22 | #include "i2c-pp.h" | 23 | #include "i2c-pp.h" |
23 | 24 | ||
24 | static unsigned short backlight_brightness; | 25 | static unsigned short backlight_brightness; |
26 | static bool backlight_is_on; | ||
27 | |||
28 | int __backlight_is_on(void) | ||
29 | { | ||
30 | return (int)backlight_is_on; | ||
31 | } | ||
25 | 32 | ||
26 | void __backlight_set_brightness(int brightness) | 33 | void __backlight_set_brightness(int brightness) |
27 | { | 34 | { |
28 | backlight_brightness = brightness; | 35 | backlight_brightness = brightness; |
29 | pp_i2c_send( 0x46, 0x23, backlight_brightness); | 36 | pp_i2c_send( 0x46, 0x23, backlight_brightness); |
37 | backlight_is_on = true; | ||
30 | } | 38 | } |
31 | 39 | ||
32 | void __backlight_on(void) | 40 | void __backlight_on(void) |
33 | { | 41 | { |
42 | lcd_enable(true); /* power on lcd */ | ||
34 | pp_i2c_send( 0x46, 0x23, backlight_brightness); | 43 | pp_i2c_send( 0x46, 0x23, backlight_brightness); |
44 | backlight_is_on = true; | ||
35 | } | 45 | } |
36 | 46 | ||
37 | void __backlight_off(void) | 47 | void __backlight_off(void) |
38 | { | 48 | { |
39 | pp_i2c_send( 0x46, 0x23, 0x0); | 49 | pp_i2c_send( 0x46, 0x23, 0x0); |
50 | lcd_enable(false); /* power off lcd */ | ||
51 | backlight_is_on = false; | ||
40 | } | 52 | } |
41 | 53 | ||
42 | 54 | ||
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 @@ | |||
23 | void __backlight_on(void); | 23 | void __backlight_on(void); |
24 | void __backlight_off(void); | 24 | void __backlight_off(void); |
25 | void __backlight_set_brightness(int brightness); | 25 | void __backlight_set_brightness(int brightness); |
26 | int __backlight_is_on(void); | ||
26 | 27 | ||
27 | void __button_backlight_on(void); | 28 | void __button_backlight_on(void); |
28 | void __button_backlight_off(void); | 29 | 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 @@ | |||
23 | #include "lcd.h" | 23 | #include "lcd.h" |
24 | #include "system.h" | 24 | #include "system.h" |
25 | #include <string.h> | 25 | #include <string.h> |
26 | #include "backlight-target.h" | ||
27 | #include "pp5024.h" | ||
26 | 28 | ||
27 | #define LCD_DATA_IN_GPIO GPIOB_INPUT_VAL | 29 | #define LCD_DATA_IN_GPIO GPIOB_INPUT_VAL |
28 | #define LCD_DATA_IN_PIN 6 | 30 | #define LCD_DATA_IN_PIN 6 |
@@ -141,12 +143,12 @@ inline void lcd_init_device(void) | |||
141 | outl(((inl(0x70000010) & (0x03ffffff)) | (0x15 << 26)), 0x70000010); | 143 | outl(((inl(0x70000010) & (0x03ffffff)) | (0x15 << 26)), 0x70000010); |
142 | outl(((inl(0x70000014) & (0x0fffffff)) | (0x5 << 28)), 0x70000014); | 144 | outl(((inl(0x70000014) & (0x0fffffff)) | (0x5 << 28)), 0x70000014); |
143 | outl((inl(0x70000020) & ~(0x3 << 10)), 0x70000020); | 145 | outl((inl(0x70000020) & ~(0x3 << 10)), 0x70000020); |
144 | DEV_EN |= (1 << 26); /* Enable controller */ | 146 | DEV_EN |= DEV_LCD; /* Enable controller */ |
145 | outl(0x6, 0x600060d0); | 147 | outl(0x6, 0x600060d0); |
146 | DEV_RS |= (1 << 26); /* Reset controller */ | 148 | DEV_RS |= DEV_LCD; /* Reset controller */ |
147 | outl((inl(0x70000020) & ~(1 << 14)), 0x70000020); | 149 | outl((inl(0x70000020) & ~(1 << 14)), 0x70000020); |
148 | lcd_bus_idle(); | 150 | lcd_bus_idle(); |
149 | DEV_RS &=~(1 << 26); /* Clear reset */ | 151 | DEV_RS &=~DEV_LCD; /* Clear reset */ |
150 | udelay(1000); | 152 | udelay(1000); |
151 | 153 | ||
152 | LCD_REG_0 = (LCD_REG_0 & (0x00ffffff)) | (0x22 << 24); | 154 | LCD_REG_0 = (LCD_REG_0 & (0x00ffffff)) | (0x22 << 24); |
@@ -247,40 +249,66 @@ inline void lcd_init_device(void) | |||
247 | lcd_send_msg(0x70, 34); | 249 | lcd_send_msg(0x70, 34); |
248 | } | 250 | } |
249 | 251 | ||
252 | void lcd_enable(bool on) | ||
253 | { | ||
254 | if(on) | ||
255 | { | ||
256 | DEV_EN |= DEV_LCD; /* Enable LCD controller */ | ||
257 | LCD_REG_6 |= 1; /* Enable DMA */ | ||
258 | } | ||
259 | else | ||
260 | { | ||
261 | if(DEV_EN & DEV_LCD) | ||
262 | { | ||
263 | LCD_REG_6 &= ~1; /* Disable DMA */ | ||
264 | udelay(20000); /* Wait for dma end (assuming 50Hz) */ | ||
265 | DEV_EN &= ~DEV_LCD; /* Disable LCD controller */ | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
250 | inline void lcd_update_rect(int x, int y, int width, int height) | 270 | inline void lcd_update_rect(int x, int y, int width, int height) |
251 | { | 271 | { |
252 | (void)x; | 272 | (void)x; |
253 | (void)width; | 273 | (void)width; |
254 | /* Turn off DMA and wait for the transfer to complete */ | ||
255 | /* TODO: Work out the proper delay */ | ||
256 | LCD_REG_6 &= ~1; | ||
257 | udelay(1000); | ||
258 | |||
259 | /* Copy the Rockbox framebuffer to the second framebuffer */ | ||
260 | /* TODO: Move the second framebuffer into uncached SDRAM */ | ||
261 | memcpy(((char*)&lcd_driver_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), | ||
262 | ((char *)&lcd_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), | ||
263 | ((height * sizeof(fb_data) * LCD_WIDTH))); | ||
264 | flush_icache(); | ||
265 | 274 | ||
266 | /* Restart DMA */ | 275 | if(__backlight_is_on()) |
267 | LCD_REG_6 |= 1; | 276 | { |
277 | /* Turn off DMA and wait for the transfer to complete */ | ||
278 | /* TODO: Work out the proper delay */ | ||
279 | LCD_REG_6 &= ~1; | ||
280 | udelay(1000); | ||
281 | |||
282 | /* Copy the Rockbox framebuffer to the second framebuffer */ | ||
283 | /* TODO: Move the second framebuffer into uncached SDRAM */ | ||
284 | memcpy(((char*)&lcd_driver_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), | ||
285 | ((char *)&lcd_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), | ||
286 | ((height * sizeof(fb_data) * LCD_WIDTH))); | ||
287 | flush_icache(); | ||
288 | |||
289 | /* Restart DMA */ | ||
290 | LCD_REG_6 |= 1; | ||
291 | } | ||
268 | } | 292 | } |
269 | 293 | ||
270 | inline void lcd_update(void) | 294 | inline void lcd_update(void) |
271 | { | 295 | { |
272 | /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer | 296 | if(__backlight_is_on()) |
273 | * and lcd_framebuffer */ | 297 | { |
274 | /* Turn off DMA and wait for the transfer to complete */ | 298 | /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer |
275 | LCD_REG_6 &= ~1; | 299 | * and lcd_framebuffer */ |
276 | udelay(1000); | 300 | /* Turn off DMA and wait for the transfer to complete */ |
277 | 301 | LCD_REG_6 &= ~1; | |
278 | /* Copy the Rockbox framebuffer to the second framebuffer */ | 302 | udelay(1000); |
279 | memcpy(lcd_driver_framebuffer, lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT); | 303 | |
280 | flush_icache(); | 304 | /* Copy the Rockbox framebuffer to the second framebuffer */ |
281 | 305 | memcpy(lcd_driver_framebuffer, lcd_framebuffer, | |
282 | /* Restart DMA */ | 306 | sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT); |
283 | LCD_REG_6 |= 1; | 307 | flush_icache(); |
308 | |||
309 | /* Restart DMA */ | ||
310 | LCD_REG_6 |= 1; | ||
311 | } | ||
284 | } | 312 | } |
285 | 313 | ||
286 | 314 | ||