summaryrefslogtreecommitdiff
path: root/firmware/pcm_playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/pcm_playback.c')
-rw-r--r--firmware/pcm_playback.c418
1 files changed, 150 insertions, 268 deletions
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index c692e5d817..6ce5ed671c 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -49,6 +49,12 @@
49#include "button.h" 49#include "button.h"
50#include <string.h> 50#include <string.h>
51 51
52static bool pcm_playing;
53static bool pcm_paused;
54
55/* the registered callback function to ask for more mp3 data */
56static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL;
57
52#ifdef CPU_COLDFIRE 58#ifdef CPU_COLDFIRE
53 59
54#ifdef HAVE_SPDIF_OUT 60#ifdef HAVE_SPDIF_OUT
@@ -57,8 +63,6 @@
57#define IIS_DEFPARM(freq) ((freq << 12) | 0x300 | 4 << 2) 63#define IIS_DEFPARM(freq) ((freq << 12) | 0x300 | 4 << 2)
58#define IIS_RESET 0x800 64#define IIS_RESET 0x800
59 65
60static bool pcm_playing;
61static bool pcm_paused;
62static int pcm_freq = 0x6; /* 44.1 is default */ 66static int pcm_freq = 0x6; /* 44.1 is default */
63 67
64/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ 68/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
@@ -129,114 +133,11 @@ void pcm_set_frequency(unsigned int frequency)
129 } 133 }
130} 134}
131 135
132/* the registered callback function to ask for more mp3 data */
133static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL;
134
135void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size),
136 unsigned char* start, size_t size)
137{
138 callback_for_more = get_more;
139
140 if (!(start && size))
141 {
142 if (get_more)
143 get_more(&start, &size);
144 else
145 return;
146 }
147 if (start && size)
148 {
149 dma_start(start, size);
150 if (pcm_paused) {
151 pcm_paused = false;
152 pcm_play_pause(false);
153 }
154 }
155}
156
157size_t pcm_get_bytes_waiting(void) 136size_t pcm_get_bytes_waiting(void)
158{ 137{
159 return (BCR0 & 0xffffff); 138 return (BCR0 & 0xffffff);
160} 139}
161 140
162void pcm_mute(bool mute)
163{
164#ifdef HAVE_UDA1380
165 uda1380_mute(mute);
166#endif
167 if (mute)
168 sleep(HZ/16);
169}
170
171void pcm_play_stop(void)
172{
173 if (pcm_playing) {
174 dma_stop();
175 }
176}
177
178void pcm_play_pause(bool play)
179{
180 size_t next_size;
181 unsigned char *next_start;
182 bool needs_change = pcm_paused == play;
183
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)
188 {
189 if(play)
190 {
191 if (pcm_get_bytes_waiting())
192 {
193 logf("unpause");
194 /* Enable the FIFO and force one write to it */
195 IIS2CONFIG = IIS_DEFPARM(pcm_freq);
196#ifdef HAVE_SPDIF_OUT
197 EBU1CONFIG = EBU_DEFPARM;
198#endif
199 DCR0 |= DMA_EEXT | DMA_START;
200 }
201 else
202 {
203 logf("unpause, no data waiting");
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 }
214 }
215 }
216 else
217 {
218 logf("pause");
219
220 /* Disable DMA peripheral request. */
221 DCR0 &= ~DMA_EEXT;
222 IIS2CONFIG = IIS_RESET | IIS_DEFPARM(pcm_freq);
223#ifdef HAVE_SPDIF_OUT
224 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
225#endif
226 }
227 }
228}
229
230bool pcm_is_paused(void)
231{
232 return pcm_paused;
233}
234
235bool pcm_is_playing(void)
236{
237 return pcm_playing;
238}
239
240/* DMA0 Interrupt is called when the DMA has finished transfering a chunk */ 141/* DMA0 Interrupt is called when the DMA has finished transfering a chunk */
241void DMA0(void) __attribute__ ((interrupt_handler, section(".icode"))); 142void DMA0(void) __attribute__ ((interrupt_handler, section(".icode")));
242void DMA0(void) 143void DMA0(void)
@@ -343,9 +244,7 @@ void pcm_init(void)
343#define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x7800000) >> 23) 244#define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x7800000) >> 23)
344#endif 245#endif
345 246
346static bool pcm_playing; 247static int pcm_freq = 44100; /* 44.1 is default */
347static bool pcm_paused;
348static int pcm_freq = 0x6; /* 44.1 is default */
349 248
350/* NOTE: The order of these two variables is important if you use the iPod 249/* NOTE: The order of these two variables is important if you use the iPod
351 assembler optimised fiq handler, so don't change it. */ 250 assembler optimised fiq handler, so don't change it. */
@@ -428,145 +327,11 @@ void pcm_set_frequency(unsigned int frequency)
428 pcm_freq=frequency; 327 pcm_freq=frequency;
429} 328}
430 329
431/* the registered callback function to ask for more PCM data */
432static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL;
433
434void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size),
435 unsigned char* start, size_t size)
436{
437 callback_for_more = get_more;
438
439 if (!(start && size))
440 {
441 if (get_more)
442 get_more(&start, &size);
443 else
444 return;
445 }
446 if (start && size) {
447 dma_start(start, size);
448 if (pcm_paused) {
449 pcm_paused = false;
450 pcm_play_pause(false);
451 }
452 }
453}
454
455size_t pcm_get_bytes_waiting(void) 330size_t pcm_get_bytes_waiting(void)
456{ 331{
457 return p_size; 332 return p_size;
458} 333}
459 334
460void pcm_mute(bool mute)
461{
462 wmcodec_mute(mute);
463 if (mute)
464 sleep(HZ/16);
465}
466
467void pcm_play_stop(void)
468{
469 if (pcm_playing) {
470 dma_stop();
471 }
472}
473
474void pcm_play_pause(bool play)
475{
476 size_t next_size;
477 unsigned char *next_start;
478
479 bool needs_change = pcm_paused == play;
480 /* This needs to be done ahead of the rest to prevent infinite
481 * recursion from dma_start */
482 pcm_paused = !play;
483 if (pcm_playing && needs_change)
484 {
485 if(play)
486 {
487 if (pcm_get_bytes_waiting())
488 {
489 logf("unpause");
490 /* Enable the FIFO and fill it */
491
492 enable_fiq();
493
494 /* Enable playback FIFO */
495#if CONFIG_CPU == PP5020
496 IISCONFIG |= 0x20000000;
497#elif CONFIG_CPU == PP5002
498 IISCONFIG |= 0x4;
499#endif
500
501 /* Fill the FIFO - we assume there are enough bytes in the
502 pcm buffer to fill the 32-byte FIFO. */
503 while (p_size > 0) {
504 if (FIFO_FREE_COUNT < 2) {
505 /* Enable interrupt */
506#if CONFIG_CPU == PP5020
507 IISCONFIG |= 0x2;
508#elif CONFIG_CPU == PP5002
509 IISFIFO_CFG |= (1<<9);
510#endif
511 return;
512 }
513
514 IISFIFO_WR = (*(p++))<<16;
515 IISFIFO_WR = (*(p++))<<16;
516 p_size-=4;
517 }
518 }
519 else
520 {
521 logf("unpause, no data waiting");
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 }
532 }
533 }
534 else
535 {
536 logf("pause");
537
538#if CONFIG_CPU == PP5020
539
540 /* Disable the interrupt */
541 IISCONFIG &= ~0x2;
542
543 /* Disable playback FIFO */
544 IISCONFIG &= ~0x20000000;
545
546#elif CONFIG_CPU == PP5002
547
548 /* Disable the interrupt */
549 IISFIFO_CFG &= ~(1<<9);
550
551 /* Disable playback FIFO */
552 IISCONFIG &= ~0x4;
553#endif
554
555 disable_fiq();
556 }
557 }
558}
559
560bool pcm_is_paused(void)
561{
562 return pcm_paused;
563}
564
565bool pcm_is_playing(void)
566{
567 return pcm_playing;
568}
569
570/* ASM optimised FIQ handler. GCC fails to make use of the fact that FIQ mode 335/* ASM optimised FIQ handler. GCC fails to make use of the fact that FIQ mode
571 has registers r8-r14 banked, and so does not need to be saved. This routine 336 has registers r8-r14 banked, and so does not need to be saved. This routine
572 uses only these registers, and so will never touch the stack unless it 337 uses only these registers, and so will never touch the stack unless it
@@ -717,52 +482,166 @@ void pcm_set_frequency(unsigned int frequency)
717 (void)frequency; 482 (void)frequency;
718} 483}
719 484
720void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size),
721 unsigned char* start, size_t size)
722{
723 (void)get_more;
724 (void)start;
725 (void)size;
726}
727
728void pcm_play_stop(void) 485void pcm_play_stop(void)
729{ 486{
730} 487}
731 488
732void pcm_mute(bool mute) 489size_t pcm_get_bytes_waiting(void)
733{ 490{
734 (void)mute; 491 return 0;
735} 492}
736 493
737void pcm_play_pause(bool play) 494#endif
738{
739 (void)play;
740}
741 495
742bool pcm_is_paused(void) 496void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size),
497 unsigned char* start, size_t size)
743{ 498{
744 return false; 499 callback_for_more = get_more;
500
501 if (!(start && size))
502 {
503 if (get_more)
504 get_more(&start, &size);
505 else
506 return;
507 }
508 if (start && size)
509 {
510 dma_start(start, size);
511 if (pcm_paused) {
512 pcm_paused = false;
513 pcm_play_pause(false);
514 }
515 }
745} 516}
746 517
747bool pcm_is_playing(void) 518void pcm_mute(bool mute)
748{ 519{
749 return false; 520#ifdef HAVE_UDA1380
521 uda1380_mute(mute);
522#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
523 wmcodec_mute(mute);
524#elif defined(HAVE_TLV320)
525 tlv320_mute(mute);
526#endif
527 if (mute)
528 sleep(HZ/16);
750} 529}
751 530
752void pcm_calculate_peaks(int *left, int *right) 531void pcm_play_stop(void)
753{ 532{
754 (void)left; 533 if (pcm_playing) {
755 (void)right; 534 dma_stop();
535 }
756} 536}
757 537
758size_t pcm_get_bytes_waiting(void) 538void pcm_play_pause(bool play)
759{ 539{
760 return 0; 540 bool needs_change = pcm_paused == play;
761} 541
542 /* This needs to be done ahead of the rest to prevent infinite
543 * recursion from dma_start */
544 pcm_paused = !play;
545 if (pcm_playing && needs_change) {
546 if(play) {
547 if (pcm_get_bytes_waiting()) {
548 logf("unpause");
549
550#ifdef CPU_COLDFIRE
551 /* Enable the FIFO and force one write to it */
552 IIS2CONFIG = IIS_DEFPARM(pcm_freq);
553#ifdef HAVE_SPDIF_OUT
554 EBU1CONFIG = EBU_DEFPARM;
555#endif
556 DCR0 |= DMA_EEXT | DMA_START;
557#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
558 /* Enable the FIFO and fill it */
559
560 enable_fiq();
762 561
562 /* Enable playback FIFO */
563#if CONFIG_CPU == PP5020
564 IISCONFIG |= 0x20000000;
565#elif CONFIG_CPU == PP5002
566 IISCONFIG |= 0x4;
763#endif 567#endif
764 568
569 /* Fill the FIFO - we assume there are enough bytes in the
570 pcm buffer to fill the 32-byte FIFO. */
571 while (p_size > 0) {
572 if (FIFO_FREE_COUNT < 2) {
573 /* Enable interrupt */
574#if CONFIG_CPU == PP5020
575 IISCONFIG |= 0x2;
576#elif CONFIG_CPU == PP5002
577 IISFIFO_CFG |= (1<<9);
578#endif
579 return;
580 }
581
582 IISFIFO_WR = (*(p++))<<16;
583 IISFIFO_WR = (*(p++))<<16;
584 p_size-=4;
585 }
586#elif (CONFIG_CPU == PNX0101) /* End wmcodecs */
587 /* nothing yet */
588#endif
589 } else {
765#if (CONFIG_CPU != PNX0101) 590#if (CONFIG_CPU != PNX0101)
591 size_t next_size;
592 unsigned char *next_start;
593 void (*get_more)(unsigned char**, size_t*) = callback_for_more;
594 logf("unpause, no data waiting");
595 if (get_more)
596 get_more(&next_start, &next_size);
597 if (next_start && next_size)
598 dma_start(next_start, next_size);
599 else
600 {
601 dma_stop();
602 logf("unpause attempted, no data");
603 }
604#endif
605 }
606 } else {
607 logf("pause");
608
609#ifdef CPU_COLDFIRE
610 /* Disable DMA peripheral request. */
611 DCR0 &= ~DMA_EEXT;
612 IIS2CONFIG = IIS_RESET | IIS_DEFPARM(pcm_freq);
613#ifdef HAVE_SPDIF_OUT
614 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
615#endif
616#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
617#if CONFIG_CPU == PP5020
618 /* Disable the interrupt */
619 IISCONFIG &= ~0x2;
620 /* Disable playback FIFO */
621 IISCONFIG &= ~0x20000000;
622#elif CONFIG_CPU == PP5002
623 /* Disable the interrupt */
624 IISFIFO_CFG &= ~(1<<9);
625 /* Disable playback FIFO */
626 IISCONFIG &= ~0x4;
627#endif
628
629 disable_fiq();
630#elif (CONFIG_CPU == PNX0101) /* End wmcodecs */
631 /* nothing yet */
632#endif
633 }
634 }
635}
636
637bool pcm_is_playing(void) {
638 return pcm_playing;
639}
640
641bool pcm_is_paused(void) {
642 return pcm_paused;
643}
644
766/* 645/*
767 * This function goes directly into the DMA buffer to calculate the left and 646 * This function goes directly into the DMA buffer to calculate the left and
768 * right peak values. To avoid missing peaks it tries to look forward two full 647 * right peak values. To avoid missing peaks it tries to look forward two full
@@ -780,6 +659,10 @@ size_t pcm_get_bytes_waiting(void)
780 659
781void pcm_calculate_peaks(int *left, int *right) 660void pcm_calculate_peaks(int *left, int *right)
782{ 661{
662#if (CONFIG_CPU == PNX0101)
663 (void)left;
664 (void)right;
665#else
783 short *addr; 666 short *addr;
784 short *end; 667 short *end;
785 { 668 {
@@ -843,6 +726,5 @@ void pcm_calculate_peaks(int *left, int *right)
843 else 726 else
844 *right = peak_value; 727 *right = peak_value;
845 } 728 }
846}
847
848#endif 729#endif
730}