diff options
Diffstat (limited to 'firmware/pcm_playback.c')
-rw-r--r-- | firmware/pcm_playback.c | 105 |
1 files changed, 67 insertions, 38 deletions
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c index 0d9af14f2c..d3e9f3eca5 100644 --- a/firmware/pcm_playback.c +++ b/firmware/pcm_playback.c | |||
@@ -61,11 +61,11 @@ static bool pcm_playing; | |||
61 | static bool pcm_paused; | 61 | static bool pcm_paused; |
62 | static int pcm_freq = 0x6; /* 44.1 is default */ | 62 | static int pcm_freq = 0x6; /* 44.1 is default */ |
63 | 63 | ||
64 | static unsigned char *next_start IDATA_ATTR; | 64 | size_t next_size IBSS_ATTR; |
65 | static long next_size IDATA_ATTR; | 65 | unsigned char *next_start IBSS_ATTR; |
66 | 66 | ||
67 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ | 67 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ |
68 | static void dma_start(const void *addr, long size) | 68 | static void dma_start(const void *addr, size_t size) |
69 | { | 69 | { |
70 | pcm_playing = true; | 70 | pcm_playing = true; |
71 | 71 | ||
@@ -104,8 +104,6 @@ static void dma_stop(void) | |||
104 | EBU1CONFIG = IIS_RESET | EBU_DEFPARM; | 104 | EBU1CONFIG = IIS_RESET | EBU_DEFPARM; |
105 | #endif | 105 | #endif |
106 | 106 | ||
107 | next_start = NULL; | ||
108 | next_size = 0; | ||
109 | pcm_paused = false; | 107 | pcm_paused = false; |
110 | } | 108 | } |
111 | 109 | ||
@@ -131,23 +129,27 @@ void pcm_set_frequency(unsigned int frequency) | |||
131 | } | 129 | } |
132 | 130 | ||
133 | /* the registered callback function to ask for more mp3 data */ | 131 | /* the registered callback function to ask for more mp3 data */ |
134 | static void (*callback_for_more)(unsigned char**, long*) IDATA_ATTR = NULL; | 132 | static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL; |
135 | 133 | ||
136 | void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) | 134 | void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size), |
135 | unsigned char* start, size_t size) | ||
137 | { | 136 | { |
138 | unsigned char *start; | ||
139 | long size; | ||
140 | |||
141 | callback_for_more = get_more; | 137 | callback_for_more = get_more; |
142 | 138 | ||
143 | get_more((unsigned char **)&start, (long *)&size); | 139 | if (!(start && size)) |
144 | get_more(&next_start, &next_size); | 140 | { |
145 | dma_start(start, size); | 141 | if (get_more) |
142 | get_more(&start, &size); | ||
143 | else | ||
144 | return; | ||
145 | } | ||
146 | if (start && size) | ||
147 | dma_start(start, size); | ||
146 | } | 148 | } |
147 | 149 | ||
148 | long pcm_get_bytes_waiting(void) | 150 | size_t pcm_get_bytes_waiting(void) |
149 | { | 151 | { |
150 | return next_size + (BCR0 & 0xffffff); | 152 | return (BCR0 & 0xffffff); |
151 | } | 153 | } |
152 | 154 | ||
153 | void pcm_mute(bool mute) | 155 | void pcm_mute(bool mute) |
@@ -169,19 +171,32 @@ void pcm_play_pause(bool play) | |||
169 | if (!pcm_playing) | 171 | if (!pcm_playing) |
170 | return ; | 172 | return ; |
171 | 173 | ||
172 | if(pcm_paused && play && next_size) | 174 | if(pcm_paused && play) |
173 | { | 175 | { |
174 | logf("unpause"); | 176 | if (BCR0 & 0xffffff) |
175 | /* Reset chunk size so dma has enough data to fill the fifo. */ | 177 | { |
176 | /* This shouldn't be needed anymore. */ | 178 | logf("unpause"); |
177 | //SAR0 = (unsigned long)next_start; | 179 | /* Enable the FIFO and force one write to it */ |
178 | //BCR0 = next_size; | 180 | IIS2CONFIG = IIS_DEFPARM(pcm_freq); |
179 | /* Enable the FIFO and force one write to it */ | ||
180 | IIS2CONFIG = IIS_DEFPARM(pcm_freq); | ||
181 | #ifdef HAVE_SPDIF_OUT | 181 | #ifdef HAVE_SPDIF_OUT |
182 | EBU1CONFIG = EBU_DEFPARM; | 182 | EBU1CONFIG = EBU_DEFPARM; |
183 | #endif | 183 | #endif |
184 | DCR0 |= DMA_EEXT | DMA_START; | 184 | DCR0 |= DMA_EEXT | DMA_START; |
185 | } | ||
186 | else | ||
187 | { | ||
188 | logf("unpause, no data waiting"); | ||
189 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; | ||
190 | if (get_more) | ||
191 | get_more(&next_start, &next_size); | ||
192 | if (next_start && next_size) | ||
193 | dma_start(next_start, next_size); | ||
194 | else | ||
195 | { | ||
196 | dma_stop(); | ||
197 | logf("unpause attempted, no data"); | ||
198 | } | ||
199 | } | ||
185 | } | 200 | } |
186 | else if(!pcm_paused && !play) | 201 | else if(!pcm_paused && !play) |
187 | { | 202 | { |
@@ -224,13 +239,22 @@ void DMA0(void) | |||
224 | } | 239 | } |
225 | else | 240 | else |
226 | { | 241 | { |
242 | { | ||
243 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; | ||
244 | if (get_more) | ||
245 | get_more(&next_start, &next_size); | ||
246 | else | ||
247 | { | ||
248 | next_size = 0; | ||
249 | next_start = NULL; | ||
250 | } | ||
251 | } | ||
227 | if(next_size) | 252 | if(next_size) |
228 | { | 253 | { |
229 | SAR0 = (unsigned long)next_start; /* Source address */ | 254 | SAR0 = (unsigned long)next_start; /* Source address */ |
230 | BCR0 = next_size; /* Bytes to transfer */ | 255 | BCR0 = next_size; /* Bytes to transfer */ |
231 | DCR0 |= DMA_EEXT; | 256 | DCR0 |= DMA_EEXT; |
232 | if (callback_for_more) | 257 | |
233 | callback_for_more(&next_start, &next_size); | ||
234 | } | 258 | } |
235 | else | 259 | else |
236 | { | 260 | { |
@@ -301,9 +325,9 @@ static bool pcm_paused; | |||
301 | static int pcm_freq = 0x6; /* 44.1 is default */ | 325 | static int pcm_freq = 0x6; /* 44.1 is default */ |
302 | 326 | ||
303 | /* the registered callback function to ask for more mp3 data */ | 327 | /* the registered callback function to ask for more mp3 data */ |
304 | static void (*callback_for_more)(unsigned char**, long*) = NULL; | 328 | static void (*callback_for_more)(unsigned char**, size_t*) = NULL; |
305 | static unsigned short *p IBSS_ATTR; | 329 | static unsigned short *p IBSS_ATTR; |
306 | static long size IBSS_ATTR; | 330 | static size_t size IBSS_ATTR; |
307 | 331 | ||
308 | /* Stops the DMA transfer and interrupt */ | 332 | /* Stops the DMA transfer and interrupt */ |
309 | static void dma_stop(void) | 333 | static void dma_stop(void) |
@@ -353,7 +377,7 @@ void fiq(void) | |||
353 | IISCONFIG &= ~0x2; | 377 | IISCONFIG &= ~0x2; |
354 | 378 | ||
355 | if ((size==0) && (callback_for_more)) { | 379 | if ((size==0) && (callback_for_more)) { |
356 | callback_for_more((unsigned char **)&p, (long *)&size); | 380 | callback_for_more((unsigned char **)&p, &size); |
357 | } | 381 | } |
358 | 382 | ||
359 | while (size > 0) { | 383 | while (size > 0) { |
@@ -368,20 +392,22 @@ void fiq(void) | |||
368 | size-=4; | 392 | size-=4; |
369 | 393 | ||
370 | if ((size==0) && (callback_for_more)) { | 394 | if ((size==0) && (callback_for_more)) { |
371 | callback_for_more((unsigned char **)&p, (long *)&size); | 395 | callback_for_more((unsigned char **)&p, &size); |
372 | } | 396 | } |
373 | } | 397 | } |
374 | } | 398 | } |
375 | 399 | ||
376 | void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) | 400 | void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size), |
401 | unsigned char* _p, size_t _size) | ||
377 | { | 402 | { |
378 | int free_count; | 403 | size_t free_count; |
379 | 404 | ||
380 | callback_for_more = get_more; | 405 | callback_for_more = get_more; |
381 | 406 | ||
382 | if (size > 0) { return; } | 407 | if (size > 0) { return; } |
383 | 408 | ||
384 | get_more((unsigned char **)&p, (long *)&size); | 409 | p = (unsigned short *)_p; |
410 | size = _size; | ||
385 | 411 | ||
386 | /* setup I2S interrupt for FIQ */ | 412 | /* setup I2S interrupt for FIQ */ |
387 | outl(inl(0x6000402c) | I2S_MASK, 0x6000402c); | 413 | outl(inl(0x6000402c) | I2S_MASK, 0x6000402c); |
@@ -406,7 +432,7 @@ void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) | |||
406 | size-=4; | 432 | size-=4; |
407 | 433 | ||
408 | if ((size==0) && (get_more)) { | 434 | if ((size==0) && (get_more)) { |
409 | get_more((unsigned char **)&p, (long *)&size); | 435 | get_more((unsigned char **)&p, &size); |
410 | } | 436 | } |
411 | } | 437 | } |
412 | } | 438 | } |
@@ -448,7 +474,7 @@ bool pcm_is_playing(void) | |||
448 | return pcm_playing; | 474 | return pcm_playing; |
449 | } | 475 | } |
450 | 476 | ||
451 | long pcm_get_bytes_waiting(void) | 477 | size_t pcm_get_bytes_waiting(void) |
452 | { | 478 | { |
453 | return size; | 479 | return size; |
454 | } | 480 | } |
@@ -608,9 +634,12 @@ void pcm_set_frequency(unsigned int frequency) | |||
608 | (void)frequency; | 634 | (void)frequency; |
609 | } | 635 | } |
610 | 636 | ||
611 | void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) | 637 | void pcm_play_data(void (*get_more)(unsigned char** start, long* size), |
638 | unsigned char* start, long size) | ||
612 | { | 639 | { |
613 | (void)get_more; | 640 | (void)get_more; |
641 | (void)start; | ||
642 | (void)size; | ||
614 | } | 643 | } |
615 | 644 | ||
616 | void pcm_play_stop(void) | 645 | void pcm_play_stop(void) |