diff options
Diffstat (limited to 'firmware/pcm_playback.c')
-rw-r--r-- | firmware/pcm_playback.c | 418 |
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 | ||
52 | static bool pcm_playing; | ||
53 | static bool pcm_paused; | ||
54 | |||
55 | /* the registered callback function to ask for more mp3 data */ | ||
56 | static 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 | ||
60 | static bool pcm_playing; | ||
61 | static bool pcm_paused; | ||
62 | static int pcm_freq = 0x6; /* 44.1 is default */ | 66 | static 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 */ | ||
133 | static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL; | ||
134 | |||
135 | void 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 | |||
157 | size_t pcm_get_bytes_waiting(void) | 136 | size_t pcm_get_bytes_waiting(void) |
158 | { | 137 | { |
159 | return (BCR0 & 0xffffff); | 138 | return (BCR0 & 0xffffff); |
160 | } | 139 | } |
161 | 140 | ||
162 | void pcm_mute(bool mute) | ||
163 | { | ||
164 | #ifdef HAVE_UDA1380 | ||
165 | uda1380_mute(mute); | ||
166 | #endif | ||
167 | if (mute) | ||
168 | sleep(HZ/16); | ||
169 | } | ||
170 | |||
171 | void pcm_play_stop(void) | ||
172 | { | ||
173 | if (pcm_playing) { | ||
174 | dma_stop(); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | void 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 | |||
230 | bool pcm_is_paused(void) | ||
231 | { | ||
232 | return pcm_paused; | ||
233 | } | ||
234 | |||
235 | bool 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 */ |
241 | void DMA0(void) __attribute__ ((interrupt_handler, section(".icode"))); | 142 | void DMA0(void) __attribute__ ((interrupt_handler, section(".icode"))); |
242 | void DMA0(void) | 143 | void 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 | ||
346 | static bool pcm_playing; | 247 | static int pcm_freq = 44100; /* 44.1 is default */ |
347 | static bool pcm_paused; | ||
348 | static 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 */ | ||
432 | static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL; | ||
433 | |||
434 | void 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 | |||
455 | size_t pcm_get_bytes_waiting(void) | 330 | size_t pcm_get_bytes_waiting(void) |
456 | { | 331 | { |
457 | return p_size; | 332 | return p_size; |
458 | } | 333 | } |
459 | 334 | ||
460 | void pcm_mute(bool mute) | ||
461 | { | ||
462 | wmcodec_mute(mute); | ||
463 | if (mute) | ||
464 | sleep(HZ/16); | ||
465 | } | ||
466 | |||
467 | void pcm_play_stop(void) | ||
468 | { | ||
469 | if (pcm_playing) { | ||
470 | dma_stop(); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | void 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 | |||
560 | bool pcm_is_paused(void) | ||
561 | { | ||
562 | return pcm_paused; | ||
563 | } | ||
564 | |||
565 | bool 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 | ||
720 | void 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 | |||
728 | void pcm_play_stop(void) | 485 | void pcm_play_stop(void) |
729 | { | 486 | { |
730 | } | 487 | } |
731 | 488 | ||
732 | void pcm_mute(bool mute) | 489 | size_t pcm_get_bytes_waiting(void) |
733 | { | 490 | { |
734 | (void)mute; | 491 | return 0; |
735 | } | 492 | } |
736 | 493 | ||
737 | void pcm_play_pause(bool play) | 494 | #endif |
738 | { | ||
739 | (void)play; | ||
740 | } | ||
741 | 495 | ||
742 | bool pcm_is_paused(void) | 496 | void 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 | ||
747 | bool pcm_is_playing(void) | 518 | void 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 | ||
752 | void pcm_calculate_peaks(int *left, int *right) | 531 | void pcm_play_stop(void) |
753 | { | 532 | { |
754 | (void)left; | 533 | if (pcm_playing) { |
755 | (void)right; | 534 | dma_stop(); |
535 | } | ||
756 | } | 536 | } |
757 | 537 | ||
758 | size_t pcm_get_bytes_waiting(void) | 538 | void 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 | |||
637 | bool pcm_is_playing(void) { | ||
638 | return pcm_playing; | ||
639 | } | ||
640 | |||
641 | bool 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 | ||
781 | void pcm_calculate_peaks(int *left, int *right) | 660 | void 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 | } | ||