summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2006-10-15 11:57:52 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2006-10-15 11:57:52 +0000
commit70587527898345fdb7245be7c8723b338323fceb (patch)
tree2cd1f4570c34db202f2a4b4cc9fa867e1f7582f1
parent450f619dcf4904e5aee00b89c417a5ba8a1bf23f (diff)
downloadrockbox-70587527898345fdb7245be7c8723b338323fceb.tar.gz
rockbox-70587527898345fdb7245be7c8723b338323fceb.zip
Removed ugly boosting solutions from playback code and let scheduler
handle unboosting instead. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11226 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/pcmbuf.c86
-rw-r--r--apps/pcmbuf.h1
-rw-r--r--apps/playback.c32
-rw-r--r--firmware/export/config.h1
-rw-r--r--firmware/export/thread.h8
-rw-r--r--firmware/thread.c32
6 files changed, 67 insertions, 93 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index d8612a4fbc..44f175c67d 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -94,7 +94,6 @@ static size_t pcmbuf_mix_sample IDATA_ATTR;
94 94
95static bool low_latency_mode = false; 95static bool low_latency_mode = false;
96static bool pcmbuf_flush; 96static bool pcmbuf_flush;
97static volatile bool output_completed = false;
98 97
99extern struct thread_entry *codec_thread_p; 98extern struct thread_entry *codec_thread_p;
100 99
@@ -109,44 +108,6 @@ static bool prepare_insert(size_t length);
109static void pcmbuf_under_watermark(void); 108static void pcmbuf_under_watermark(void);
110static bool pcmbuf_flush_fillpos(void); 109static bool pcmbuf_flush_fillpos(void);
111 110
112#if defined(HAVE_ADJUSTABLE_CPU_FREQ) && !defined(SIMULATOR)
113void pcmbuf_boost(bool state)
114{
115 static bool boost_state = false;
116#ifdef HAVE_PRIORITY_SCHEDULING
117 static bool priority_modified = false;
118#endif
119
120 if (crossfade_init || crossfade_active)
121 return;
122
123 if (state != boost_state)
124 {
125 cpu_boost_id(state, CPUBOOSTID_PCMBUF);
126 boost_state = state;
127 }
128
129#ifdef HAVE_PRIORITY_SCHEDULING
130 if (state && LOW_DATA(2) && pcm_is_playing())
131 {
132 if (!priority_modified)
133 {
134 /* Buffer is critically low so override UI priority. */
135 priority_modified = true;
136 thread_set_priority(codec_thread_p, PRIORITY_REALTIME);
137 }
138 }
139 else if (priority_modified)
140 {
141 /* Set back the original priority. */
142 thread_set_priority(codec_thread_p, PRIORITY_PLAYBACK);
143 priority_modified = false;
144 }
145
146#endif
147}
148#endif
149
150#define CALL_IF_EXISTS(function, args...) if (function) function(args) 111#define CALL_IF_EXISTS(function, args...) if (function) function(args)
151/* This function has 2 major logical parts (separated by brackets both for 112/* This function has 2 major logical parts (separated by brackets both for
152 * readability and variable scoping). The first part performs the 113 * readability and variable scoping). The first part performs the
@@ -204,7 +165,6 @@ process_new_buffer:
204 *realsize = 0; 165 *realsize = 0;
205 *realstart = NULL; 166 *realstart = NULL;
206 CALL_IF_EXISTS(pcmbuf_event_handler); 167 CALL_IF_EXISTS(pcmbuf_event_handler);
207 output_completed = true;
208 } 168 }
209 } 169 }
210} 170}
@@ -268,8 +228,25 @@ static inline void pcmbuf_add_chunk(void)
268 228
269static void pcmbuf_under_watermark(void) 229static void pcmbuf_under_watermark(void)
270{ 230{
231#ifdef HAVE_PRIORITY_SCHEDULING
232 static int old_priority = 0;
233
234 if (LOW_DATA(2) && !old_priority && pcm_is_playing())
235 {
236 /* Buffer is critically low so override UI priority. */
237 old_priority = thread_set_priority(codec_thread_p, PRIORITY_REALTIME);
238 }
239 else if (old_priority)
240 {
241 /* Set back the original priority. */
242 thread_set_priority(codec_thread_p, old_priority);
243 old_priority = 0;
244 }
245#endif
246
271 /* Fill audio buffer by boosting cpu */ 247 /* Fill audio buffer by boosting cpu */
272 pcmbuf_boost(true); 248 trigger_cpu_boost();
249
273 /* Disable crossfade if < .5s of audio */ 250 /* Disable crossfade if < .5s of audio */
274 if (LOW_DATA(2)) 251 if (LOW_DATA(2))
275 { 252 {
@@ -328,17 +305,16 @@ bool pcmbuf_crossfade_init(bool manual_skip)
328 return false; 305 return false;
329 } 306 }
330 307
308 trigger_cpu_boost();
309
331 /* Not enough data, or crossfade disabled, flush the old data instead */ 310 /* Not enough data, or crossfade disabled, flush the old data instead */
332 if (LOW_DATA(2) || !pcmbuf_is_crossfade_enabled() || low_latency_mode) 311 if (LOW_DATA(2) || !pcmbuf_is_crossfade_enabled() || low_latency_mode)
333 { 312 {
334 pcmbuf_boost(true);
335 pcmbuf_flush_fillpos(); 313 pcmbuf_flush_fillpos();
336 pcmbuf_flush = true; 314 pcmbuf_flush = true;
337 return false; 315 return false;
338 } 316 }
339 317
340 pcmbuf_boost(true);
341
342 /* Don't enable mix mode when skipping tracks manually. */ 318 /* Don't enable mix mode when skipping tracks manually. */
343 if (manual_skip) 319 if (manual_skip)
344 crossfade_mixmode = false; 320 crossfade_mixmode = false;
@@ -371,9 +347,6 @@ void pcmbuf_play_stop(void)
371 crossfade_init = false; 347 crossfade_init = false;
372 crossfade_active = false; 348 crossfade_active = false;
373 pcmbuf_flush = false; 349 pcmbuf_flush = false;
374
375 pcmbuf_boost(false);
376
377} 350}
378 351
379int pcmbuf_used_descs(void) { 352int pcmbuf_used_descs(void) {
@@ -433,7 +406,7 @@ void pcmbuf_pause(bool pause) {
433 pcm_play_pause(!pause); 406 pcm_play_pause(!pause);
434 if (!pause) 407 if (!pause)
435 pcm_mute(false); 408 pcm_mute(false);
436 pcmbuf_boost(!pause && pcm_is_playing()); 409 trigger_cpu_boost();
437} 410}
438 411
439/* Force playback. */ 412/* Force playback. */
@@ -466,8 +439,6 @@ static bool pcmbuf_flush_fillpos(void)
466 if (audiobuffer_fillpos) { 439 if (audiobuffer_fillpos) {
467 /* Never use the last buffer descriptor */ 440 /* Never use the last buffer descriptor */
468 while (pcmbuf_write == pcmbuf_write_end) { 441 while (pcmbuf_write == pcmbuf_write_end) {
469 /* Deboost to let the playback catchup */
470 pcmbuf_boost(false);
471 /* If this happens, something is being stupid */ 442 /* If this happens, something is being stupid */
472 if (!pcm_is_playing()) { 443 if (!pcm_is_playing()) {
473 logf("pcmbuf_flush_fillpos error"); 444 logf("pcmbuf_flush_fillpos error");
@@ -762,14 +733,12 @@ static bool prepare_insert(size_t length)
762 733
763 /* Need to save PCMBUF_MIN_CHUNK to prevent wrapping overwriting */ 734 /* Need to save PCMBUF_MIN_CHUNK to prevent wrapping overwriting */
764 if (pcmbuf_free() < length + PCMBUF_MIN_CHUNK) 735 if (pcmbuf_free() < length + PCMBUF_MIN_CHUNK)
765 {
766 pcmbuf_boost(false);
767 return false; 736 return false;
768 }
769 737
770 if (!pcm_is_playing()) 738 if (!pcm_is_playing())
771 { 739 {
772 pcmbuf_boost(true); 740 trigger_cpu_boost();
741
773 /* Pre-buffer 1s. */ 742 /* Pre-buffer 1s. */
774#if MEM <= 1 743#if MEM <= 1
775 if (!LOW_DATA(1)) 744 if (!LOW_DATA(1))
@@ -1031,12 +1000,3 @@ bool pcmbuf_is_crossfade_enabled(void)
1031 return crossfade_enabled; 1000 return crossfade_enabled;
1032} 1001}
1033 1002
1034bool pcmbuf_output_completed(void)
1035{
1036 if (output_completed)
1037 {
1038 output_completed = false;
1039 return true;
1040 }
1041 return false;
1042}
diff --git a/apps/pcmbuf.h b/apps/pcmbuf.h
index 2106968368..b5035f4405 100644
--- a/apps/pcmbuf.h
+++ b/apps/pcmbuf.h
@@ -46,7 +46,6 @@ size_t get_pcmbuf_descsize(void);
46void pcmbuf_pause(bool pause); 46void pcmbuf_pause(bool pause);
47void pcmbuf_play_stop(void); 47void pcmbuf_play_stop(void);
48bool pcmbuf_is_crossfade_active(void); 48bool pcmbuf_is_crossfade_active(void);
49bool pcmbuf_output_completed(void);
50 49
51/* These functions are for playing chained buffers of PCM data */ 50/* These functions are for playing chained buffers of PCM data */
52#if defined(HAVE_ADJUSTABLE_CPU_FREQ) && !defined(SIMULATOR) 51#if defined(HAVE_ADJUSTABLE_CPU_FREQ) && !defined(SIMULATOR)
diff --git a/apps/playback.c b/apps/playback.c
index 44aa8696fc..feba1d1c6c 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -292,11 +292,6 @@ struct voice_info {
292 char *buf; 292 char *buf;
293}; 293};
294 294
295#ifdef HAVE_ADJUSTABLE_CPU_FREQ
296static void voice_boost_cpu(bool state);
297#else
298#define voice_boost_cpu(state) do { } while(0)
299#endif
300static void voice_thread(void); 295static void voice_thread(void);
301 296
302#endif /* PLAYBACK_VOICE */ 297#endif /* PLAYBACK_VOICE */
@@ -316,7 +311,7 @@ void mp3_play_data(const unsigned char* start, int size,
316 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY"); 311 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
317 queue_post(&voice_queue, Q_VOICE_PLAY, &voice_clip); 312 queue_post(&voice_queue, Q_VOICE_PLAY, &voice_clip);
318 voice_thread_start = true; 313 voice_thread_start = true;
319 voice_boost_cpu(true); 314 trigger_cpu_boost();
320#else 315#else
321 (void) start; 316 (void) start;
322 (void) size; 317 (void) size;
@@ -815,19 +810,6 @@ static const char * get_codec_filename(int enc_spec)
815 810
816#ifdef PLAYBACK_VOICE 811#ifdef PLAYBACK_VOICE
817 812
818#ifdef HAVE_ADJUSTABLE_CPU_FREQ
819static void voice_boost_cpu(bool state)
820{
821 static bool voice_cpu_boosted = false;
822
823 if (state != voice_cpu_boosted)
824 {
825 voice_cpu_boosted = state;
826 cpu_boost_id(state, CPUBOOSTID_PLAYBACK_VOICE);
827 }
828}
829#endif
830
831static bool voice_pcmbuf_insert_split_callback( 813static bool voice_pcmbuf_insert_split_callback(
832 const void *ch1, const void *ch2, size_t length) 814 const void *ch1, const void *ch2, size_t length)
833{ 815{
@@ -976,7 +958,6 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
976 voice_getmore = NULL; 958 voice_getmore = NULL;
977 voice_remaining = 0; 959 voice_remaining = 0;
978 voicebuf = NULL; 960 voicebuf = NULL;
979 voice_boost_cpu(false);
980 961
981 /* Force the codec to think it's changing tracks */ 962 /* Force the codec to think it's changing tracks */
982 ci_voice.new_track = 1; 963 ci_voice.new_track = 1;
@@ -1005,7 +986,7 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1005 /* Set up new voice data */ 986 /* Set up new voice data */
1006 struct voice_info *voice_data; 987 struct voice_info *voice_data;
1007 voice_is_playing = true; 988 voice_is_playing = true;
1008 voice_boost_cpu(true); 989 trigger_cpu_boost();
1009 voice_data = ev.data; 990 voice_data = ev.data;
1010 voice_remaining = voice_data->size; 991 voice_remaining = voice_data->size;
1011 voicebuf = voice_data->buf; 992 voicebuf = voice_data->buf;
@@ -1666,7 +1647,7 @@ static bool codec_load_next_track(void)
1666 automatic_skip = true; 1647 automatic_skip = true;
1667 } 1648 }
1668 1649
1669 cpu_boost_id(true, CPUBOOSTID_PLAYBACK_CODEC); 1650 trigger_cpu_boost();
1670 LOGFQUEUE("codec > audio Q_AUDIO_CHECK_NEW_TRACK"); 1651 LOGFQUEUE("codec > audio Q_AUDIO_CHECK_NEW_TRACK");
1671 queue_post(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0); 1652 queue_post(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1672 while (1) 1653 while (1)
@@ -1680,7 +1661,7 @@ static bool codec_load_next_track(void)
1680 else 1661 else
1681 break; 1662 break;
1682 } 1663 }
1683 cpu_boost_id(false, CPUBOOSTID_PLAYBACK_CODEC); 1664
1684 switch (ev.id) 1665 switch (ev.id)
1685 { 1666 {
1686 case Q_CODEC_REQUEST_COMPLETE: 1667 case Q_CODEC_REQUEST_COMPLETE:
@@ -2153,7 +2134,7 @@ static void audio_read_file(bool quick)
2153 return ; 2134 return ;
2154 } 2135 }
2155 2136
2156 cpu_boost_id(true, CPUBOOSTID_PLAYBACK_AUDIO); 2137 trigger_cpu_boost();
2157 while (tracks[track_widx].filerem > 0) 2138 while (tracks[track_widx].filerem > 0)
2158 { 2139 {
2159 int overlap; 2140 int overlap;
@@ -2218,7 +2199,6 @@ static void audio_read_file(bool quick)
2218 logf("Partially buf:%dB", 2199 logf("Partially buf:%dB",
2219 tracks[track_widx].filesize - tracks[track_widx].filerem); 2200 tracks[track_widx].filesize - tracks[track_widx].filerem);
2220 } 2201 }
2221 cpu_boost_id(false, CPUBOOSTID_PLAYBACK_AUDIO);
2222} 2202}
2223 2203
2224static bool audio_loadcodec(bool start_play) 2204static bool audio_loadcodec(bool start_play)
@@ -3338,8 +3318,6 @@ static void audio_thread(void)
3338 3318
3339 case SYS_TIMEOUT: 3319 case SYS_TIMEOUT:
3340 LOGFQUEUE("audio < SYS_TIMEOUT"); 3320 LOGFQUEUE("audio < SYS_TIMEOUT");
3341 if (pcmbuf_output_completed())
3342 pcmbuf_play_stop(); /* Stop to ensure unboosted */
3343 break; 3321 break;
3344 3322
3345 default: 3323 default:
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 1b756cc6bd..6a3091de30 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -222,6 +222,7 @@
222 222
223#if (CONFIG_CODEC == SWCODEC) && !defined(SIMULATOR) && !defined(BOOTLOADER) 223#if (CONFIG_CODEC == SWCODEC) && !defined(SIMULATOR) && !defined(BOOTLOADER)
224#define HAVE_PRIORITY_SCHEDULING 224#define HAVE_PRIORITY_SCHEDULING
225#define HAVE_SCHEDULER_BOOSTCTRL
225#endif 226#endif
226 227
227/* define for all cpus from coldfire family */ 228/* define for all cpus from coldfire family */
diff --git a/firmware/export/thread.h b/firmware/export/thread.h
index cd532c8968..17e6e3aa88 100644
--- a/firmware/export/thread.h
+++ b/firmware/export/thread.h
@@ -131,12 +131,18 @@ struct thread_entry*
131 const char *name 131 const char *name
132 IF_PRIO(, int priority)); 132 IF_PRIO(, int priority));
133 133
134#ifdef HAVE_SCHEDULER_BOOSTCTRL
135void trigger_cpu_boost(void);
136#else
137#define trigger_cpu_boost()
138#endif
139
134void remove_thread(struct thread_entry *thread); 140void remove_thread(struct thread_entry *thread);
135void switch_thread(bool save_context, struct thread_entry **blocked_list); 141void switch_thread(bool save_context, struct thread_entry **blocked_list);
136void sleep_thread(int ticks); 142void sleep_thread(int ticks);
137void block_thread(struct thread_entry **thread, int timeout); 143void block_thread(struct thread_entry **thread, int timeout);
138void wakeup_thread(struct thread_entry **thread); 144void wakeup_thread(struct thread_entry **thread);
139void thread_set_priority(struct thread_entry *thread, int priority); 145int thread_set_priority(struct thread_entry *thread, int priority);
140void init_threads(void); 146void init_threads(void);
141int thread_stack_usage(const struct thread_entry *thread); 147int thread_stack_usage(const struct thread_entry *thread);
142int thread_get_status(const struct thread_entry *thread); 148int thread_get_status(const struct thread_entry *thread);
diff --git a/firmware/thread.c b/firmware/thread.c
index 205375a44d..6a94a52333 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -35,6 +35,9 @@ struct core_entry cores[NUM_CORES] IBSS_ATTR;
35#ifdef HAVE_PRIORITY_SCHEDULING 35#ifdef HAVE_PRIORITY_SCHEDULING
36static unsigned short highest_priority IBSS_ATTR; 36static unsigned short highest_priority IBSS_ATTR;
37#endif 37#endif
38#ifdef HAVE_SCHEDULER_BOOSTCTRL
39static bool cpu_boosted IBSS_ATTR;
40#endif
38 41
39/* Define to enable additional checks for blocking violations etc. */ 42/* Define to enable additional checks for blocking violations etc. */
40// #define THREAD_EXTRA_CHECKS 43// #define THREAD_EXTRA_CHECKS
@@ -332,6 +335,14 @@ static inline void sleep_core(void)
332 if (cores[CURRENT_CORE].running != NULL) 335 if (cores[CURRENT_CORE].running != NULL)
333 break; 336 break;
334 337
338#ifdef HAVE_SCHEDULER_BOOSTCTRL
339 if (cpu_boosted)
340 {
341 cpu_boost(false);
342 cpu_boosted = false;
343 }
344#endif
345
335 /* Enter sleep mode to reduce power usage, woken up on interrupt */ 346 /* Enter sleep mode to reduce power usage, woken up on interrupt */
336#ifdef CPU_COLDFIRE 347#ifdef CPU_COLDFIRE
337 asm volatile ("stop #0x2000"); 348 asm volatile ("stop #0x2000");
@@ -646,6 +657,17 @@ struct thread_entry*
646 return thread; 657 return thread;
647} 658}
648 659
660#ifdef HAVE_SCHEDULER_BOOSTCTRL
661void trigger_cpu_boost(void)
662{
663 if (!cpu_boosted)
664 {
665 cpu_boost(true);
666 cpu_boosted = true;
667 }
668}
669#endif
670
649/*--------------------------------------------------------------------------- 671/*---------------------------------------------------------------------------
650 * Remove a thread on the current core from the scheduler. 672 * Remove a thread on the current core from the scheduler.
651 * Parameter is the ID as returned from create_thread(). 673 * Parameter is the ID as returned from create_thread().
@@ -676,13 +698,18 @@ void remove_thread(struct thread_entry *thread)
676} 698}
677 699
678#ifdef HAVE_PRIORITY_SCHEDULING 700#ifdef HAVE_PRIORITY_SCHEDULING
679void thread_set_priority(struct thread_entry *thread, int priority) 701int thread_set_priority(struct thread_entry *thread, int priority)
680{ 702{
703 int old_priority;
704
681 if (thread == NULL) 705 if (thread == NULL)
682 thread = cores[CURRENT_CORE].running; 706 thread = cores[CURRENT_CORE].running;
683 707
708 old_priority = thread->priority;
684 thread->priority = priority; 709 thread->priority = priority;
685 highest_priority = 100; 710 highest_priority = 100;
711
712 return old_priority;
686} 713}
687#endif 714#endif
688 715
@@ -699,6 +726,9 @@ void init_threads(void)
699 cores[core].threads[0].priority = PRIORITY_USER_INTERFACE; 726 cores[core].threads[0].priority = PRIORITY_USER_INTERFACE;
700 highest_priority = 100; 727 highest_priority = 100;
701#endif 728#endif
729#ifdef HAVE_SCHEDULER_BOOSTCTRL
730 cpu_boosted = false;
731#endif
702 add_to_list(&cores[core].running, &cores[core].threads[0]); 732 add_to_list(&cores[core].running, &cores[core].threads[0]);
703 733
704 /* In multiple core setups, each core has a different stack. There is probably 734 /* In multiple core setups, each core has a different stack. There is probably