diff options
author | Tomasz Malesinski <tomal@rockbox.org> | 2006-08-12 21:03:23 +0000 |
---|---|---|
committer | Tomasz Malesinski <tomal@rockbox.org> | 2006-08-12 21:03:23 +0000 |
commit | 4e5f4ee5e03072d8f470610f8751efcf17ad4f6a (patch) | |
tree | 80c7b76f34301cebf1f3394b542de63f638e5b77 /firmware/pcm_playback.c | |
parent | 062384109190f4f05ef88ab17ec51cd8d49ed5c4 (diff) | |
download | rockbox-4e5f4ee5e03072d8f470610f8751efcf17ad4f6a.tar.gz rockbox-4e5f4ee5e03072d8f470610f8751efcf17ad4f6a.zip |
Iriver iFP7xx sound support.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10552 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/pcm_playback.c')
-rw-r--r-- | firmware/pcm_playback.c | 173 |
1 files changed, 169 insertions, 4 deletions
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c index 473c49f30d..16e8f5e3af 100644 --- a/firmware/pcm_playback.c +++ b/firmware/pcm_playback.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include "tlv320.h" | 33 | #include "tlv320.h" |
34 | #elif defined(HAVE_WM8731) || defined(HAVE_WM8721) | 34 | #elif defined(HAVE_WM8731) || defined(HAVE_WM8721) |
35 | #include "wm8731l.h" | 35 | #include "wm8731l.h" |
36 | #elif CONFIG_CPU == PNX0101 | ||
37 | #include "pnx0101.h" | ||
36 | #endif | 38 | #endif |
37 | #include "system.h" | 39 | #include "system.h" |
38 | #include "logf.h" | 40 | #include "logf.h" |
@@ -55,9 +57,9 @@ static bool pcm_paused; | |||
55 | /* the registered callback function to ask for more mp3 data */ | 57 | /* the registered callback function to ask for more mp3 data */ |
56 | static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL; | 58 | static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL; |
57 | 59 | ||
58 | #if (CONFIG_CPU == PNX0101 || CONFIG_CPU == S3C2440) | 60 | #if (CONFIG_CPU == S3C2440) |
59 | 61 | ||
60 | /* TODO: Implement for iFP7xx | 62 | /* TODO: Implement for Gigabeat |
61 | For now, just implement some dummy functions. | 63 | For now, just implement some dummy functions. |
62 | */ | 64 | */ |
63 | 65 | ||
@@ -526,6 +528,168 @@ void pcm_init(void) | |||
526 | dma_stop(); | 528 | dma_stop(); |
527 | } | 529 | } |
528 | 530 | ||
531 | #elif (CONFIG_CPU == PNX0101) | ||
532 | |||
533 | #define DMA_BUF_SAMPLES 0x100 | ||
534 | |||
535 | short __attribute__((section(".dmabuf"))) dma_buf_left[DMA_BUF_SAMPLES]; | ||
536 | short __attribute__((section(".dmabuf"))) dma_buf_right[DMA_BUF_SAMPLES]; | ||
537 | |||
538 | static int pcm_freq = 44100; /* 44.1 is default */ | ||
539 | |||
540 | unsigned short* p IBSS_ATTR; | ||
541 | size_t p_size IBSS_ATTR; | ||
542 | |||
543 | static void dma_start(const void *addr, size_t size) | ||
544 | { | ||
545 | p = (unsigned short*)addr; | ||
546 | p_size = size; | ||
547 | |||
548 | pcm_playing = true; | ||
549 | } | ||
550 | |||
551 | static void dma_stop(void) | ||
552 | { | ||
553 | pcm_playing = false; | ||
554 | } | ||
555 | |||
556 | static inline void fill_dma_buf(int offset) | ||
557 | { | ||
558 | short *l, *r, *lend; | ||
559 | |||
560 | l = dma_buf_left + offset; | ||
561 | lend = l + DMA_BUF_SAMPLES / 2; | ||
562 | r = dma_buf_right + offset; | ||
563 | |||
564 | if (pcm_playing && !pcm_paused) | ||
565 | { | ||
566 | do | ||
567 | { | ||
568 | int count; | ||
569 | unsigned short *tmp_p; | ||
570 | count = MIN(p_size / 4, (size_t)(lend - l)); | ||
571 | tmp_p = p; | ||
572 | p_size -= count * 4; | ||
573 | |||
574 | if ((int)l & 3) | ||
575 | { | ||
576 | *l++ = *tmp_p++; | ||
577 | *r++ = *tmp_p++; | ||
578 | count--; | ||
579 | } | ||
580 | while (count >= 4) | ||
581 | { | ||
582 | asm("ldmia %0!, {r0, r1, r2, r3}\n\t" | ||
583 | "and r4, r0, %3\n\t" | ||
584 | "orr r4, r4, r1, lsl #16\n\t" | ||
585 | "and r5, r2, %3\n\t" | ||
586 | "orr r5, r5, r3, lsl #16\n\t" | ||
587 | "stmia %1!, {r4, r5}\n\t" | ||
588 | "bic r4, r1, %3\n\t" | ||
589 | "orr r4, r4, r0, lsr #16\n\t" | ||
590 | "bic r5, r3, %3\n\t" | ||
591 | "orr r5, r5, r2, lsr #16\n\t" | ||
592 | "stmia %2!, {r4, r5}" | ||
593 | : "+r" (tmp_p), "+r" (l), "+r" (r) | ||
594 | : "r" (0xffff) | ||
595 | : "r0", "r1", "r2", "r3", "r4", "r5", "memory"); | ||
596 | count -= 4; | ||
597 | } | ||
598 | while (count > 0) | ||
599 | { | ||
600 | *l++ = *tmp_p++; | ||
601 | *r++ = *tmp_p++; | ||
602 | count--; | ||
603 | } | ||
604 | p = tmp_p; | ||
605 | if (l >= lend) | ||
606 | return; | ||
607 | else if (callback_for_more) | ||
608 | callback_for_more((unsigned char**)&p, | ||
609 | &p_size); | ||
610 | } | ||
611 | while (p_size); | ||
612 | pcm_playing = false; | ||
613 | } | ||
614 | |||
615 | if (l < lend) | ||
616 | { | ||
617 | memset(l, 0, sizeof(short) * (lend - l)); | ||
618 | memset(r, 0, sizeof(short) * (lend - l)); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | static void audio_irq(void) | ||
623 | { | ||
624 | unsigned long st = DMAINTSTAT & ~DMAINTEN; | ||
625 | int i; | ||
626 | for (i = 0; i < 2; i++) | ||
627 | if (st & (1 << i)) | ||
628 | { | ||
629 | fill_dma_buf((i == 1) ? 0 : DMA_BUF_SAMPLES / 2); | ||
630 | DMAINTSTAT = 1 << i; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | unsigned long physical_address(void *p) | ||
635 | { | ||
636 | unsigned long adr = (unsigned long)p; | ||
637 | return (MMUBLOCK((adr >> 21) & 0xf) << 21) | (adr & ((1 << 21) - 1)); | ||
638 | } | ||
639 | |||
640 | void pcm_init(void) | ||
641 | { | ||
642 | int i; | ||
643 | callback_for_more = NULL; | ||
644 | pcm_playing = false; | ||
645 | pcm_paused = false; | ||
646 | |||
647 | memset(dma_buf_left, 0, sizeof(dma_buf_left)); | ||
648 | memset(dma_buf_right, 0, sizeof(dma_buf_right)); | ||
649 | |||
650 | for (i = 0; i < 8; i++) | ||
651 | { | ||
652 | DMASRC(i) = 0; | ||
653 | DMADEST(i) = 0; | ||
654 | DMALEN(i) = 0x1ffff; | ||
655 | DMAR0C(i) = 0; | ||
656 | DMAR10(i) = 0; | ||
657 | DMAR1C(i) = 0; | ||
658 | } | ||
659 | |||
660 | DMAINTSTAT = 0xc000ffff; | ||
661 | DMAINTEN = 0xc000ffff; | ||
662 | |||
663 | DMASRC(0) = physical_address(dma_buf_left); | ||
664 | DMADEST(0) = 0x80200280; | ||
665 | DMALEN(0) = 0xff; | ||
666 | DMAR1C(0) = 0; | ||
667 | DMAR0C(0) = 0x40408; | ||
668 | |||
669 | DMASRC(1) = physical_address(dma_buf_right); | ||
670 | DMADEST(1) = 0x80200284; | ||
671 | DMALEN(1) = 0xff; | ||
672 | DMAR1C(1) = 0; | ||
673 | DMAR0C(1) = 0x40409; | ||
674 | |||
675 | irq_set_int_handler(0x1b, audio_irq); | ||
676 | irq_enable_int(0x1b); | ||
677 | |||
678 | DMAINTSTAT = 1; | ||
679 | DMAINTSTAT = 2; | ||
680 | DMAINTEN &= ~3; | ||
681 | DMAR10(0) |= 1; | ||
682 | DMAR10(1) |= 1; | ||
683 | } | ||
684 | |||
685 | void pcm_set_frequency(unsigned int frequency) | ||
686 | { | ||
687 | pcm_freq=frequency; | ||
688 | } | ||
689 | size_t pcm_get_bytes_waiting(void) | ||
690 | { | ||
691 | return p_size; | ||
692 | } | ||
529 | #endif | 693 | #endif |
530 | 694 | ||
531 | void pcm_play_stop(void) | 695 | void pcm_play_stop(void) |
@@ -699,7 +863,7 @@ bool pcm_is_paused(void) { | |||
699 | 863 | ||
700 | void pcm_calculate_peaks(int *left, int *right) | 864 | void pcm_calculate_peaks(int *left, int *right) |
701 | { | 865 | { |
702 | #if (CONFIG_CPU == PNX0101 || CONFIG_CPU == S3C2440) | 866 | #if (CONFIG_CPU == S3C2440) |
703 | (void)left; | 867 | (void)left; |
704 | (void)right; | 868 | (void)right; |
705 | #else | 869 | #else |
@@ -710,7 +874,8 @@ void pcm_calculate_peaks(int *left, int *right) | |||
710 | size_t samples = (BCR0 & 0xffffff) / 4; | 874 | size_t samples = (BCR0 & 0xffffff) / 4; |
711 | addr = (short *) (SAR0 & ~3); | 875 | addr = (short *) (SAR0 & ~3); |
712 | #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \ | 876 | #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \ |
713 | || defined(HAVE_WM8731) || defined(HAVE_WM8721) | 877 | || defined(HAVE_WM8731) || defined(HAVE_WM8721) \ |
878 | || (CONFIG_CPU == PNX0101) | ||
714 | size_t samples = p_size / 4; | 879 | size_t samples = p_size / 4; |
715 | addr = p; | 880 | addr = p; |
716 | #endif | 881 | #endif |