summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/pcmbuf.c5
-rw-r--r--firmware/pcm_playback.c187
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
392void pcmbuf_pause(bool pause) { 392void 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;
61static bool pcm_paused; 61static bool pcm_paused;
62static int pcm_freq = 0x6; /* 44.1 is default */ 62static int pcm_freq = 0x6; /* 44.1 is default */
63 63
64size_t next_size IBSS_ATTR;
65unsigned 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 */
68static void dma_start(const void *addr, size_t size) 65static 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
156size_t pcm_get_bytes_waiting(void) 157size_t pcm_get_bytes_waiting(void)
@@ -176,48 +177,54 @@ void pcm_play_stop(void)
176 177
177void pcm_play_pause(bool play) 178void 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
223bool pcm_is_paused(void) 230bool 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
419void pcm_set_frequency(unsigned int frequency) 426void 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
443size_t pcm_get_bytes_waiting(void) 455size_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
545bool pcm_is_paused(void) 560bool 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"