diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/export/config-clip.h | 4 | ||||
-rw-r--r-- | firmware/export/config-m200v4.h | 8 | ||||
-rw-r--r-- | firmware/target/arm/as3525/app.lds | 53 | ||||
-rw-r--r-- | firmware/target/arm/as3525/pcm-as3525.c | 102 |
4 files changed, 134 insertions, 33 deletions
diff --git a/firmware/export/config-clip.h b/firmware/export/config-clip.h index 0f4b93b4ae..40630bb75a 100644 --- a/firmware/export/config-clip.h +++ b/firmware/export/config-clip.h | |||
@@ -95,10 +95,10 @@ | |||
95 | #define HAVE_FAT16SUPPORT | 95 | #define HAVE_FAT16SUPPORT |
96 | 96 | ||
97 | /* The number of bytes reserved for loadable codecs */ | 97 | /* The number of bytes reserved for loadable codecs */ |
98 | #define CODEC_SIZE 0x80000 /* TODO : check if we can use IRAM */ | 98 | #define CODEC_SIZE 0x48000 /* in IRAM */ |
99 | 99 | ||
100 | /* The number of bytes reserved for loadable plugins */ | 100 | /* The number of bytes reserved for loadable plugins */ |
101 | #define PLUGIN_BUFFER_SIZE 0x80000 | 101 | #define PLUGIN_BUFFER_SIZE 0x60000 |
102 | 102 | ||
103 | #define AB_REPEAT_ENABLE 1 | 103 | #define AB_REPEAT_ENABLE 1 |
104 | 104 | ||
diff --git a/firmware/export/config-m200v4.h b/firmware/export/config-m200v4.h index b5c4f56b9f..ec264d0fe1 100644 --- a/firmware/export/config-m200v4.h +++ b/firmware/export/config-m200v4.h | |||
@@ -73,14 +73,10 @@ | |||
73 | #define HAVE_SW_POWEROFF | 73 | #define HAVE_SW_POWEROFF |
74 | 74 | ||
75 | /* The number of bytes reserved for loadable codecs */ | 75 | /* The number of bytes reserved for loadable codecs */ |
76 | #define CODEC_SIZE 0x100000 | 76 | #define CODEC_SIZE 0x48000 /* in IRAM */ |
77 | 77 | ||
78 | /* The number of bytes reserved for loadable plugins */ | 78 | /* The number of bytes reserved for loadable plugins */ |
79 | #if 0 /* The plugin buffer doesn't fit in the 2MB memory */ | 79 | #define PLUGIN_BUFFER_SIZE 0x60000 |
80 | #define PLUGIN_BUFFER_SIZE 0x80000 | ||
81 | #else | ||
82 | #define PLUGIN_BUFFER_SIZE 0 | ||
83 | #endif | ||
84 | 80 | ||
85 | #define AB_REPEAT_ENABLE 1 | 81 | #define AB_REPEAT_ENABLE 1 |
86 | 82 | ||
diff --git a/firmware/target/arm/as3525/app.lds b/firmware/target/arm/as3525/app.lds index bf8e68f048..21cdac528b 100644 --- a/firmware/target/arm/as3525/app.lds +++ b/firmware/target/arm/as3525/app.lds | |||
@@ -6,6 +6,11 @@ OUTPUT_FORMAT(elf32-littlearm) | |||
6 | OUTPUT_ARCH(arm) | 6 | OUTPUT_ARCH(arm) |
7 | STARTUP(target/arm/crt0.o) | 7 | STARTUP(target/arm/crt0.o) |
8 | 8 | ||
9 | #if MEMORYSIZE <= 2 | ||
10 | /* we put the codec buffer in IRAM */ | ||
11 | #define LOWMEM | ||
12 | #endif | ||
13 | |||
9 | #define PLUGINSIZE PLUGIN_BUFFER_SIZE | 14 | #define PLUGINSIZE PLUGIN_BUFFER_SIZE |
10 | #define CODECSIZE CODEC_SIZE | 15 | #define CODECSIZE CODEC_SIZE |
11 | 16 | ||
@@ -16,8 +21,15 @@ STARTUP(target/arm/crt0.o) | |||
16 | #endif | 21 | #endif |
17 | 22 | ||
18 | #include "cpu.h" | 23 | #include "cpu.h" |
24 | |||
19 | #define IRAMSIZE 0x50000 | 25 | #define IRAMSIZE 0x50000 |
26 | |||
27 | #ifdef LOWMEM | ||
28 | #define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGINSIZE | ||
29 | #define CODECORIG (IRAMORIG + IRAMSIZE - CODEC_SIZE) | ||
30 | #else | ||
20 | #define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGINSIZE - CODECSIZE | 31 | #define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGINSIZE - CODECSIZE |
32 | #endif | ||
21 | 33 | ||
22 | #define IRAMORIG 0x0 | 34 | #define IRAMORIG 0x0 |
23 | #define DRAMORIG 0x30000000 + STUBOFFSET | 35 | #define DRAMORIG 0x30000000 + STUBOFFSET |
@@ -26,11 +38,20 @@ STARTUP(target/arm/crt0.o) | |||
26 | #define ENDAUDIOADDR (DRAMORIG + DRAMSIZE) | 38 | #define ENDAUDIOADDR (DRAMORIG + DRAMSIZE) |
27 | 39 | ||
28 | /* Where the codec buffer ends, and the plugin buffer starts */ | 40 | /* Where the codec buffer ends, and the plugin buffer starts */ |
41 | #ifdef LOWMEM | ||
42 | #define ENDADDR (ENDAUDIOADDR) | ||
43 | #else | ||
29 | #define ENDADDR (ENDAUDIOADDR + CODECSIZE) | 44 | #define ENDADDR (ENDAUDIOADDR + CODECSIZE) |
45 | #endif | ||
30 | 46 | ||
31 | MEMORY | 47 | MEMORY |
32 | { | 48 | { |
49 | #ifdef LOWMEM | ||
50 | IRAM : ORIGIN = IRAMORIG, LENGTH = (IRAMSIZE - CODEC_SIZE) | ||
51 | CODEC_IRAM : ORIGIN = CODECORIG, LENGTH = CODEC_SIZE | ||
52 | #else | ||
33 | IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE | 53 | IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE |
54 | #endif | ||
34 | DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE | 55 | DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE |
35 | } | 56 | } |
36 | 57 | ||
@@ -69,8 +90,6 @@ SECTIONS | |||
69 | *(.eh_frame) | 90 | *(.eh_frame) |
70 | } | 91 | } |
71 | 92 | ||
72 | _initdata_end =.; | ||
73 | |||
74 | .vectors IRAMORIG: | 93 | .vectors IRAMORIG: |
75 | { | 94 | { |
76 | _vectors_start = .; | 95 | _vectors_start = .; |
@@ -79,16 +98,7 @@ SECTIONS | |||
79 | 98 | ||
80 | _vectorscopy = LOADADDR(.vectors); | 99 | _vectorscopy = LOADADDR(.vectors); |
81 | 100 | ||
82 | .ibss (NOLOAD) : | 101 | .iram : |
83 | { | ||
84 | _iedata = .; | ||
85 | *(.qharray) | ||
86 | *(.ibss) | ||
87 | . = ALIGN(0x4); | ||
88 | _iend = .; | ||
89 | } > IRAM | ||
90 | |||
91 | .iram _iend : | ||
92 | { | 102 | { |
93 | _iramstart = .; | 103 | _iramstart = .; |
94 | *(.icode) | 104 | *(.icode) |
@@ -98,6 +108,15 @@ SECTIONS | |||
98 | _iramend = .; | 108 | _iramend = .; |
99 | } > IRAM AT> DRAM | 109 | } > IRAM AT> DRAM |
100 | 110 | ||
111 | .ibss (NOLOAD) : | ||
112 | { | ||
113 | _iedata = .; | ||
114 | *(.qharray) | ||
115 | *(.ibss) | ||
116 | . = ALIGN(0x4); | ||
117 | _iend = .; | ||
118 | } > IRAM | ||
119 | |||
101 | _iramcopy = LOADADDR(.iram); | 120 | _iramcopy = LOADADDR(.iram); |
102 | 121 | ||
103 | .stack (NOLOAD) : | 122 | .stack (NOLOAD) : |
@@ -130,15 +149,19 @@ SECTIONS | |||
130 | _audiobufend = .; | 149 | _audiobufend = .; |
131 | } > DRAM | 150 | } > DRAM |
132 | 151 | ||
133 | .codec ENDAUDIOADDR (NOLOAD) : | 152 | .codec CODECORIG (NOLOAD) : |
134 | { | 153 | { |
135 | codecbuf = .; | 154 | codecbuf = .; |
136 | _codecbuf = .; | 155 | _codecbuf = .; |
137 | } | 156 | #ifdef LOWMEM |
157 | } > CODEC_IRAM | ||
158 | #else | ||
159 | } > DRAM | ||
160 | #endif | ||
138 | 161 | ||
139 | .plugin ENDADDR (NOLOAD) : | 162 | .plugin ENDADDR (NOLOAD) : |
140 | { | 163 | { |
141 | _pluginbuf = .; | 164 | _pluginbuf = .; |
142 | pluginbuf = .; | 165 | pluginbuf = .; |
143 | } | 166 | } > DRAM |
144 | } | 167 | } |
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c index d91450c9cf..0386cc3336 100644 --- a/firmware/target/arm/as3525/pcm-as3525.c +++ b/firmware/target/arm/as3525/pcm-as3525.c | |||
@@ -21,58 +21,140 @@ | |||
21 | #include "system.h" | 21 | #include "system.h" |
22 | #include "audio.h" | 22 | #include "audio.h" |
23 | #include "string.h" | 23 | #include "string.h" |
24 | 24 | #include "as3525.h" | |
25 | /* TODO */ | 25 | #include "pl081.h" |
26 | 26 | #include "dma-target.h" | |
27 | #include "clock-target.h" | ||
28 | #include "panic.h" | ||
29 | #include "as3514.h" | ||
30 | #include "audiohw.h" | ||
31 | |||
32 | #define MAX_TRANSFER (4*((1<<11)-1)) /* maximum data we can transfer via DMA | ||
33 | * i.e. 32 bits at once (size of I2SO_DATA) | ||
34 | * and the number of 32bits words has to | ||
35 | * fit in 11 bits of DMA register */ | ||
36 | |||
37 | static unsigned char *dma_start_addr; | ||
38 | static size_t dma_size; /* in 4*32 bits */ | ||
39 | static void dma_callback(void); | ||
40 | static int locked = 0; | ||
41 | |||
42 | /* Mask the DMA interrupt */ | ||
27 | void pcm_play_lock(void) | 43 | void pcm_play_lock(void) |
28 | { | 44 | { |
45 | if(++locked == 1) | ||
46 | VIC_INT_EN_CLEAR |= INTERRUPT_DMAC; | ||
29 | } | 47 | } |
30 | 48 | ||
49 | /* Unmask the DMA interrupt if enabled */ | ||
31 | void pcm_play_unlock(void) | 50 | void pcm_play_unlock(void) |
32 | { | 51 | { |
52 | if(--locked == 0) | ||
53 | VIC_INT_ENABLE |= INTERRUPT_DMAC; | ||
33 | } | 54 | } |
34 | 55 | ||
35 | void pcm_play_dma_start(const void *addr, size_t size) | 56 | static void play_start_pcm(void) |
36 | { | 57 | { |
58 | const unsigned char* addr = dma_start_addr; | ||
59 | size_t size = dma_size; | ||
60 | if(size > MAX_TRANSFER) | ||
61 | size = MAX_TRANSFER; | ||
62 | |||
63 | if((unsigned int)dma_start_addr & 3) | ||
64 | panicf("unaligned pointer!"); | ||
65 | |||
66 | dma_size -= size; | ||
67 | dma_start_addr += size; | ||
68 | |||
69 | dma_enable_channel(1, (void*)addr, (void*)I2SOUT_DATA, DMA_PERI_I2SOUT, | ||
70 | DMAC_FLOWCTRL_DMAC_MEM_TO_PERI, true, false, size >> 2, DMA_S1, | ||
71 | dma_callback); | ||
37 | } | 72 | } |
38 | 73 | ||
39 | void pcm_play_dma_stop(void) | 74 | static void dma_callback(void) |
40 | { | 75 | { |
76 | if(!dma_size) | ||
77 | { | ||
78 | register pcm_more_callback_type get_more = pcm_callback_for_more; | ||
79 | if(get_more) | ||
80 | get_more(&dma_start_addr, &dma_size); | ||
81 | } | ||
82 | |||
83 | if(!dma_size) | ||
84 | pcm_play_dma_stop(); | ||
85 | else | ||
86 | play_start_pcm(); | ||
41 | } | 87 | } |
42 | 88 | ||
43 | void pcm_play_dma_pause(bool pause) | 89 | void pcm_play_dma_start(const void *addr, size_t size) |
44 | { | 90 | { |
91 | dma_size = size; | ||
92 | dma_start_addr = (unsigned char*)addr; | ||
93 | |||
94 | play_start_pcm(); | ||
45 | } | 95 | } |
46 | 96 | ||
47 | unsigned long physical_address(void *p) | 97 | void pcm_play_dma_stop(void) |
98 | { | ||
99 | dma_disable_channel(1); | ||
100 | dma_size = 0; | ||
101 | } | ||
102 | |||
103 | void pcm_play_dma_pause(bool pause) | ||
48 | { | 104 | { |
49 | return 0; | 105 | if(pause) |
106 | dma_disable_channel(1); | ||
107 | else | ||
108 | play_start_pcm(); | ||
50 | } | 109 | } |
51 | 110 | ||
52 | void pcm_play_dma_init(void) | 111 | void pcm_play_dma_init(void) |
53 | { | 112 | { |
113 | CGU_PERI |= CGU_I2SOUT_APB_CLOCK_ENABLE; | ||
114 | |||
115 | /* enable I2SO_MCLK, clock source PLLA, minimal frequency */ | ||
116 | CGU_AUDIO |= (1<<11) | (511<<2) | (1<<0); | ||
117 | |||
118 | I2SOUT_CONTROL |= (1<<6) ; /* enable dma */ | ||
119 | I2SOUT_CONTROL |= (1<<3) ; /* stereo */ | ||
120 | I2SOUT_CONTROL &= ~(1<<2); /* 16 bit samples */ | ||
121 | |||
122 | audiohw_preinit(); | ||
54 | } | 123 | } |
55 | 124 | ||
56 | void pcm_postinit(void) | 125 | void pcm_postinit(void) |
57 | { | 126 | { |
127 | audiohw_postinit(); | ||
128 | pcm_apply_settings(); | ||
58 | } | 129 | } |
59 | 130 | ||
60 | void pcm_set_frequency(unsigned int frequency) | 131 | void pcm_set_frequency(unsigned int frequency) |
61 | { | 132 | { |
133 | const int divider = (((AS3525_PLLA_FREQ/128) + (frequency/2)) / frequency) - 1; | ||
134 | if(divider < 0 || divider > 511) | ||
135 | panicf("unsupported frequency %d", frequency); | ||
136 | |||
137 | CGU_AUDIO &= ~(((511 ^ divider) << 2) /* I2SOUT */ | ||
138 | /*| ((511 ^ divider) << 14) */ /* I2SIN */ | ||
139 | ); | ||
140 | |||
141 | pcm_curr_sampr = frequency; | ||
62 | } | 142 | } |
63 | 143 | ||
64 | void pcm_apply_settings(void) | 144 | void pcm_apply_settings(void) |
65 | { | 145 | { |
146 | pcm_set_frequency(HW_SAMPR_DEFAULT); | ||
66 | } | 147 | } |
67 | 148 | ||
68 | size_t pcm_get_bytes_waiting(void) | 149 | size_t pcm_get_bytes_waiting(void) |
69 | { | 150 | { |
70 | return 0; | 151 | return dma_size; |
71 | } | 152 | } |
72 | 153 | ||
73 | const void * pcm_play_dma_get_peak_buffer(int *count) | 154 | const void * pcm_play_dma_get_peak_buffer(int *count) |
74 | { | 155 | { |
75 | return NULL; | 156 | *count = dma_size >> 2; |
157 | return (const void*)dma_start_addr; | ||
76 | } | 158 | } |
77 | 159 | ||
78 | 160 | ||