diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/app.lds | 8 | ||||
-rw-r--r-- | firmware/export/pnx0101.h | 14 | ||||
-rw-r--r-- | firmware/pcm_playback.c | 173 | ||||
-rw-r--r-- | firmware/sound.c | 8 |
4 files changed, 197 insertions, 6 deletions
diff --git a/firmware/app.lds b/firmware/app.lds index 1caea68fa0..7a8ec11c3e 100644 --- a/firmware/app.lds +++ b/firmware/app.lds | |||
@@ -154,6 +154,9 @@ MEMORY | |||
154 | { | 154 | { |
155 | DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE | 155 | DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE |
156 | IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE | 156 | IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE |
157 | #if CONFIG_CPU==PNX0101 | ||
158 | IRAM0 : ORIGIN = 0x0, LENGTH = IRAMSIZE | ||
159 | #endif | ||
157 | } | 160 | } |
158 | 161 | ||
159 | SECTIONS | 162 | SECTIONS |
@@ -221,7 +224,12 @@ SECTIONS | |||
221 | _vectorsstart = .; | 224 | _vectorsstart = .; |
222 | *(.vectors); | 225 | *(.vectors); |
223 | _vectorsend = .; | 226 | _vectorsend = .; |
227 | #if CONFIG_CPU==PNX0101 | ||
228 | *(.dmabuf) | ||
229 | } >IRAM0 AT> DRAM | ||
230 | #else | ||
224 | } AT> DRAM | 231 | } AT> DRAM |
232 | #endif | ||
225 | 233 | ||
226 | _vectorscopy = LOADADDR(.vectors); | 234 | _vectorscopy = LOADADDR(.vectors); |
227 | #endif | 235 | #endif |
diff --git a/firmware/export/pnx0101.h b/firmware/export/pnx0101.h index 4408c0aa5b..4867c6b25d 100644 --- a/firmware/export/pnx0101.h +++ b/firmware/export/pnx0101.h | |||
@@ -64,4 +64,18 @@ | |||
64 | #define ADCR24 (*(volatile unsigned long *)0x80002424) | 64 | #define ADCR24 (*(volatile unsigned long *)0x80002424) |
65 | #define ADCR28 (*(volatile unsigned long *)0x80002428) | 65 | #define ADCR28 (*(volatile unsigned long *)0x80002428) |
66 | 66 | ||
67 | #define DMAINTSTAT (*(volatile unsigned long *)0x80104c04) | ||
68 | #define DMAINTEN (*(volatile unsigned long *)0x80104c08) | ||
69 | |||
70 | #define DMASRC(n) (*(volatile unsigned long *)(0x80104800 + (n) * 0x20)) | ||
71 | #define DMADEST(n) (*(volatile unsigned long *)(0x80104804 + (n) * 0x20)) | ||
72 | #define DMALEN(n) (*(volatile unsigned long *)(0x80104808 + (n) * 0x20)) | ||
73 | #define DMAR0C(n) (*(volatile unsigned long *)(0x8010480c + (n) * 0x20)) | ||
74 | #define DMAR10(n) (*(volatile unsigned long *)(0x80104810 + (n) * 0x20)) | ||
75 | #define DMAR1C(n) (*(volatile unsigned long *)(0x8010481c + (n) * 0x20)) | ||
76 | |||
77 | #define MMUBLOCK(n) (*(volatile unsigned long *)(0x80105018 + (n) * 4)) | ||
78 | |||
79 | #define CODECVOL (*(volatile unsigned long *)0x80200398) | ||
80 | |||
67 | #endif | 81 | #endif |
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 |
diff --git a/firmware/sound.c b/firmware/sound.c index 5e4cd5db48..a3a8eed806 100644 --- a/firmware/sound.c +++ b/firmware/sound.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "wm8731l.h" | 34 | #include "wm8731l.h" |
35 | #elif defined(HAVE_TLV320) | 35 | #elif defined(HAVE_TLV320) |
36 | #include "tlv320.h" | 36 | #include "tlv320.h" |
37 | #elif CONFIG_CPU == PNX0101 | ||
38 | #include "pnx0101.h" | ||
37 | #endif | 39 | #endif |
38 | #include "dac.h" | 40 | #include "dac.h" |
39 | #include "system.h" | 41 | #include "system.h" |
@@ -85,6 +87,8 @@ static const struct sound_settings_info sound_settings_table[] = { | |||
85 | [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25, sound_set_volume}, | 87 | [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25, sound_set_volume}, |
86 | [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass}, | 88 | [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass}, |
87 | [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble}, | 89 | [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble}, |
90 | #elif (CONFIG_CPU == PNX0101) | ||
91 | [SOUND_VOLUME] = {"dB", 0, 1, -48, 15, 0, sound_set_volume}, | ||
88 | #else /* MAS3507D */ | 92 | #else /* MAS3507D */ |
89 | [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18, sound_set_volume}, | 93 | [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18, sound_set_volume}, |
90 | [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7, sound_set_bass}, | 94 | [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7, sound_set_bass}, |
@@ -599,8 +603,8 @@ void sound_set_volume(int value) | |||
599 | current_volume = value * 10; /* tenth of dB */ | 603 | current_volume = value * 10; /* tenth of dB */ |
600 | set_prescaled_volume(); | 604 | set_prescaled_volume(); |
601 | #elif CONFIG_CPU == PNX0101 | 605 | #elif CONFIG_CPU == PNX0101 |
602 | /* TODO: implement for iFP */ | 606 | int tmp = (60 - value * 4) & 0xff; |
603 | (void)value; | 607 | CODECVOL = tmp | (tmp << 8); |
604 | #endif | 608 | #endif |
605 | } | 609 | } |
606 | 610 | ||