AMSv1: Don't modify MPMC_DYNAMIC_CONTROL
[kugel-rb.git] / apps / main.c
blob6c6d09cbaa6de1f6fc152e3646ed5585bc25f33b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Björn Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
23 #include "storage.h"
24 #include "disk.h"
25 #include "fat.h"
26 #include "lcd.h"
27 #include "rtc.h"
28 #include "debug.h"
29 #include "led.h"
30 #include "kernel.h"
31 #include "button.h"
32 #include "tree.h"
33 #include "filetypes.h"
34 #include "panic.h"
35 #include "menu.h"
36 #include "system.h"
37 #include "usb.h"
38 #include "powermgmt.h"
39 #include "adc.h"
40 #include "i2c.h"
41 #ifndef DEBUG
42 #include "serial.h"
43 #endif
44 #include "audio.h"
45 #include "mp3_playback.h"
46 #include "thread.h"
47 #include "settings.h"
48 #include "backlight.h"
49 #include "status.h"
50 #include "debug_menu.h"
51 #include "font.h"
52 #include "language.h"
53 #include "wps.h"
54 #include "playlist.h"
55 #include "buffer.h"
56 #include "rolo.h"
57 #include "screens.h"
58 #include "usb_screen.h"
59 #include "power.h"
60 #include "talk.h"
61 #include "plugin.h"
62 #include "misc.h"
63 #include "dircache.h"
64 #ifdef HAVE_TAGCACHE
65 #include "tagcache.h"
66 #include "tagtree.h"
67 #endif
68 #include "lang.h"
69 #include "string.h"
70 #include "splash.h"
71 #include "eeprom_settings.h"
72 #include "scrobbler.h"
73 #include "icon.h"
74 #include "viewport.h"
75 #include "statusbar-skinned.h"
76 #include "bootchart.h"
78 #ifdef IPOD_ACCESSORY_PROTOCOL
79 #include "iap.h"
80 #endif
82 #if (CONFIG_CODEC == SWCODEC)
83 #include "playback.h"
84 #include "tdspeed.h"
85 #endif
86 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
87 #include "pcm_record.h"
88 #endif
90 #ifdef BUTTON_REC
91 #define SETTINGS_RESET BUTTON_REC
92 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
93 #define SETTINGS_RESET BUTTON_A
94 #endif
96 #if CONFIG_TUNER
97 #include "radio.h"
98 #endif
99 #if (CONFIG_STORAGE & STORAGE_MMC)
100 #include "ata_mmc.h"
101 #endif
103 #ifdef HAVE_REMOTE_LCD
104 #include "lcd-remote.h"
105 #endif
107 #if CONFIG_USBOTG == USBOTG_ISP1362
108 #include "isp1362.h"
109 #endif
111 #if CONFIG_USBOTG == USBOTG_M5636
112 #include "m5636.h"
113 #endif
115 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
116 #include "sim_tasks.h"
117 #endif
119 #ifdef HAVE_SDL
120 #include "system-sdl.h"
121 #endif
123 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
125 static void init(void);
127 #ifdef HAVE_SDL
128 #if defined(WIN32) && defined(main)
129 /* Don't use SDL_main on windows -> no more stdio redirection */
130 #undef main
131 #endif
132 int main(int argc, char *argv[])
134 sys_handle_argv(argc, argv);
135 #else
136 /* main(), and various functions called by main() and init() may be
137 * be INIT_ATTR. These functions must not be called after the final call
138 * to root_menu() at the end of main()
139 * see definition of INIT_ATTR in config.h */
140 int main(void) INIT_ATTR __attribute__((noreturn));
141 int main(void)
143 #endif
144 int i;
145 CHART(">init");
146 init();
147 CHART("<init");
148 FOR_NB_SCREENS(i)
150 screens[i].clear_display();
151 screens[i].update();
153 #ifdef HAVE_LCD_BITMAP
154 list_init();
155 #endif
156 tree_gui_init();
157 /* Keep the order of this 3
158 * Must be done before any code uses the multi-screen API */
159 #ifdef HAVE_USBSTACK
160 /* All threads should be created and public queues registered by now */
161 usb_start_monitoring();
162 #endif
164 #ifdef AUTOROCK
166 static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
168 if(file_exists(filename)) /* no complaint if it doesn't exist */
170 plugin_load((char*)filename, NULL); /* start if it does */
173 #endif /* #ifdef AUTOROCK */
175 global_status.last_volume_change = 0;
176 /* no calls INIT_ATTR functions after this point anymore!
177 * see definition of INIT_ATTR in config.h */
178 CHART(">root_menu");
179 root_menu();
182 static int init_dircache(bool preinit) INIT_ATTR;
183 static int init_dircache(bool preinit)
185 #ifdef HAVE_DIRCACHE
186 int result = 0;
187 bool clear = false;
189 if (preinit)
190 dircache_init();
192 if (!global_settings.dircache)
193 return 0;
195 # ifdef HAVE_EEPROM_SETTINGS
196 if (firmware_settings.initialized && firmware_settings.disk_clean
197 && preinit)
199 result = dircache_load();
201 if (result < 0)
203 firmware_settings.disk_clean = false;
204 if (global_status.dircache_size <= 0)
206 /* This will be in default language, settings are not
207 applied yet. Not really any easy way to fix that. */
208 splash(0, str(LANG_SCANNING_DISK));
209 clear = true;
212 dircache_build(global_status.dircache_size);
215 else
216 # endif
218 if (preinit)
219 return -1;
221 if (!dircache_is_enabled()
222 && !dircache_is_initializing())
224 if (global_status.dircache_size <= 0)
226 splash(0, str(LANG_SCANNING_DISK));
227 clear = true;
229 result = dircache_build(global_status.dircache_size);
232 if (result < 0)
234 /* Initialization of dircache failed. Manual action is
235 * necessary to enable dircache again.
237 splashf(0, "Dircache failed, disabled. Result: %d", result);
238 global_settings.dircache = false;
242 if (clear)
244 backlight_on();
245 show_logo();
246 global_status.dircache_size = dircache_get_cache_size();
247 status_save();
250 return result;
251 #else
252 (void)preinit;
253 return 0;
254 #endif
257 #ifdef HAVE_TAGCACHE
258 static void init_tagcache(void) INIT_ATTR;
259 static void init_tagcache(void)
261 bool clear = false;
262 #if CONFIG_CODEC == SWCODEC
263 long talked_tick = 0;
264 #endif
265 tagcache_init();
267 while (!tagcache_is_initialized())
269 int ret = tagcache_get_commit_step();
271 if (ret > 0)
273 #if CONFIG_CODEC == SWCODEC
274 /* hwcodec can't use voice here, as the database commit
275 * uses the audio buffer. */
276 if(global_settings.talk_menu
277 && (talked_tick == 0
278 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
280 talked_tick = current_tick;
281 talk_id(LANG_TAGCACHE_INIT, false);
282 talk_number(ret, true);
283 talk_id(VOICE_OF, true);
284 talk_number(tagcache_get_max_commit_step(), true);
286 #endif
287 #ifdef HAVE_LCD_BITMAP
288 if (lang_is_rtl())
290 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
291 str(LANG_TAGCACHE_INIT));
293 else
295 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
296 tagcache_get_max_commit_step());
298 #else
299 lcd_double_height(false);
300 lcd_putsf(0, 1, " DB [%d/%d]", ret,
301 tagcache_get_max_commit_step());
302 lcd_update();
303 #endif
304 clear = true;
306 sleep(HZ/4);
308 tagtree_init();
310 if (clear)
312 backlight_on();
313 show_logo();
316 #endif
318 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
320 static void init(void)
322 system_init();
323 kernel_init();
324 buffer_init();
325 enable_irq();
326 lcd_init();
327 #ifdef HAVE_REMOTE_LCD
328 lcd_remote_init();
329 #endif
330 font_init();
331 show_logo();
332 button_init();
333 backlight_init();
334 sim_tasks_init();
335 lang_init(core_language_builtin, language_strings,
336 LANG_LAST_INDEX_IN_ARRAY);
337 #ifdef DEBUG
338 debug_init();
339 #endif
340 /* Keep the order of this 3 (viewportmanager handles statusbars)
341 * Must be done before any code uses the multi-screen API */
342 gui_syncstatusbar_init(&statusbars);
343 gui_sync_wps_init();
344 sb_skin_init();
345 viewportmanager_init();
347 storage_init();
348 settings_reset();
349 settings_load(SETTINGS_ALL);
350 settings_apply(true);
351 init_dircache(true);
352 init_dircache(false);
353 #ifdef HAVE_TAGCACHE
354 init_tagcache();
355 #endif
356 sleep(HZ/2);
357 tree_mem_init();
358 filetype_init();
359 playlist_init();
360 theme_init_buffer();
362 #if CONFIG_CODEC != SWCODEC
363 mp3_init( global_settings.volume,
364 global_settings.bass,
365 global_settings.treble,
366 global_settings.balance,
367 global_settings.loudness,
368 global_settings.avc,
369 global_settings.channel_config,
370 global_settings.stereo_width,
371 global_settings.mdb_strength,
372 global_settings.mdb_harmonics,
373 global_settings.mdb_center,
374 global_settings.mdb_shape,
375 global_settings.mdb_enable,
376 global_settings.superbass);
378 /* audio_init must to know the size of voice buffer so init voice first */
379 talk_init();
380 #endif /* CONFIG_CODEC != SWCODEC */
382 scrobbler_init();
383 #if CONFIG_CODEC == SWCODEC
384 tdspeed_init();
385 #endif /* CONFIG_CODEC == SWCODEC */
387 audio_init();
388 button_clear_queue(); /* Empty the keyboard buffer */
390 settings_apply_skins();
393 #else
395 static void init(void) INIT_ATTR;
396 static void init(void)
398 int rc;
399 bool mounted = false;
400 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
401 /* if nobody initialized ATA before, I consider this a cold start */
402 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
403 #endif
405 system_init();
406 kernel_init();
408 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
409 set_cpu_frequency(CPUFREQ_NORMAL);
410 #ifdef CPU_COLDFIRE
411 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
412 #endif
413 cpu_boost(true);
414 #endif
416 buffer_init();
418 settings_reset();
420 i2c_init();
422 power_init();
424 enable_irq();
425 #ifdef CPU_ARM
426 enable_fiq();
427 #endif
428 /* current_tick should be ticking by now */
429 CHART("ticking");
431 lcd_init();
432 #ifdef HAVE_REMOTE_LCD
433 lcd_remote_init();
434 #endif
435 font_init();
437 CHART(">show_logo");
438 show_logo();
439 CHART("<show_logo");
440 lang_init(core_language_builtin, language_strings,
441 LANG_LAST_INDEX_IN_ARRAY);
443 #ifdef DEBUG
444 debug_init();
445 #else
446 #ifdef HAVE_SERIAL
447 serial_setup();
448 #endif
449 #endif
451 #if CONFIG_RTC
452 rtc_init();
453 #endif
454 #ifdef HAVE_RTC_RAM
455 CHART(">settings_load(RTC)");
456 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
457 CHART("<settings_load(RTC)");
458 #endif
460 adc_init();
462 usb_init();
463 #if CONFIG_USBOTG == USBOTG_ISP1362
464 isp1362_init();
465 #elif CONFIG_USBOTG == USBOTG_M5636
466 m5636_init();
467 #endif
469 backlight_init();
471 button_init();
473 powermgmt_init();
475 #if CONFIG_TUNER
476 radio_init();
477 #endif
479 /* Keep the order of this 3 (viewportmanager handles statusbars)
480 * Must be done before any code uses the multi-screen API */
481 CHART(">gui_syncstatusbar_init");
482 gui_syncstatusbar_init(&statusbars);
483 CHART("<gui_syncstatusbar_init");
484 CHART(">sb_skin_init");
485 sb_skin_init();
486 CHART("<sb_skin_init");
487 CHART(">gui_sync_wps_init");
488 gui_sync_wps_init();
489 CHART("<gui_sync_wps_init");
490 CHART(">viewportmanager_init");
491 viewportmanager_init();
492 CHART("<viewportmanager_init");
494 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
495 /* charger_inserted() can't be used here because power_thread()
496 hasn't checked power_input_status() yet */
497 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
498 && !global_settings.car_adapter_mode
499 #ifdef ATA_POWER_PLAYERSTYLE
500 && !ide_powered() /* relies on probing result from bootloader */
501 #endif
504 rc = charging_screen(); /* display a "charging" screen */
505 if (rc == 1) /* charger removed */
506 power_off();
507 /* "On" pressed or USB connected: proceed */
508 show_logo(); /* again, to provide better visual feedback */
510 #endif
513 disk_init_subsystem();
514 CHART(">storage_init");
515 rc = storage_init();
516 CHART("<storage_init");
517 if(rc)
519 #ifdef HAVE_LCD_BITMAP
520 lcd_clear_display();
521 lcd_putsf(0, 1, "ATA error: %d", rc);
522 lcd_puts(0, 3, "Press ON to debug");
523 lcd_update();
524 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
525 dbg_ports();
526 #endif
527 panicf("ata: %d", rc);
530 #ifdef HAVE_EEPROM_SETTINGS
531 CHART(">eeprom_settings_init");
532 eeprom_settings_init();
533 CHART("<eeprom_settings_init");
534 #endif
536 #ifndef HAVE_USBSTACK
537 usb_start_monitoring();
538 while (usb_detect() == USB_INSERTED)
540 #ifdef HAVE_EEPROM_SETTINGS
541 firmware_settings.disk_clean = false;
542 #endif
543 /* enter USB mode early, before trying to mount */
544 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
545 #if (CONFIG_STORAGE & STORAGE_MMC)
546 if (!mmc_touched() ||
547 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
548 #endif
550 gui_usb_screen_run();
551 mounted = true; /* mounting done @ end of USB mode */
553 #ifdef HAVE_USB_POWER
554 if (usb_powered()) /* avoid deadlock */
555 break;
556 #endif
558 #endif
560 if (!mounted)
562 CHART(">disk_mount_all");
563 rc = disk_mount_all();
564 CHART("<disk_mount_all");
565 if (rc<=0)
567 lcd_clear_display();
568 lcd_puts(0, 0, "No partition");
569 lcd_puts(0, 1, "found.");
570 #ifdef HAVE_LCD_BITMAP
571 lcd_puts(0, 2, "Insert USB cable");
572 lcd_puts(0, 3, "and fix it.");
573 #endif
574 lcd_update();
576 while(button_get(true) != SYS_USB_CONNECTED) {};
577 gui_usb_screen_run();
578 system_reboot();
582 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
583 (CONFIG_KEYPAD == IRIVER_H10_PAD)
584 #ifdef SETTINGS_RESET
585 /* Reset settings if holding the reset button. (Rec on Archos,
586 A on Gigabeat) */
587 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
588 #else
589 /* Reset settings if the hold button is turned on */
590 if (button_hold())
591 #endif
593 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
594 settings_reset();
596 else
597 #endif
599 CHART(">settings_load(ALL)");
600 settings_load(SETTINGS_ALL);
601 CHART("<settings_load(ALL)");
604 CHART(">init_dircache(true)");
605 rc = init_dircache(true);
606 CHART("<init_dircache(true)");
607 if (rc < 0)
609 #ifdef HAVE_TAGCACHE
610 remove(TAGCACHE_STATEFILE);
611 #endif
614 CHART(">settings_apply(true)");
615 settings_apply(true);
616 CHART("<settings_apply(true)");
617 CHART(">init_dircache(false)");
618 init_dircache(false);
619 CHART("<init_dircache(false)");
620 #ifdef HAVE_TAGCACHE
621 CHART(">init_tagcache");
622 init_tagcache();
623 CHART("<init_tagcache");
624 #endif
626 #ifdef HAVE_EEPROM_SETTINGS
627 if (firmware_settings.initialized)
629 /* In case we crash. */
630 firmware_settings.disk_clean = false;
631 CHART(">eeprom_settings_store");
632 eeprom_settings_store();
633 CHART("<eeprom_settings_store");
635 #endif
636 playlist_init();
637 tree_mem_init();
638 filetype_init();
639 scrobbler_init();
640 #if CONFIG_CODEC == SWCODEC
641 tdspeed_init();
642 #endif /* CONFIG_CODEC == SWCODEC */
643 theme_init_buffer();
645 #if CONFIG_CODEC != SWCODEC
646 /* No buffer allocation (see buffer.c) may take place after the call to
647 audio_init() since the mpeg thread takes the rest of the buffer space */
648 mp3_init( global_settings.volume,
649 global_settings.bass,
650 global_settings.treble,
651 global_settings.balance,
652 global_settings.loudness,
653 global_settings.avc,
654 global_settings.channel_config,
655 global_settings.stereo_width,
656 global_settings.mdb_strength,
657 global_settings.mdb_harmonics,
658 global_settings.mdb_center,
659 global_settings.mdb_shape,
660 global_settings.mdb_enable,
661 global_settings.superbass);
663 /* audio_init must to know the size of voice buffer so init voice first */
664 talk_init();
665 #endif /* CONFIG_CODEC != SWCODEC */
667 CHART(">audio_init");
668 audio_init();
669 CHART("<audio_init");
671 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
672 pcm_rec_init();
673 #endif
675 /* runtime database has to be initialized after audio_init() */
676 cpu_boost(false);
678 #if CONFIG_CHARGING
679 car_adapter_mode_init();
680 #endif
681 #ifdef IPOD_ACCESSORY_PROTOCOL
682 iap_setup(global_settings.serial_bitrate);
683 #endif
684 #ifdef HAVE_ACCESSORY_SUPPLY
685 accessory_supply_set(global_settings.accessory_supply);
686 #endif
687 #ifdef HAVE_LINEOUT_POWEROFF
688 lineout_set(global_settings.lineout_active);
689 #endif
690 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
691 CHART("<check_bootfile(false)");
692 check_bootfile(false); /* remember write time and filesize */
693 CHART(">check_bootfile(false)");
694 #endif
695 CHART("<settings_apply_skins");
696 settings_apply_skins();
697 CHART(">settings_apply_skins");
700 #ifdef CPU_PP
701 void __attribute__((noreturn)) cop_main(void)
703 /* This is the entry point for the coprocessor
704 Anyone not running an upgraded bootloader will never reach this point,
705 so it should not be assumed that the coprocessor be usable even on
706 platforms which support it.
708 A kernel thread is initially setup on the coprocessor and immediately
709 destroyed for purposes of continuity. The cop sits idle until at least
710 one thread exists on it. */
712 #if NUM_CORES > 1
713 system_init();
714 kernel_init();
715 /* This should never be reached */
716 #endif
717 while(1) {
718 sleep_core(COP);
721 #endif /* CPU_PP */
723 #endif /* SIMULATOR */