diff options
-rw-r--r-- | apps/pcmbuf.c | 5 | ||||
-rw-r--r-- | firmware/pcm_playback.c | 187 |
2 files changed, 104 insertions, 88 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 31b59f88f6..6a8e2f2607 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -390,8 +390,11 @@ static void pcmbuf_flush_audio(void) | |||
390 | } | 390 | } |
391 | 391 | ||
392 | void pcmbuf_pause(bool pause) { | 392 | void pcmbuf_pause(bool pause) { |
393 | pcm_mute(pause); | 393 | if (pause) |
394 | pcm_mute(true); | ||
394 | pcm_play_pause(!pause); | 395 | pcm_play_pause(!pause); |
396 | if (!pause) | ||
397 | pcm_mute(false); | ||
395 | pcmbuf_boost(!pause); | 398 | pcmbuf_boost(!pause); |
396 | } | 399 | } |
397 | 400 | ||
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c index 1b6a1871ad..c692e5d817 100644 --- a/firmware/pcm_playback.c +++ b/firmware/pcm_playback.c | |||
@@ -61,9 +61,6 @@ 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 | size_t next_size IBSS_ATTR; | ||
65 | unsigned char *next_start IBSS_ATTR; | ||
66 | |||
67 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ | 64 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ |
68 | static void dma_start(const void *addr, size_t size) | 65 | static void dma_start(const void *addr, size_t size) |
69 | { | 66 | { |
@@ -103,8 +100,6 @@ static void dma_stop(void) | |||
103 | #ifdef HAVE_SPDIF_OUT | 100 | #ifdef HAVE_SPDIF_OUT |
104 | EBU1CONFIG = IIS_RESET | EBU_DEFPARM; | 101 | EBU1CONFIG = IIS_RESET | EBU_DEFPARM; |
105 | #endif | 102 | #endif |
106 | |||
107 | pcm_paused = false; | ||
108 | } | 103 | } |
109 | 104 | ||
110 | /* sets frequency of input to DAC */ | 105 | /* sets frequency of input to DAC */ |
@@ -150,7 +145,13 @@ void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size), | |||
150 | return; | 145 | return; |
151 | } | 146 | } |
152 | if (start && size) | 147 | if (start && size) |
148 | { | ||
153 | dma_start(start, size); | 149 | dma_start(start, size); |
150 | if (pcm_paused) { | ||
151 | pcm_paused = false; | ||
152 | pcm_play_pause(false); | ||
153 | } | ||
154 | } | ||
154 | } | 155 | } |
155 | 156 | ||
156 | size_t pcm_get_bytes_waiting(void) | 157 | size_t pcm_get_bytes_waiting(void) |
@@ -176,48 +177,54 @@ void pcm_play_stop(void) | |||
176 | 177 | ||
177 | void pcm_play_pause(bool play) | 178 | void pcm_play_pause(bool play) |
178 | { | 179 | { |
179 | if (!pcm_playing) | 180 | size_t next_size; |
180 | return ; | 181 | unsigned char *next_start; |
182 | bool needs_change = pcm_paused == play; | ||
181 | 183 | ||
182 | if(pcm_paused && play) | 184 | /* This must be done ahead of the rest of the function to prevent |
185 | * infinite recursion in dma_start */ | ||
186 | pcm_paused = !play; | ||
187 | if (pcm_playing && needs_change) | ||
183 | { | 188 | { |
184 | if (BCR0 & 0xffffff) | 189 | if(play) |
185 | { | 190 | { |
186 | logf("unpause"); | 191 | if (pcm_get_bytes_waiting()) |
187 | /* Enable the FIFO and force one write to it */ | 192 | { |
188 | IIS2CONFIG = IIS_DEFPARM(pcm_freq); | 193 | logf("unpause"); |
194 | /* Enable the FIFO and force one write to it */ | ||
195 | IIS2CONFIG = IIS_DEFPARM(pcm_freq); | ||
189 | #ifdef HAVE_SPDIF_OUT | 196 | #ifdef HAVE_SPDIF_OUT |
190 | EBU1CONFIG = EBU_DEFPARM; | 197 | EBU1CONFIG = EBU_DEFPARM; |
191 | #endif | 198 | #endif |
192 | DCR0 |= DMA_EEXT | DMA_START; | 199 | DCR0 |= DMA_EEXT | DMA_START; |
193 | } | 200 | } |
194 | else | ||
195 | { | ||
196 | logf("unpause, no data waiting"); | ||
197 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; | ||
198 | if (get_more) | ||
199 | get_more(&next_start, &next_size); | ||
200 | if (next_start && next_size) | ||
201 | dma_start(next_start, next_size); | ||
202 | else | 201 | else |
203 | { | 202 | { |
204 | dma_stop(); | 203 | logf("unpause, no data waiting"); |
205 | logf("unpause attempted, no data"); | 204 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; |
205 | if (get_more) | ||
206 | get_more(&next_start, &next_size); | ||
207 | if (next_start && next_size) | ||
208 | dma_start(next_start, next_size); | ||
209 | else | ||
210 | { | ||
211 | dma_stop(); | ||
212 | logf("unpause attempted, no data"); | ||
213 | } | ||
206 | } | 214 | } |
207 | } | 215 | } |
208 | } | 216 | else |
209 | else if(!pcm_paused && !play) | 217 | { |
210 | { | 218 | logf("pause"); |
211 | logf("pause"); | ||
212 | 219 | ||
213 | /* Disable DMA peripheral request. */ | 220 | /* Disable DMA peripheral request. */ |
214 | DCR0 &= ~DMA_EEXT; | 221 | DCR0 &= ~DMA_EEXT; |
215 | IIS2CONFIG = IIS_RESET | IIS_DEFPARM(pcm_freq); | 222 | IIS2CONFIG = IIS_RESET | IIS_DEFPARM(pcm_freq); |
216 | #ifdef HAVE_SPDIF_OUT | 223 | #ifdef HAVE_SPDIF_OUT |
217 | EBU1CONFIG = IIS_RESET | EBU_DEFPARM; | 224 | EBU1CONFIG = IIS_RESET | EBU_DEFPARM; |
218 | #endif | 225 | #endif |
226 | } | ||
219 | } | 227 | } |
220 | pcm_paused = !play; | ||
221 | } | 228 | } |
222 | 229 | ||
223 | bool pcm_is_paused(void) | 230 | bool pcm_is_paused(void) |
@@ -247,6 +254,8 @@ void DMA0(void) | |||
247 | } | 254 | } |
248 | else | 255 | else |
249 | { | 256 | { |
257 | size_t next_size; | ||
258 | unsigned char *next_start; | ||
250 | { | 259 | { |
251 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; | 260 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; |
252 | if (get_more) | 261 | if (get_more) |
@@ -412,8 +421,6 @@ static void dma_stop(void) | |||
412 | #endif | 421 | #endif |
413 | 422 | ||
414 | disable_fiq(); | 423 | disable_fiq(); |
415 | |||
416 | pcm_paused = false; | ||
417 | } | 424 | } |
418 | 425 | ||
419 | void pcm_set_frequency(unsigned int frequency) | 426 | void pcm_set_frequency(unsigned int frequency) |
@@ -436,8 +443,13 @@ void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size), | |||
436 | else | 443 | else |
437 | return; | 444 | return; |
438 | } | 445 | } |
439 | if (start && size) | 446 | if (start && size) { |
440 | dma_start(start, size); | 447 | dma_start(start, size); |
448 | if (pcm_paused) { | ||
449 | pcm_paused = false; | ||
450 | pcm_play_pause(false); | ||
451 | } | ||
452 | } | ||
441 | } | 453 | } |
442 | 454 | ||
443 | size_t pcm_get_bytes_waiting(void) | 455 | size_t pcm_get_bytes_waiting(void) |
@@ -464,82 +476,85 @@ void pcm_play_pause(bool play) | |||
464 | size_t next_size; | 476 | size_t next_size; |
465 | unsigned char *next_start; | 477 | unsigned char *next_start; |
466 | 478 | ||
467 | if (!pcm_playing) | 479 | bool needs_change = pcm_paused == play; |
468 | return ; | 480 | /* This needs to be done ahead of the rest to prevent infinite |
469 | 481 | * recursion from dma_start */ | |
470 | if(pcm_paused && play) | 482 | pcm_paused = !play; |
483 | if (pcm_playing && needs_change) | ||
471 | { | 484 | { |
472 | if (pcm_get_bytes_waiting()) | 485 | if(play) |
473 | { | 486 | { |
474 | logf("unpause"); | 487 | if (pcm_get_bytes_waiting()) |
475 | /* Enable the FIFO and fill it */ | 488 | { |
489 | logf("unpause"); | ||
490 | /* Enable the FIFO and fill it */ | ||
476 | 491 | ||
477 | enable_fiq(); | 492 | enable_fiq(); |
478 | 493 | ||
479 | /* Enable playback FIFO */ | 494 | /* Enable playback FIFO */ |
480 | #if CONFIG_CPU == PP5020 | 495 | #if CONFIG_CPU == PP5020 |
481 | IISCONFIG |= 0x20000000; | 496 | IISCONFIG |= 0x20000000; |
482 | #elif CONFIG_CPU == PP5002 | 497 | #elif CONFIG_CPU == PP5002 |
483 | IISCONFIG |= 0x4; | 498 | IISCONFIG |= 0x4; |
484 | #endif | 499 | #endif |
485 | 500 | ||
486 | /* Fill the FIFO - we assume there are enough bytes in the | 501 | /* Fill the FIFO - we assume there are enough bytes in the |
487 | pcm buffer to fill the 32-byte FIFO. */ | 502 | pcm buffer to fill the 32-byte FIFO. */ |
488 | while (p_size > 0) { | 503 | while (p_size > 0) { |
489 | if (FIFO_FREE_COUNT < 2) { | 504 | if (FIFO_FREE_COUNT < 2) { |
490 | /* Enable interrupt */ | 505 | /* Enable interrupt */ |
491 | #if CONFIG_CPU == PP5020 | 506 | #if CONFIG_CPU == PP5020 |
492 | IISCONFIG |= 0x2; | 507 | IISCONFIG |= 0x2; |
493 | #elif CONFIG_CPU == PP5002 | 508 | #elif CONFIG_CPU == PP5002 |
494 | IISFIFO_CFG |= (1<<9); | 509 | IISFIFO_CFG |= (1<<9); |
495 | #endif | 510 | #endif |
496 | return; | 511 | return; |
497 | } | 512 | } |
498 | 513 | ||
499 | IISFIFO_WR = (*(p++))<<16; | 514 | IISFIFO_WR = (*(p++))<<16; |
500 | IISFIFO_WR = (*(p++))<<16; | 515 | IISFIFO_WR = (*(p++))<<16; |
501 | p_size-=4; | 516 | p_size-=4; |
517 | } | ||
502 | } | 518 | } |
503 | } | ||
504 | else | ||
505 | { | ||
506 | logf("unpause, no data waiting"); | ||
507 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; | ||
508 | if (get_more) | ||
509 | get_more(&next_start, &next_size); | ||
510 | if (next_start && next_size) | ||
511 | dma_start(next_start, next_size); | ||
512 | else | 519 | else |
513 | { | 520 | { |
514 | dma_stop(); | 521 | logf("unpause, no data waiting"); |
515 | logf("unpause attempted, no data"); | 522 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; |
523 | if (get_more) | ||
524 | get_more(&next_start, &next_size); | ||
525 | if (next_start && next_size) | ||
526 | dma_start(next_start, next_size); | ||
527 | else | ||
528 | { | ||
529 | dma_stop(); | ||
530 | logf("unpause attempted, no data"); | ||
531 | } | ||
516 | } | 532 | } |
517 | } | 533 | } |
518 | } | 534 | else |
519 | else if(!pcm_paused && !play) | 535 | { |
520 | { | 536 | logf("pause"); |
521 | logf("pause"); | ||
522 | 537 | ||
523 | #if CONFIG_CPU == PP5020 | 538 | #if CONFIG_CPU == PP5020 |
524 | 539 | ||
525 | /* Disable the interrupt */ | 540 | /* Disable the interrupt */ |
526 | IISCONFIG &= ~0x2; | 541 | IISCONFIG &= ~0x2; |
527 | 542 | ||
528 | /* Disable playback FIFO */ | 543 | /* Disable playback FIFO */ |
529 | IISCONFIG &= ~0x20000000; | 544 | IISCONFIG &= ~0x20000000; |
530 | 545 | ||
531 | #elif CONFIG_CPU == PP5002 | 546 | #elif CONFIG_CPU == PP5002 |
532 | 547 | ||
533 | /* Disable the interrupt */ | 548 | /* Disable the interrupt */ |
534 | IISFIFO_CFG &= ~(1<<9); | 549 | IISFIFO_CFG &= ~(1<<9); |
535 | 550 | ||
536 | /* Disable playback FIFO */ | 551 | /* Disable playback FIFO */ |
537 | IISCONFIG &= ~0x4; | 552 | IISCONFIG &= ~0x4; |
538 | #endif | 553 | #endif |
539 | 554 | ||
540 | disable_fiq(); | 555 | disable_fiq(); |
556 | } | ||
541 | } | 557 | } |
542 | pcm_paused = !play; | ||
543 | } | 558 | } |
544 | 559 | ||
545 | bool pcm_is_paused(void) | 560 | bool pcm_is_paused(void) |
@@ -615,8 +630,6 @@ void fiq(void) | |||
615 | "mrs r10, cpsr \n\t" | 630 | "mrs r10, cpsr \n\t" |
616 | "orr r10, r10, #0x40 \n\t" /* disable FIQ */ | 631 | "orr r10, r10, #0x40 \n\t" /* disable FIQ */ |
617 | "msr cpsr_c, r10 \n\t" | 632 | "msr cpsr_c, r10 \n\t" |
618 | "ldr r10, =pcm_paused \n\t" | ||
619 | "strb r8, [r10] \n\t" /* pcm_paused = false */ | ||
620 | ".exit: \n\t" | 633 | ".exit: \n\t" |
621 | "str r8, [r11, #4] \n\t" | 634 | "str r8, [r11, #4] \n\t" |
622 | "str r9, [r11] \n\t" | 635 | "str r9, [r11] \n\t" |