diff options
23 files changed, 537 insertions, 52 deletions
diff --git a/apps/features.txt b/apps/features.txt index 3c0b0a3856..39c8422fbd 100644 --- a/apps/features.txt +++ b/apps/features.txt | |||
@@ -288,3 +288,7 @@ play_frequency | |||
288 | #if defined(HAVE_BOOTDATA) | 288 | #if defined(HAVE_BOOTDATA) |
289 | boot_data | 289 | boot_data |
290 | #endif | 290 | #endif |
291 | |||
292 | #if defined(CONFIG_POWER_SAVING) | ||
293 | sys_powersaving | ||
294 | #endif | ||
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index d4e0697667..fa1b5f2c27 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -13647,3 +13647,54 @@ | |||
13647 | *: "Disable Touch" | 13647 | *: "Disable Touch" |
13648 | </voice> | 13648 | </voice> |
13649 | </phrase> | 13649 | </phrase> |
13650 | <phrase> | ||
13651 | id: LANG_POWER_SAVING_MENU | ||
13652 | desc: system clock and voltage settings | ||
13653 | user: core | ||
13654 | <source> | ||
13655 | *: none | ||
13656 | sys_powersaving: "Power Saving" | ||
13657 | </source> | ||
13658 | <dest> | ||
13659 | *: none | ||
13660 | sys_powersaving: "Power Saving" | ||
13661 | </dest> | ||
13662 | <voice> | ||
13663 | *: none | ||
13664 | sys_powersaving: "Power Saving" | ||
13665 | </voice> | ||
13666 | </phrase> | ||
13667 | <phrase> | ||
13668 | id: LANG_CPU | ||
13669 | desc: system clock and voltage settings | ||
13670 | user: core | ||
13671 | <source> | ||
13672 | *: none | ||
13673 | sys_powersaving: "CPU" | ||
13674 | </source> | ||
13675 | <dest> | ||
13676 | *: none | ||
13677 | sys_powersaving: "CPU" | ||
13678 | </dest> | ||
13679 | <voice> | ||
13680 | *: none | ||
13681 | sys_powersaving: "CPU" | ||
13682 | </voice> | ||
13683 | </phrase> | ||
13684 | <phrase> | ||
13685 | id: LANG_I2C | ||
13686 | desc: system clock and voltage settings | ||
13687 | user: core | ||
13688 | <source> | ||
13689 | *: none | ||
13690 | sys_powersaving: "I2C" | ||
13691 | </source> | ||
13692 | <dest> | ||
13693 | *: none | ||
13694 | sys_powersaving: "I2C" | ||
13695 | </dest> | ||
13696 | <voice> | ||
13697 | *: none | ||
13698 | sys_powersaving: "I2C" | ||
13699 | </voice> | ||
13700 | </phrase> | ||
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c index 5c99cb4cd4..f23f01d4dc 100644 --- a/apps/menus/settings_menu.c +++ b/apps/menus/settings_menu.c | |||
@@ -295,6 +295,36 @@ MAKE_MENU(disk_menu, ID2P(LANG_DISK_MENU), 0, Icon_NOICON, | |||
295 | ); | 295 | ); |
296 | #endif | 296 | #endif |
297 | 297 | ||
298 | #ifdef CONFIG_POWER_SAVING | ||
299 | #if (CONFIG_POWER_SAVING & POWERSV_CPU) | ||
300 | MENUITEM_SETTING(cpu_powersave, &global_settings.cpu_powersave, NULL); | ||
301 | #endif | ||
302 | #if (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
303 | MENUITEM_SETTING(disk_powersave, &global_settings.disk_powersave, NULL); | ||
304 | #endif | ||
305 | #if (CONFIG_POWER_SAVING & POWERSV_I2C) | ||
306 | MENUITEM_SETTING(i2c_powersave, &global_settings.i2c_powersave, NULL); | ||
307 | #endif | ||
308 | #if (CONFIG_POWER_SAVING & POWERSV_DISP) | ||
309 | MENUITEM_SETTING(disp_powersave, &global_settings.disp_powersave, NULL); | ||
310 | #endif | ||
311 | |||
312 | MAKE_MENU(power_save_menu, ID2P(LANG_POWER_SAVING_MENU), 0, Icon_NOICON, | ||
313 | #if (CONFIG_POWER_SAVING & POWERSV_CPU) | ||
314 | &cpu_powersave, | ||
315 | #endif | ||
316 | #if (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
317 | &disk_powersave, | ||
318 | #endif | ||
319 | #if (CONFIG_POWER_SAVING & POWERSV_I2C) | ||
320 | &i2c_powersave, | ||
321 | #endif | ||
322 | #if (CONFIG_POWER_SAVING & POWERSV_DISP) | ||
323 | &disp_powersave, | ||
324 | #endif | ||
325 | ); | ||
326 | #endif /* ifdef CONFIG_POWER_SAVING */ | ||
327 | |||
298 | /* Limits menu */ | 328 | /* Limits menu */ |
299 | MENUITEM_SETTING(max_files_in_dir, &global_settings.max_files_in_dir, NULL); | 329 | MENUITEM_SETTING(max_files_in_dir, &global_settings.max_files_in_dir, NULL); |
300 | MENUITEM_SETTING(max_files_in_playlist, &global_settings.max_files_in_playlist, NULL); | 330 | MENUITEM_SETTING(max_files_in_playlist, &global_settings.max_files_in_playlist, NULL); |
@@ -412,6 +442,11 @@ MAKE_MENU(system_menu, ID2P(LANG_SYSTEM), | |||
412 | &disk_menu, | 442 | &disk_menu, |
413 | #endif | 443 | #endif |
414 | &limits_menu, | 444 | &limits_menu, |
445 | |||
446 | #if defined(CONFIG_POWER_SAVING) | ||
447 | &power_save_menu, | ||
448 | #endif | ||
449 | |||
415 | #ifdef HAVE_QUICKSCREEN | 450 | #ifdef HAVE_QUICKSCREEN |
416 | &shortcuts_replaces_quickscreen, | 451 | &shortcuts_replaces_quickscreen, |
417 | #endif | 452 | #endif |
diff --git a/apps/settings.h b/apps/settings.h index 71233d904a..411675153a 100644 --- a/apps/settings.h +++ b/apps/settings.h | |||
@@ -860,6 +860,25 @@ struct user_settings | |||
860 | int governor; | 860 | int governor; |
861 | int usb_mode; | 861 | int usb_mode; |
862 | #endif | 862 | #endif |
863 | |||
864 | #ifdef CONFIG_POWER_SAVING | ||
865 | #if (CONFIG_POWER_SAVING & POWERSV_CPU) | ||
866 | bool cpu_powersave; | ||
867 | #endif | ||
868 | |||
869 | #if (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
870 | bool disk_powersave; | ||
871 | #endif | ||
872 | |||
873 | #if (CONFIG_POWER_SAVING & POWERSV_I2C) | ||
874 | bool i2c_powersave; | ||
875 | #endif | ||
876 | |||
877 | #if (CONFIG_POWER_SAVING & POWERSV_DISP) | ||
878 | bool disp_powersave; | ||
879 | #endif | ||
880 | #endif /*defined(CONFIG_POWER_SAVING)*/ | ||
881 | |||
863 | }; | 882 | }; |
864 | 883 | ||
865 | /** global variables **/ | 884 | /** global variables **/ |
diff --git a/apps/settings_list.c b/apps/settings_list.c index 57763d345a..fe280b0ff6 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c | |||
@@ -2246,7 +2246,43 @@ const struct settings_list settings[] = { | |||
2246 | ID2P(LANG_IBASSO_USB_MODE_CHARGE), | 2246 | ID2P(LANG_IBASSO_USB_MODE_CHARGE), |
2247 | ID2P(LANG_IBASSO_USB_MODE_ADB)), | 2247 | ID2P(LANG_IBASSO_USB_MODE_ADB)), |
2248 | #endif | 2248 | #endif |
2249 | }; | 2249 | |
2250 | #ifdef CONFIG_POWER_SAVING | ||
2251 | #if (CONFIG_POWER_SAVING & POWERSV_CPU) | ||
2252 | OFFON_SETTING(0, | ||
2253 | cpu_powersave, | ||
2254 | LANG_CPU, | ||
2255 | false, | ||
2256 | "cpu powersave", | ||
2257 | cpu_set_powersave), | ||
2258 | #endif | ||
2259 | #if (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
2260 | OFFON_SETTING(0, | ||
2261 | disk_powersave, | ||
2262 | LANG_DISK_MENU, | ||
2263 | false, | ||
2264 | "disk powersave", | ||
2265 | disk_set_powersave), | ||
2266 | #endif | ||
2267 | #if (CONFIG_POWER_SAVING & POWERSV_DISP) | ||
2268 | OFFON_SETTING(0, | ||
2269 | disp_powersave, | ||
2270 | LANG_DISPLAY, | ||
2271 | false, | ||
2272 | "disp powersave", | ||
2273 | disp_set_powersave), | ||
2274 | #endif | ||
2275 | #if (CONFIG_POWER_SAVING & POWERSV_I2C) | ||
2276 | OFFON_SETTING(0, | ||
2277 | i2c_powersave, | ||
2278 | LANG_I2C, | ||
2279 | false, | ||
2280 | "i2c powersave", | ||
2281 | i2c_set_powersave), | ||
2282 | #endif | ||
2283 | #endif /*defined(CONFIG_POWER_SAVING)*/ | ||
2284 | |||
2285 | };/*struct settings_list settings*/ | ||
2250 | 2286 | ||
2251 | const int nb_settings = sizeof(settings)/sizeof(*settings); | 2287 | const int nb_settings = sizeof(settings)/sizeof(*settings); |
2252 | 2288 | ||
diff --git a/firmware/export/config.h b/firmware/export/config.h index 14664257bf..e362000c18 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h | |||
@@ -168,6 +168,12 @@ | |||
168 | #define SONY_NWZA860_PAD 64 /* The NWZ-A860 is too different (touchscreen) */ | 168 | #define SONY_NWZA860_PAD 64 /* The NWZ-A860 is too different (touchscreen) */ |
169 | #define AGPTEK_ROCKER_PAD 65 | 169 | #define AGPTEK_ROCKER_PAD 65 |
170 | 170 | ||
171 | /* CONFIG_POWER_SAVE combinable bit flags*/ | ||
172 | #define POWERSV_CPU 0x1 | ||
173 | #define POWERSV_I2C 0x2 | ||
174 | #define POWERSV_DISK 0x4 | ||
175 | #define POWERSV_DISP 0x8 | ||
176 | |||
171 | /* CONFIG_REMOTE_KEYPAD */ | 177 | /* CONFIG_REMOTE_KEYPAD */ |
172 | #define H100_REMOTE 1 | 178 | #define H100_REMOTE 1 |
173 | #define H300_REMOTE 2 | 179 | #define H300_REMOTE 2 |
diff --git a/firmware/export/config/sansac200v2.h b/firmware/export/config/sansac200v2.h index a51f9e3b00..98fbb570fb 100644 --- a/firmware/export/config/sansac200v2.h +++ b/firmware/export/config/sansac200v2.h | |||
@@ -193,6 +193,14 @@ | |||
193 | /* Define this if you have adjustable CPU frequency */ | 193 | /* Define this if you have adjustable CPU frequency */ |
194 | #define HAVE_ADJUSTABLE_CPU_FREQ | 194 | #define HAVE_ADJUSTABLE_CPU_FREQ |
195 | 195 | ||
196 | /*define this to enable CPU voltage scaling on AMS devices*/ | ||
197 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE | ||
198 | |||
199 | #ifndef BOOTLOADER | ||
200 | /*define this with flags for power saving options device supports*/ | ||
201 | #define CONFIG_POWER_SAVING (POWERSV_CPU | POWERSV_I2C | POWERSV_DISK) | ||
202 | #endif | ||
203 | |||
196 | #define BOOTFILE_EXT "sansa" | 204 | #define BOOTFILE_EXT "sansa" |
197 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 205 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
198 | #define BOOTDIR "/.rockbox" | 206 | #define BOOTDIR "/.rockbox" |
diff --git a/firmware/export/config/sansaclip.h b/firmware/export/config/sansaclip.h index cdee43d44a..f0300c2ac1 100644 --- a/firmware/export/config/sansaclip.h +++ b/firmware/export/config/sansaclip.h | |||
@@ -186,6 +186,14 @@ | |||
186 | /* Define this if you have adjustable CPU frequency */ | 186 | /* Define this if you have adjustable CPU frequency */ |
187 | #define HAVE_ADJUSTABLE_CPU_FREQ | 187 | #define HAVE_ADJUSTABLE_CPU_FREQ |
188 | 188 | ||
189 | /*define this to enable CPU voltage scaling on AMS devices*/ | ||
190 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE | ||
191 | |||
192 | #ifndef BOOTLOADER | ||
193 | /*define this with flags for power saving options device supports*/ | ||
194 | #define CONFIG_POWER_SAVING (POWERSV_CPU | POWERSV_I2C | POWERSV_DISK) | ||
195 | #endif | ||
196 | |||
189 | #define BOOTFILE_EXT "sansa" | 197 | #define BOOTFILE_EXT "sansa" |
190 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 198 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
191 | #define BOOTDIR "/.rockbox" | 199 | #define BOOTDIR "/.rockbox" |
diff --git a/firmware/export/config/sansaclipplus.h b/firmware/export/config/sansaclipplus.h index addf7d86c0..9a307420f4 100644 --- a/firmware/export/config/sansaclipplus.h +++ b/firmware/export/config/sansaclipplus.h | |||
@@ -206,6 +206,11 @@ | |||
206 | /*define this to enable CPU voltage scaling on AMS devices*/ | 206 | /*define this to enable CPU voltage scaling on AMS devices*/ |
207 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE | 207 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE |
208 | 208 | ||
209 | #ifndef BOOTLOADER | ||
210 | /*define this with flags for power saving options device supports*/ | ||
211 | #define CONFIG_POWER_SAVING (POWERSV_CPU | POWERSV_I2C | POWERSV_DISK | POWERSV_DISP) | ||
212 | #endif | ||
213 | |||
209 | #define BOOTFILE_EXT "sansa" | 214 | #define BOOTFILE_EXT "sansa" |
210 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 215 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
211 | #define BOOTDIR "/.rockbox" | 216 | #define BOOTDIR "/.rockbox" |
diff --git a/firmware/export/config/sansaclipv2.h b/firmware/export/config/sansaclipv2.h index cf3f90e363..81a0d4703f 100644 --- a/firmware/export/config/sansaclipv2.h +++ b/firmware/export/config/sansaclipv2.h | |||
@@ -200,6 +200,11 @@ | |||
200 | /*define this to enable CPU voltage scaling on AMS devices*/ | 200 | /*define this to enable CPU voltage scaling on AMS devices*/ |
201 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE | 201 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE |
202 | 202 | ||
203 | #ifndef BOOTLOADER | ||
204 | /*define this with flags for power saving options device supports*/ | ||
205 | #define CONFIG_POWER_SAVING (POWERSV_CPU | POWERSV_I2C | POWERSV_DISK) | ||
206 | #endif | ||
207 | |||
203 | #define BOOTFILE_EXT "sansa" | 208 | #define BOOTFILE_EXT "sansa" |
204 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 209 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
205 | #define BOOTDIR "/.rockbox" | 210 | #define BOOTDIR "/.rockbox" |
diff --git a/firmware/export/config/sansaclipzip.h b/firmware/export/config/sansaclipzip.h index fc9f558eef..8464603c34 100644 --- a/firmware/export/config/sansaclipzip.h +++ b/firmware/export/config/sansaclipzip.h | |||
@@ -205,6 +205,11 @@ | |||
205 | /*define this to enable CPU voltage scaling on AMS devices*/ | 205 | /*define this to enable CPU voltage scaling on AMS devices*/ |
206 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE | 206 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE |
207 | 207 | ||
208 | #ifndef BOOTLOADER | ||
209 | /*define this with flags for power saving options device supports*/ | ||
210 | #define CONFIG_POWER_SAVING (POWERSV_CPU | POWERSV_I2C | POWERSV_DISK | POWERSV_DISP) | ||
211 | #endif | ||
212 | |||
208 | #define BOOTFILE_EXT "sansa" | 213 | #define BOOTFILE_EXT "sansa" |
209 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 214 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
210 | #define BOOTDIR "/.rockbox" | 215 | #define BOOTDIR "/.rockbox" |
diff --git a/firmware/export/config/sansae200v2.h b/firmware/export/config/sansae200v2.h index 96b51f4e12..50e1843189 100644 --- a/firmware/export/config/sansae200v2.h +++ b/firmware/export/config/sansae200v2.h | |||
@@ -213,6 +213,14 @@ | |||
213 | /* Define this if you have adjustable CPU frequency */ | 213 | /* Define this if you have adjustable CPU frequency */ |
214 | #define HAVE_ADJUSTABLE_CPU_FREQ | 214 | #define HAVE_ADJUSTABLE_CPU_FREQ |
215 | 215 | ||
216 | /*define this to enable CPU voltage scaling on AMS devices*/ | ||
217 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE | ||
218 | |||
219 | #ifndef BOOTLOADER | ||
220 | /*define this with flags for power saving options device supports*/ | ||
221 | #define CONFIG_POWER_SAVING (POWERSV_CPU | POWERSV_I2C | POWERSV_DISK) | ||
222 | #endif | ||
223 | |||
216 | #define BOOTFILE_EXT "sansa" | 224 | #define BOOTFILE_EXT "sansa" |
217 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 225 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
218 | #define BOOTDIR "/.rockbox" | 226 | #define BOOTDIR "/.rockbox" |
diff --git a/firmware/export/config/sansafuze.h b/firmware/export/config/sansafuze.h index fae3463d75..dedf8c44da 100644 --- a/firmware/export/config/sansafuze.h +++ b/firmware/export/config/sansafuze.h | |||
@@ -219,6 +219,14 @@ | |||
219 | /* Define this if you have adjustable CPU frequency */ | 219 | /* Define this if you have adjustable CPU frequency */ |
220 | #define HAVE_ADJUSTABLE_CPU_FREQ | 220 | #define HAVE_ADJUSTABLE_CPU_FREQ |
221 | 221 | ||
222 | /*define this to enable CPU voltage scaling on AMS devices*/ | ||
223 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE | ||
224 | |||
225 | #ifndef BOOTLOADER | ||
226 | /*define this with flags for power saving options device supports*/ | ||
227 | #define CONFIG_POWER_SAVING (POWERSV_CPU | POWERSV_I2C | POWERSV_DISK) | ||
228 | #endif | ||
229 | |||
222 | #define BOOTFILE_EXT "sansa" | 230 | #define BOOTFILE_EXT "sansa" |
223 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 231 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
224 | #define BOOTDIR "/.rockbox" | 232 | #define BOOTDIR "/.rockbox" |
diff --git a/firmware/export/config/sansafuzev2.h b/firmware/export/config/sansafuzev2.h index b85e0747a3..3190930b56 100644 --- a/firmware/export/config/sansafuzev2.h +++ b/firmware/export/config/sansafuzev2.h | |||
@@ -224,6 +224,11 @@ | |||
224 | /*define this to enable CPU voltage scaling on AMS devices*/ | 224 | /*define this to enable CPU voltage scaling on AMS devices*/ |
225 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE | 225 | #define HAVE_ADJUSTABLE_CPU_VOLTAGE |
226 | 226 | ||
227 | #ifndef BOOTLOADER | ||
228 | /*define this with flags for power saving options device supports*/ | ||
229 | #define CONFIG_POWER_SAVING (POWERSV_CPU | POWERSV_I2C | POWERSV_DISK) | ||
230 | #endif | ||
231 | |||
227 | #define BOOTFILE_EXT "sansa" | 232 | #define BOOTFILE_EXT "sansa" |
228 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 233 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
229 | #define BOOTDIR "/.rockbox" | 234 | #define BOOTDIR "/.rockbox" |
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c index 14c3ee7a36..d23859e420 100644 --- a/firmware/target/arm/as3525/ascodec-as3525.c +++ b/firmware/target/arm/as3525/ascodec-as3525.c | |||
@@ -623,11 +623,25 @@ void i2c_init(void) | |||
623 | /* required function but called too late for our needs */ | 623 | /* required function but called too late for our needs */ |
624 | } | 624 | } |
625 | 625 | ||
626 | static void i2c_set_prescaler(unsigned int prescaler) | ||
627 | { | ||
628 | int oldlevel = disable_interrupt_save(IRQ_FIQ_STATUS); | ||
629 | /* must be on to write regs */ | ||
630 | bool i2c_enabled = bitset32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE) & | ||
631 | CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE; | ||
632 | |||
633 | I2C2_CPSR0 = prescaler & 0xFF; /* 8 lsb */ | ||
634 | I2C2_CPSR1 = (prescaler >> 8) & 0x3; /* 2 msb */ | ||
635 | |||
636 | if (!i2c_enabled) /* put it back how we found it */ | ||
637 | bitclr32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE); | ||
638 | |||
639 | restore_irq(oldlevel); | ||
640 | } | ||
641 | |||
626 | /* initialises the internal i2c bus and prepares for transfers to the codec */ | 642 | /* initialises the internal i2c bus and prepares for transfers to the codec */ |
627 | void ascodec_init(void) | 643 | void ascodec_init(void) |
628 | { | 644 | { |
629 | int prescaler; | ||
630 | |||
631 | ll_init(&req_list); | 645 | ll_init(&req_list); |
632 | mutex_init(&as_mtx); | 646 | mutex_init(&as_mtx); |
633 | ascodec_async_init(&as_audio_req, ascodec_int_audio_cb, 0); | 647 | ascodec_async_init(&as_audio_req, ascodec_int_audio_cb, 0); |
@@ -637,9 +651,7 @@ void ascodec_init(void) | |||
637 | bitset32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE); | 651 | bitset32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE); |
638 | 652 | ||
639 | /* prescaler for i2c clock */ | 653 | /* prescaler for i2c clock */ |
640 | prescaler = AS3525_I2C_PRESCALER; | 654 | i2c_set_prescaler(AS3525_I2C_PRESCALER); |
641 | I2C2_CPSR0 = prescaler & 0xFF; /* 8 lsb */ | ||
642 | I2C2_CPSR1 = (prescaler >> 8) & 0x3; /* 2 msb */ | ||
643 | 655 | ||
644 | /* set i2c slave address of codec part */ | 656 | /* set i2c slave address of codec part */ |
645 | I2C2_SLAD0 = AS3514_I2C_ADDR << 1; | 657 | I2C2_SLAD0 = AS3514_I2C_ADDR << 1; |
@@ -690,3 +702,12 @@ void ams_i2c_get_debug_cpsr(unsigned int *i2c_cpsr) | |||
690 | 702 | ||
691 | restore_irq(oldlevel); | 703 | restore_irq(oldlevel); |
692 | } | 704 | } |
705 | |||
706 | #if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_I2C) | ||
707 | /* declared in system-as3525.c */ | ||
708 | void ams_i2c_set_low_speed(bool slow) | ||
709 | { | ||
710 | i2c_set_prescaler(slow ? AS3525_I2C_PRESCALER_MAX : AS3525_I2C_PRESCALER); | ||
711 | } | ||
712 | #endif | ||
713 | |||
diff --git a/firmware/target/arm/as3525/clock-target.h b/firmware/target/arm/as3525/clock-target.h index 7f6b17eff4..c45529dfda 100644 --- a/firmware/target/arm/as3525/clock-target.h +++ b/firmware/target/arm/as3525/clock-target.h | |||
@@ -158,22 +158,32 @@ | |||
158 | #endif /* CONFIG_CPU */ | 158 | #endif /* CONFIG_CPU */ |
159 | 159 | ||
160 | /* PCLK as Source */ | 160 | /* PCLK as Source */ |
161 | #define AS3525_DBOP_DIV (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1) /*div=1/(n+1)*/ | 161 | #define AS3525_DBOP_DIV (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1) /*div=1/(n+1)*/ |
162 | #define AS3525_I2C_PRESCALER CLK_DIV(AS3525_PCLK_FREQ, AS3525_I2C_FREQ) | 162 | #define AS3525_I2C_PRESCALER CLK_DIV(AS3525_PCLK_FREQ, AS3525_I2C_FREQ) |
163 | #define AS3525_I2C_FREQ 400000 | 163 | #define AS3525_I2C_PRESCALER_MAX 0xFF | 0x300 /* Max value for prescaler */ |
164 | #define AS3525_SD_IDENT_DIV ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1) | 164 | #define AS3525_I2C_FREQ 400000 |
165 | #define AS3525_SD_IDENT_FREQ 400000 /* must be between 100 & 400 kHz */ | 165 | #define AS3525_SD_IDENT_DIV ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1) |
166 | #define AS3525_SSP_PRESCALER ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SSP_FREQ) + 1) & ~1) /* must be an even number */ | 166 | #define AS3525_SD_IDENT_FREQ 400000 /* must be between 100 & 400 kHz */ |
167 | #define AS3525_SSP_FREQ 12000000 | 167 | #define AS3525_SSP_PRESCALER ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SSP_FREQ) + 1) & ~1) /* must be an even number */ |
168 | #if LCD_DEPTH > 1 | ||
169 | #define AS3525_SSP_PRESCALER_MAX ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SSP_FREQ_MIN) + 1) & ~1)/* must be an even number */ | ||
170 | #define AS3525_SSP_FREQ_MIN 2000000 /* 2 MHz gives a decent refresh rate on clipzip*/ | ||
171 | #else | ||
172 | #define AS3525_SSP_PRESCALER_MAX 0xFE & ~1 /*Max value for divider - must be an even number */ | ||
173 | #define AS3525_SSP_FREQ_MIN AS3525_SSP_FREQ /* No set minimum we just use max divider */ | ||
174 | #endif | ||
175 | #define AS3525_SSP_FREQ 12000000 | ||
168 | 176 | ||
169 | #define AS3525_IDE_SEL AS3525_CLK_PLLA /* Input Source */ | 177 | #define AS3525_IDE_SEL AS3525_CLK_PLLA /* Input Source */ |
170 | #define AS3525_IDE_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1)/*div=1/(n+1)*/ | 178 | #define AS3525_IDE_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1)/*div=1/(n+1)*/ |
179 | #define AS3525_IDE_DIV_MAX 0xF /* Max value for divider */ | ||
171 | 180 | ||
172 | #if CONFIG_CPU == AS3525v2 | 181 | #if CONFIG_CPU == AS3525v2 |
173 | #define AS3525_MS_FREQ 120000000 | 182 | #define AS3525_MS_FREQ 120000000 |
174 | #define AS3525_MS_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_MS_FREQ) -1) | 183 | #define AS3525_MS_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_MS_FREQ) -1) |
175 | #define AS3525_SDSLOT_FREQ 24000000 | 184 | #define AS3525_SDSLOT_FREQ 24000000 |
176 | #define AS3525_SDSLOT_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_SDSLOT_FREQ) -1) | 185 | #define AS3525_SDSLOT_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_SDSLOT_FREQ) -1) |
186 | #define AS3525_SDSLOT_DIV_MAX 0xF /* Max value for divider */ | ||
177 | #define AS3525_IDE_FREQ 80000000 | 187 | #define AS3525_IDE_FREQ 80000000 |
178 | #else | 188 | #else |
179 | #define AS3525_IDE_FREQ 50000000 /* The OF uses 66MHz maximal freq */ | 189 | #define AS3525_IDE_FREQ 50000000 /* The OF uses 66MHz maximal freq */ |
@@ -211,6 +221,10 @@ | |||
211 | #error SSP frequency is too low : clock divider will not fit ! | 221 | #error SSP frequency is too low : clock divider will not fit ! |
212 | #endif | 222 | #endif |
213 | 223 | ||
224 | #if (((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SSP_FREQ_MIN)) + 1 ) & ~1) >= (1<<8) /* 8 bits */ | ||
225 | #error SSP_MIN frequency is too low : clock divider will not fit ! | ||
226 | #endif | ||
227 | |||
214 | /* AS3525_SD_IDENT_FREQ */ | 228 | /* AS3525_SD_IDENT_FREQ */ |
215 | #if ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1) >= (1<<8) /* 8 bits */ | 229 | #if ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1) >= (1<<8) /* 8 bits */ |
216 | #error SD IDENTIFICATION frequency is too low : clock divider will not fit ! | 230 | #error SD IDENTIFICATION frequency is too low : clock divider will not fit ! |
diff --git a/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c b/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c index a50a9e5c80..7c0cfb5345 100644 --- a/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c +++ b/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c | |||
@@ -26,11 +26,25 @@ | |||
26 | #include "system.h" | 26 | #include "system.h" |
27 | #include "cpu.h" | 27 | #include "cpu.h" |
28 | 28 | ||
29 | static void ssp_set_prescaler(unsigned int prescaler) | ||
30 | { | ||
31 | int oldlevel = disable_interrupt_save(IRQ_FIQ_STATUS); | ||
32 | /* must be on to write regs */ | ||
33 | bool ssp_enabled = bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE) & | ||
34 | CGU_SSP_CLOCK_ENABLE; | ||
35 | SSP_CPSR = prescaler; | ||
36 | |||
37 | if (!ssp_enabled) /* put it back how we found it */ | ||
38 | bitclr32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); | ||
39 | |||
40 | restore_irq(oldlevel); | ||
41 | } | ||
42 | |||
29 | int lcd_hw_init(void) | 43 | int lcd_hw_init(void) |
30 | { | 44 | { |
31 | bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); | 45 | bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); |
32 | 46 | ||
33 | SSP_CPSR = AS3525_SSP_PRESCALER; /* OF = 0x10 */ | 47 | ssp_set_prescaler(AS3525_SSP_PRESCALER); /* OF = 0x10 */ |
34 | SSP_CR0 = (1<<7) | (1<<6) | 7; /* Motorola SPI frame format, 8 bits */ | 48 | SSP_CR0 = (1<<7) | (1<<6) | 7; /* Motorola SPI frame format, 8 bits */ |
35 | SSP_CR1 = (1<<3) | (1<<1); /* SSP Operation enabled */ | 49 | SSP_CR1 = (1<<3) | (1<<1); /* SSP Operation enabled */ |
36 | SSP_IMSC = 0; /* No interrupts */ | 50 | SSP_IMSC = 0; /* No interrupts */ |
@@ -115,3 +129,10 @@ void lcd_enable_power(bool onoff) | |||
115 | #endif | 129 | #endif |
116 | } | 130 | } |
117 | 131 | ||
132 | #if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_DISP) | ||
133 | /* declared in system-as3525.c */ | ||
134 | void ams_ssp_set_low_speed(bool slow) | ||
135 | { | ||
136 | ssp_set_prescaler(slow ? AS3525_SSP_PRESCALER_MAX : AS3525_SSP_PRESCALER); | ||
137 | } | ||
138 | #endif | ||
diff --git a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c index e17bfc421b..8a3df517fb 100644 --- a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c +++ b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c | |||
@@ -35,12 +35,26 @@ static int lcd_type; | |||
35 | static bool lcd_enabled; | 35 | static bool lcd_enabled; |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | static void ssp_set_prescaler(unsigned int prescaler) | ||
39 | { | ||
40 | int oldlevel = disable_interrupt_save(IRQ_FIQ_STATUS); | ||
41 | /* must be on to write regs */ | ||
42 | bool ssp_enabled = bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE) & | ||
43 | CGU_SSP_CLOCK_ENABLE; | ||
44 | SSP_CPSR = prescaler; | ||
45 | |||
46 | if (!ssp_enabled) /* put it back how we found it */ | ||
47 | bitclr32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); | ||
48 | |||
49 | restore_irq(oldlevel); | ||
50 | } | ||
51 | |||
38 | /* initialises the host lcd hardware, returns the lcd type */ | 52 | /* initialises the host lcd hardware, returns the lcd type */ |
39 | static int lcd_hw_init(void) | 53 | static int lcd_hw_init(void) |
40 | { | 54 | { |
41 | /* configure SSP */ | 55 | /* configure SSP */ |
42 | bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); | 56 | bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); |
43 | SSP_CPSR = 4; /* TODO: use AS3525_SSP_PRESCALER, OF uses 8 */ | 57 | ssp_set_prescaler(AS3525_SSP_PRESCALER); /* OF = 0x8 */ |
44 | SSP_CR0 = (0 << 8) | /* SCR, serial clock rate divider = 1 */ | 58 | SSP_CR0 = (0 << 8) | /* SCR, serial clock rate divider = 1 */ |
45 | (1 << 7) | /* SPH, phase = 1 */ | 59 | (1 << 7) | /* SPH, phase = 1 */ |
46 | (1 << 6) | /* SPO, polarity = 1 */ | 60 | (1 << 6) | /* SPO, polarity = 1 */ |
@@ -437,3 +451,11 @@ void lcd_update(void) | |||
437 | { | 451 | { |
438 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | 452 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); |
439 | } | 453 | } |
454 | |||
455 | #if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_DISP) | ||
456 | /* declared in system-as3525.c */ | ||
457 | void ams_ssp_set_low_speed(bool slow) | ||
458 | { | ||
459 | ssp_set_prescaler(slow ? AS3525_SSP_PRESCALER_MAX : AS3525_SSP_PRESCALER); | ||
460 | } | ||
461 | #endif | ||
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c index 494a76a782..9e4a86acbe 100644 --- a/firmware/target/arm/as3525/sd-as3525.c +++ b/firmware/target/arm/as3525/sd-as3525.c | |||
@@ -89,6 +89,8 @@ | |||
89 | | MCI_CMD_CRC_FAIL) | 89 | | MCI_CMD_CRC_FAIL) |
90 | 90 | ||
91 | #define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) | 91 | #define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) |
92 | |||
93 | #define IDE_INTERFACE_CLK (1<<6) /* non AHB interface */ | ||
92 | /* volumes */ | 94 | /* volumes */ |
93 | #define INTERNAL_AS3525 0 /* embedded SD card */ | 95 | #define INTERNAL_AS3525 0 /* embedded SD card */ |
94 | #define SD_SLOT_AS3525 1 /* SD slot if present */ | 96 | #define SD_SLOT_AS3525 1 /* SD slot if present */ |
@@ -109,7 +111,8 @@ static void init_pl180_controller(const int drive); | |||
109 | 111 | ||
110 | static tCardInfo card_info[NUM_DRIVES]; | 112 | static tCardInfo card_info[NUM_DRIVES]; |
111 | 113 | ||
112 | /* maximum timeouts recommanded in the SD Specification v2.00 */ | 114 | /* maximum timeouts recommended in the SD Specification v2.00 */ |
115 | /* MCI_DATA_TIMER register data timeout in card bus clock periods */ | ||
113 | #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ | 116 | #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ |
114 | #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ | 117 | #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ |
115 | 118 | ||
@@ -143,7 +146,17 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0]) | |||
143 | 146 | ||
144 | static inline void mci_delay(void) { udelay(1000) ; } | 147 | static inline void mci_delay(void) { udelay(1000) ; } |
145 | 148 | ||
146 | static void enable_controller(bool on) | 149 | static inline bool card_detect_target(void) |
150 | { | ||
151 | #if defined(HAVE_MULTIDRIVE) | ||
152 | return !(GPIOA_PIN(2)); | ||
153 | #else | ||
154 | return false; | ||
155 | #endif | ||
156 | } | ||
157 | |||
158 | #if defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP) | ||
159 | static void enable_controller_mci(bool on) | ||
147 | { | 160 | { |
148 | 161 | ||
149 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | 162 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) |
@@ -197,17 +210,33 @@ static void enable_controller(bool on) | |||
197 | #endif | 210 | #endif |
198 | } | 211 | } |
199 | } | 212 | } |
213 | #endif /* defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP) */ | ||
200 | 214 | ||
201 | static inline bool card_detect_target(void) | 215 | /* AMS v1 have two different drive interfaces MCI_SD(XPD) and GGU_IDE */ |
216 | static void enable_controller(bool on, const int drive) | ||
202 | { | 217 | { |
203 | #if defined(HAVE_MULTIDRIVE) | 218 | |
204 | return !(GPIOA_PIN(2)); | 219 | if (drive == INTERNAL_AS3525) |
205 | #else | 220 | { |
206 | return false; | 221 | #ifndef BOOTLOADER |
222 | if (on) | ||
223 | { | ||
224 | bitset32(&CGU_PERI, CGU_NAF_CLOCK_ENABLE); | ||
225 | CGU_IDE |= IDE_INTERFACE_CLK; /* interface enable */ | ||
226 | } | ||
227 | else | ||
228 | { | ||
229 | CGU_IDE &= ~(IDE_INTERFACE_CLK); /* interface disable */ | ||
230 | bitclr32(&CGU_PERI, CGU_NAF_CLOCK_ENABLE); | ||
231 | } | ||
232 | #endif | ||
233 | } | ||
234 | #if defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP) | ||
235 | else | ||
236 | enable_controller_mci(on); | ||
207 | #endif | 237 | #endif |
208 | } | 238 | } |
209 | 239 | ||
210 | |||
211 | #ifdef HAVE_HOTSWAP | 240 | #ifdef HAVE_HOTSWAP |
212 | static int sd1_oneshot_callback(struct timeout *tmo) | 241 | static int sd1_oneshot_callback(struct timeout *tmo) |
213 | { | 242 | { |
@@ -326,6 +355,7 @@ static bool send_cmd(const int drive, const int cmd, const int arg, | |||
326 | return false; | 355 | return false; |
327 | } | 356 | } |
328 | 357 | ||
358 | /* MCI_CLOCK = MCLK / 2x(ClkDiv[bits 7:0]+1) */ | ||
329 | #define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */ | 359 | #define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */ |
330 | #define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */ | 360 | #define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */ |
331 | #define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */ | 361 | #define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */ |
@@ -345,7 +375,7 @@ static int sd_init_card(const int drive) | |||
345 | /* 100 - 400kHz clock required for Identification Mode */ | 375 | /* 100 - 400kHz clock required for Identification Mode */ |
346 | /* Start of Card Identification Mode ************************************/ | 376 | /* Start of Card Identification Mode ************************************/ |
347 | 377 | ||
348 | /* CMD0 Go Idle */ | 378 | /* CMD0 Go Idle -- all card functions switch back to default */ |
349 | if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) | 379 | if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) |
350 | return -1; | 380 | return -1; |
351 | mci_delay(); | 381 | mci_delay(); |
@@ -393,10 +423,10 @@ static int sd_init_card(const int drive) | |||
393 | 423 | ||
394 | if(sd_wait_for_tran_state(drive)) | 424 | if(sd_wait_for_tran_state(drive)) |
395 | return -6; | 425 | return -6; |
396 | /* CMD6 */ | 426 | /* CMD6 0xf indicates no influence, [3:0],0x1 - HS Access*/ |
397 | if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) | 427 | if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) |
398 | return -7; | 428 | return -7; |
399 | sleep(HZ/10); | 429 | sleep(HZ/10);/* need to wait at least 8 clock periods */ |
400 | 430 | ||
401 | /* go back to STBY state so we can read csd */ | 431 | /* go back to STBY state so we can read csd */ |
402 | /* CMD7 w/rca=0: Deselect card to put it in STBY state */ | 432 | /* CMD7 w/rca=0: Deselect card to put it in STBY state */ |
@@ -517,7 +547,7 @@ static void init_pl180_controller(const int drive) | |||
517 | int sd_init(void) | 547 | int sd_init(void) |
518 | { | 548 | { |
519 | int ret; | 549 | int ret; |
520 | CGU_IDE = (1<<6) /* enable non AHB interface*/ | 550 | CGU_IDE = IDE_INTERFACE_CLK /* enable interface */ |
521 | | (AS3525_IDE_DIV << 2) | 551 | | (AS3525_IDE_DIV << 2) |
522 | | AS3525_CLK_PLLA; /* clock source = PLLA */ | 552 | | AS3525_CLK_PLLA; /* clock source = PLLA */ |
523 | 553 | ||
@@ -540,7 +570,9 @@ int sd_init(void) | |||
540 | /* init mutex */ | 570 | /* init mutex */ |
541 | mutex_init(&sd_mtx); | 571 | mutex_init(&sd_mtx); |
542 | 572 | ||
543 | enable_controller(false); | 573 | for (int i = 0; i < NUM_DRIVES ; i++) |
574 | enable_controller(false, i); | ||
575 | |||
544 | return 0; | 576 | return 0; |
545 | } | 577 | } |
546 | 578 | ||
@@ -656,7 +688,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
656 | unsigned long response; | 688 | unsigned long response; |
657 | bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); | 689 | bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); |
658 | 690 | ||
659 | enable_controller(true); | 691 | enable_controller(true, drive); |
660 | led(true); | 692 | led(true); |
661 | 693 | ||
662 | if (card_info[drive].initialized <= 0) | 694 | if (card_info[drive].initialized <= 0) |
@@ -692,27 +724,21 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
692 | else | 724 | else |
693 | discard_dcache_range(buf, count * SECTOR_SIZE); | 725 | discard_dcache_range(buf, count * SECTOR_SIZE); |
694 | } | 726 | } |
695 | 727 | const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; | |
696 | while(count) | 728 | while(count > 0) |
697 | { | 729 | { |
698 | /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH | 730 | /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH |
699 | * register, so we have to transfer maximum 127 sectors at a time. */ | 731 | * register, so we have to transfer maximum 127 sectors at a time. */ |
700 | unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ | 732 | unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ |
701 | void *dma_buf; | 733 | void *dma_buf; |
702 | const int cmd = | 734 | |
703 | write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; | ||
704 | unsigned long bank_start = start; | 735 | unsigned long bank_start = start; |
705 | unsigned long status; | ||
706 | 736 | ||
707 | /* Only switch banks for internal storage */ | 737 | /* Only switch banks for internal storage */ |
708 | if(drive == INTERNAL_AS3525) | 738 | if(drive == INTERNAL_AS3525) |
709 | { | 739 | { |
710 | unsigned int bank = 0; | 740 | unsigned int bank = bank_start / BLOCKS_PER_BANK; |
711 | while(bank_start >= BLOCKS_PER_BANK) | 741 | bank_start -= bank * BLOCKS_PER_BANK; |
712 | { | ||
713 | bank_start -= BLOCKS_PER_BANK; | ||
714 | bank++; | ||
715 | } | ||
716 | 742 | ||
717 | /* Switch bank if needed */ | 743 | /* Switch bank if needed */ |
718 | if(card_info[INTERNAL_AS3525].current_bank != bank) | 744 | if(card_info[INTERNAL_AS3525].current_bank != bank) |
@@ -770,10 +796,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
770 | /*Small delay for writes prevents data crc failures at lower freqs*/ | 796 | /*Small delay for writes prevents data crc failures at lower freqs*/ |
771 | #ifdef HAVE_MULTIDRIVE | 797 | #ifdef HAVE_MULTIDRIVE |
772 | if((drive == SD_SLOT_AS3525) && !hs_card) | 798 | if((drive == SD_SLOT_AS3525) && !hs_card) |
773 | { | 799 | udelay(4); |
774 | int write_delay = 125; | ||
775 | while(write_delay--); | ||
776 | } | ||
777 | #endif | 800 | #endif |
778 | } | 801 | } |
779 | else | 802 | else |
@@ -804,7 +827,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
804 | 827 | ||
805 | last_disk_activity = current_tick; | 828 | last_disk_activity = current_tick; |
806 | 829 | ||
807 | if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP, &status)) | 830 | if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP, &response)) |
808 | { | 831 | { |
809 | ret = -4*20; | 832 | ret = -4*20; |
810 | goto sd_transfer_error; | 833 | goto sd_transfer_error; |
@@ -831,7 +854,7 @@ sd_transfer_error: | |||
831 | sd_transfer_error_nodma: | 854 | sd_transfer_error_nodma: |
832 | 855 | ||
833 | led(false); | 856 | led(false); |
834 | enable_controller(false); | 857 | enable_controller(false, drive); |
835 | 858 | ||
836 | if (ret) /* error */ | 859 | if (ret) /* error */ |
837 | card_info[drive].initialized = 0; | 860 | card_info[drive].initialized = 0; |
@@ -922,12 +945,18 @@ void ams_sd_get_debug_info(struct ams_sd_debug_info *info) | |||
922 | #define MCI_SD *((volatile unsigned long *)(SD_MCI_BASE + 0x04)) | 945 | #define MCI_SD *((volatile unsigned long *)(SD_MCI_BASE + 0x04)) |
923 | 946 | ||
924 | mutex_lock(&sd_mtx); | 947 | mutex_lock(&sd_mtx); |
925 | enable_controller(true); /* must be on to read regs */ | 948 | |
949 | for (int i = 0; i < NUM_DRIVES ; i++) | ||
950 | enable_controller(true, i); /* must be on to read regs */ | ||
951 | |||
926 | info->mci_nand = MCI_NAND; | 952 | info->mci_nand = MCI_NAND; |
927 | #ifdef HAVE_MULTIDRIVE | 953 | #ifdef HAVE_MULTIDRIVE |
928 | info->mci_sd = MCI_SD; | 954 | info->mci_sd = MCI_SD; |
929 | #endif | 955 | #endif |
930 | enable_controller(false); | 956 | |
957 | for (int i = 0; i < NUM_DRIVES ; i++) | ||
958 | enable_controller(false, i); | ||
959 | |||
931 | mutex_unlock(&sd_mtx); | 960 | mutex_unlock(&sd_mtx); |
932 | } | 961 | } |
933 | 962 | ||
@@ -948,10 +977,10 @@ int sd_event(long id, intptr_t data) | |||
948 | 977 | ||
949 | if (id == SYS_HOTSWAP_INSERTED) | 978 | if (id == SYS_HOTSWAP_INSERTED) |
950 | { | 979 | { |
951 | enable_controller(true); | 980 | enable_controller(true, data); |
952 | init_pl180_controller(data); | 981 | init_pl180_controller(data); |
953 | rc = sd_init_card(data); | 982 | rc = sd_init_card(data); |
954 | enable_controller(false); | 983 | enable_controller(false, data); |
955 | } | 984 | } |
956 | 985 | ||
957 | mutex_unlock(&sd_mtx); | 986 | mutex_unlock(&sd_mtx); |
@@ -968,3 +997,42 @@ int sd_event(long id, intptr_t data) | |||
968 | 997 | ||
969 | return rc; | 998 | return rc; |
970 | } | 999 | } |
1000 | |||
1001 | #if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
1002 | /* declared in system-as3525.c */ | ||
1003 | void ams_sd_set_low_speed(bool slow) | ||
1004 | { | ||
1005 | /* block access while speed is changed */ | ||
1006 | mutex_lock(&sd_mtx); | ||
1007 | enable_controller(true, INTERNAL_AS3525); | ||
1008 | |||
1009 | /* After a data write, data cannot be written to MCI_CLOCK | ||
1010 | for 3 MCLK periods + 2 PCLK periods. ~10us worst case | ||
1011 | */ | ||
1012 | udelay(100); | ||
1013 | if (slow) | ||
1014 | { | ||
1015 | /* only affects internal drive clock speed*/ | ||
1016 | CGU_IDE = (CGU_IDE & ~(0xF << 2)) | (AS3525_IDE_DIV_MAX << 2); | ||
1017 | /* power save is enabled for the sd card(s) */ | ||
1018 | for (int i = 0; i < NUM_DRIVES ; i++) | ||
1019 | { | ||
1020 | if (i != INTERNAL_AS3525 && (MCI_CLOCK(i) & MCI_CLOCK_POWERSAVE) == 0) | ||
1021 | MCI_CLOCK(i) |= MCI_CLOCK_POWERSAVE; | ||
1022 | } | ||
1023 | } | ||
1024 | else | ||
1025 | { | ||
1026 | /* Full Speed */ | ||
1027 | CGU_IDE = (CGU_IDE & ~(0xF << 2)) | (AS3525_IDE_DIV << 2); | ||
1028 | for (int i = 0; i < NUM_DRIVES ; i++) | ||
1029 | { | ||
1030 | if (i != INTERNAL_AS3525 && (MCI_CLOCK(i) & MCI_CLOCK_POWERSAVE) != 0) | ||
1031 | MCI_CLOCK(i) = (MCI_CLOCK(i) & ~MCI_CLOCK_POWERSAVE); | ||
1032 | } | ||
1033 | } | ||
1034 | enable_controller(false, INTERNAL_AS3525); | ||
1035 | mutex_unlock(&sd_mtx); | ||
1036 | } | ||
1037 | #endif | ||
1038 | |||
diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c index b512cc2ea4..d27df5289c 100644 --- a/firmware/target/arm/as3525/sd-as3525v2.c +++ b/firmware/target/arm/as3525/sd-as3525v2.c | |||
@@ -488,7 +488,7 @@ static int sd_init_card(const int drive) | |||
488 | card_info[drive].initialized = 0; | 488 | card_info[drive].initialized = 0; |
489 | card_info[drive].rca = 0; | 489 | card_info[drive].rca = 0; |
490 | 490 | ||
491 | /* assume 24 MHz clock / 60 = 400 kHz */ | 491 | /* assume 24 MHz clock / (2x)60 = 200 kHz */ |
492 | MCI_CLKDIV = (MCI_CLKDIV & ~(0xFF)) | 0x3C; /* CLK_DIV_0 : bits 7:0 */ | 492 | MCI_CLKDIV = (MCI_CLKDIV & ~(0xFF)) | 0x3C; /* CLK_DIV_0 : bits 7:0 */ |
493 | 493 | ||
494 | /* 100 - 400kHz clock required for Identification Mode */ | 494 | /* 100 - 400kHz clock required for Identification Mode */ |
@@ -957,3 +957,27 @@ int sd_event(long id, intptr_t data) | |||
957 | 957 | ||
958 | return rc; | 958 | return rc; |
959 | } | 959 | } |
960 | |||
961 | #if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
962 | /* declared in system-as3525.c */ | ||
963 | void ams_sd_set_low_speed(bool slow) | ||
964 | { | ||
965 | /* block access while speed is changed */ | ||
966 | mutex_lock(&sd_mtx); | ||
967 | enable_controller(true); | ||
968 | if (slow) | ||
969 | { | ||
970 | CGU_SDSLOT = (CGU_SDSLOT & ~(0xF << 2)) | (AS3525_SDSLOT_DIV_MAX << 2); | ||
971 | /* power save is enabled for the sd card(s) ASSUMES CRD0 is int drive! */ | ||
972 | MCI_CLKENA |= (CCLK_LP_CRD1 | CCLK_LP_CRD2 | CCLK_LP_CRD3); | ||
973 | } | ||
974 | else | ||
975 | { | ||
976 | /* Full Speed */ | ||
977 | CGU_SDSLOT = (CGU_SDSLOT & ~(0xF << 2)) | (AS3525_SDSLOT_DIV << 2); | ||
978 | MCI_CLKENA = (MCI_CLKENA & ~(CCLK_LP_CRD1 | CCLK_LP_CRD2 | CCLK_LP_CRD3)); | ||
979 | } | ||
980 | enable_controller(false); | ||
981 | mutex_unlock(&sd_mtx); | ||
982 | } | ||
983 | #endif | ||
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index d630ef38ec..c11c90f9f3 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c | |||
@@ -52,6 +52,29 @@ struct mutex cpufreq_mtx; | |||
52 | #define default_interrupt(name) \ | 52 | #define default_interrupt(name) \ |
53 | extern __attribute__((weak,alias("UIRQ"))) void name (void) | 53 | extern __attribute__((weak,alias("UIRQ"))) void name (void) |
54 | 54 | ||
55 | #ifdef CONFIG_POWER_SAVING | ||
56 | /* Powersave functions either manipulate the system directly | ||
57 | or pass enabled flag on to these specific functions | ||
58 | dis/enabling powersaving for the selected subsystem | ||
59 | */ | ||
60 | #if (CONFIG_POWER_SAVING & POWERSV_CPU) | ||
61 | /*cpu_set_powersave*/ | ||
62 | #include "settings.h" | ||
63 | #endif | ||
64 | #if (CONFIG_POWER_SAVING & POWERSV_DISP) | ||
65 | /*disp_set_powersave*/ | ||
66 | void ams_ssp_set_low_speed(bool slow); /*lcd-clip-plus.c & lcd-clipzip.c*/ | ||
67 | #endif | ||
68 | #if (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
69 | /*disk_set_powersave*/ | ||
70 | void ams_sd_set_low_speed(bool slow); /* sd-as3525.c & sd-as3525v2.c */ | ||
71 | #endif | ||
72 | #if (CONFIG_POWER_SAVING & POWERSV_I2C) | ||
73 | /*i2c_set_powersave*/ | ||
74 | void ams_i2c_set_low_speed(bool slow); /* ascodec-as3525.c*/ | ||
75 | #endif | ||
76 | #endif /*CONFIG_POWER_SAVING*/ | ||
77 | |||
55 | #if CONFIG_USBOTG != USBOTG_DESIGNWARE | 78 | #if CONFIG_USBOTG != USBOTG_DESIGNWARE |
56 | static void UIRQ (void) __attribute__((interrupt ("IRQ"))); | 79 | static void UIRQ (void) __attribute__((interrupt ("IRQ"))); |
57 | #endif | 80 | #endif |
@@ -422,6 +445,39 @@ void udelay(unsigned usecs) | |||
422 | ); | 445 | ); |
423 | } | 446 | } |
424 | 447 | ||
448 | #ifdef CONFIG_POWER_SAVING | ||
449 | #if (CONFIG_POWER_SAVING & POWERSV_CPU) | ||
450 | void cpu_set_powersave(bool enabled) | ||
451 | { | ||
452 | /*global_settings.cpu_powersave*/ | ||
453 | /*handled in: set_cpu_frequency()*/ | ||
454 | (void) enabled; | ||
455 | } | ||
456 | #endif | ||
457 | #if (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
458 | void disk_set_powersave(bool enabled) | ||
459 | { | ||
460 | /*global_settings.disk_powersave*/ | ||
461 | ams_sd_set_low_speed(enabled); | ||
462 | } | ||
463 | #endif | ||
464 | #if (CONFIG_POWER_SAVING & POWERSV_DISP) | ||
465 | void disp_set_powersave(bool enabled) | ||
466 | { | ||
467 | /*global_settings.disp_powersave*/ | ||
468 | ams_ssp_set_low_speed(enabled); | ||
469 | } | ||
470 | #endif | ||
471 | #if (CONFIG_POWER_SAVING & POWERSV_I2C) | ||
472 | void i2c_set_powersave(bool enabled) | ||
473 | { | ||
474 | /*global_settings.i2c_powersave*/ | ||
475 | ams_i2c_set_low_speed(enabled); | ||
476 | } | ||
477 | #endif | ||
478 | #endif /*defined(CONFIG_POWER_SAVING)*/ | ||
479 | |||
480 | |||
425 | #ifndef BOOTLOADER | 481 | #ifndef BOOTLOADER |
426 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 482 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
427 | bool set_cpu_frequency__lock(void) | 483 | bool set_cpu_frequency__lock(void) |
@@ -481,7 +537,12 @@ void set_cpu_frequency(long frequency) | |||
481 | CGU_PROC = ((0xf << 4) | (0x3 << 2) | AS3525_CLK_MAIN); | 537 | CGU_PROC = ((0xf << 4) | (0x3 << 2) | AS3525_CLK_MAIN); |
482 | 538 | ||
483 | #ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE | 539 | #ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE |
484 | /* Decreasing frequency so reduce voltage after change */ | 540 | /* Decreasing frequency so reduce voltage after change */ |
541 | #if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_CPU) | ||
542 | if (!global_settings.cpu_powersave) | ||
543 | ascodec_write(AS3514_CVDD_DCDC3, (AS314_CP_DCDC3_SETTING | CVDD_1_15)); | ||
544 | else | ||
545 | #endif | ||
485 | ascodec_write(AS3514_CVDD_DCDC3, (AS314_CP_DCDC3_SETTING | CVDD_1_10)); | 546 | ascodec_write(AS3514_CVDD_DCDC3, (AS314_CP_DCDC3_SETTING | CVDD_1_10)); |
486 | #endif /* HAVE_ADJUSTABLE_CPU_VOLTAGE */ | 547 | #endif /* HAVE_ADJUSTABLE_CPU_VOLTAGE */ |
487 | 548 | ||
@@ -519,6 +580,13 @@ void set_cpu_frequency(long frequency) | |||
519 | 580 | ||
520 | /* Set CVDD1 power supply */ | 581 | /* Set CVDD1 power supply */ |
521 | #ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE | 582 | #ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE |
583 | #if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_CPU) | ||
584 | if (!global_settings.cpu_powersave) | ||
585 | { | ||
586 | ascodec_write_pmu(0x17, 1, 0x80 | 26); | ||
587 | return; | ||
588 | } | ||
589 | #endif | ||
522 | #if defined(SANSA_CLIPZIP) | 590 | #if defined(SANSA_CLIPZIP) |
523 | ascodec_write_pmu(0x17, 1, 0x80 | 20); | 591 | ascodec_write_pmu(0x17, 1, 0x80 | 20); |
524 | #elif defined(SANSA_CLIPPLUS) | 592 | #elif defined(SANSA_CLIPPLUS) |
diff --git a/firmware/target/arm/as3525/system-target.h b/firmware/target/arm/as3525/system-target.h index 5cdc573a1b..9c5b5a9cd6 100644 --- a/firmware/target/arm/as3525/system-target.h +++ b/firmware/target/arm/as3525/system-target.h | |||
@@ -73,6 +73,26 @@ static inline void mdelay(unsigned msecs) | |||
73 | void usb_insert_int(void); | 73 | void usb_insert_int(void); |
74 | void usb_remove_int(void); | 74 | void usb_remove_int(void); |
75 | 75 | ||
76 | |||
77 | #ifdef CONFIG_POWER_SAVING | ||
78 | /* Powersave functions either manipulate the system directly | ||
79 | or pass enabled flag on to the devices specific function | ||
80 | dis/enabling powersaving for the selected subsystem | ||
81 | */ | ||
82 | #if (CONFIG_POWER_SAVING & POWERSV_CPU) | ||
83 | void cpu_set_powersave(bool enabled); | ||
84 | #endif | ||
85 | #if (CONFIG_POWER_SAVING & POWERSV_DISP) | ||
86 | void disp_set_powersave(bool enabled); | ||
87 | #endif | ||
88 | #if (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
89 | void disk_set_powersave(bool enabled); | ||
90 | #endif | ||
91 | #if (CONFIG_POWER_SAVING & POWERSV_I2C) | ||
92 | void i2c_set_powersave(bool enabled); | ||
93 | #endif | ||
94 | #endif /*CONFIG_POWER_SAVING*/ | ||
95 | |||
76 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 96 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
77 | #define CPU_BOOST_LOCK_DEFINED | 97 | #define CPU_BOOST_LOCK_DEFINED |
78 | 98 | ||
diff --git a/manual/configure_rockbox/system_options.tex b/manual/configure_rockbox/system_options.tex index ff2967cec7..b279308e71 100755 --- a/manual/configure_rockbox/system_options.tex +++ b/manual/configure_rockbox/system_options.tex | |||
@@ -297,6 +297,30 @@ therefore result in better runtime. | |||
297 | \end{description} | 297 | \end{description} |
298 | } %\nopt{HAS_BUTTON_HOLD} | 298 | } %\nopt{HAS_BUTTON_HOLD} |
299 | 299 | ||
300 | \opt{CONFIG_POWER_SAVING}{ | ||
301 | \subsection{Power Saving} | ||
302 | These options allow users to increase runtime by lowering performance | ||
303 | of select subsystems. Certain options may \emph{not} be applicable to your | ||
304 | \dap{} or may cause undesired operation to your particular use case. | ||
305 | |||
306 | \emph{WARNING!} While every effort has been made to ensure the safety of these | ||
307 | options, due to manufacturing variance some options may cause unwanted side | ||
308 | effects, cause the \dap{} to crash or (while unlikely) even \emph{destroy} | ||
309 | your \dap{}. \emph{PROCEED WITH CAUTION} | ||
310 | |||
311 | \begin{description} | ||
312 | |||
313 | \item[CPU] | ||
314 | Allows lower voltages or cpu speed when enabled. | ||
315 | \item[Disk] | ||
316 | Allows slower disk operations when enabled. | ||
317 | \item[I2C] | ||
318 | Allows slower clocking of I2C device bus when enabled. | ||
319 | \item[Display] | ||
320 | Allows slower screen refresh rates when enabled. | ||
321 | |||
322 | \end{description} | ||
323 | } %\opt{CONFIG_POWER_SAVING} | ||
300 | 324 | ||
301 | \opt{usb_hid}{ | 325 | \opt{usb_hid}{ |
302 | \subsection{\label{ref:USB_HID}USB HID} | 326 | \subsection{\label{ref:USB_HID}USB HID} |