diff options
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | 64 |
1 files changed, 56 insertions, 8 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c index 32a14744df..a4ecd0b786 100644 --- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | |||
@@ -65,16 +65,35 @@ void pcm_dma_apply_settings(void) | |||
65 | static void* playback_address; | 65 | static void* playback_address; |
66 | static inline void set_dma(const void *addr, size_t size) | 66 | static inline void set_dma(const void *addr, size_t size) |
67 | { | 67 | { |
68 | logf("%x %x %d %d %x", (unsigned int)addr, size, (REG_AIC_SR>>24) & 0x20, (REG_AIC_SR>>8) & 0x20, REG_AIC_SR & 0xF); | 68 | int burst_size; |
69 | logf("%x %d %x", (unsigned int)addr, size, REG_AIC_SR); | ||
70 | |||
71 | if(size % 16) | ||
72 | { | ||
73 | if(size % 4) | ||
74 | { | ||
75 | size /= 2; | ||
76 | burst_size = DMAC_DCMD_DS_16BIT; | ||
77 | } | ||
78 | else | ||
79 | { | ||
80 | size /= 4; | ||
81 | burst_size = DMAC_DCMD_DS_32BIT; | ||
82 | } | ||
83 | } | ||
84 | else | ||
85 | { | ||
86 | size /= 16; | ||
87 | burst_size = DMAC_DCMD_DS_16BYTE; | ||
88 | } | ||
69 | 89 | ||
70 | __dcache_writeback_all(); | 90 | __dcache_writeback_all(); |
71 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = DMAC_DCCSR_NDES; | 91 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = DMAC_DCCSR_NDES; |
72 | REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)addr); | 92 | REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)addr); |
73 | REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)AIC_DR); | 93 | REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)AIC_DR); |
74 | REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) = size / 16; | 94 | REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) = size; |
75 | REG_DMAC_DRSR(DMA_AIC_TX_CHANNEL) = DMAC_DRSR_RS_AICOUT; | 95 | REG_DMAC_DRSR(DMA_AIC_TX_CHANNEL) = DMAC_DRSR_RS_AICOUT; |
76 | REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) = (DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DWDH_16 | DMAC_DCMD_TIE | | 96 | REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) = (DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | burst_size | DMAC_DCMD_DWDH_16 | DMAC_DCMD_TIE); |
77 | DMAC_DCMD_RDIL_IGN); | ||
78 | 97 | ||
79 | playback_address = (void*)addr; | 98 | playback_address = (void*)addr; |
80 | } | 99 | } |
@@ -181,10 +200,37 @@ void pcm_play_dma_pause(bool pause) | |||
181 | restore_irq(flags); | 200 | restore_irq(flags); |
182 | } | 201 | } |
183 | 202 | ||
203 | static int get_dma_count(void) | ||
204 | { | ||
205 | int count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL); | ||
206 | switch(REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) & DMAC_DCMD_DS_MASK) | ||
207 | { | ||
208 | case DMAC_DCMD_DS_16BIT: | ||
209 | count *= 2; | ||
210 | break; | ||
211 | case DMAC_DCMD_DS_32BIT: | ||
212 | count *= 4; | ||
213 | break; | ||
214 | case DMAC_DCMD_DS_16BYTE: | ||
215 | count *= 16; | ||
216 | break; | ||
217 | } | ||
218 | |||
219 | return count; | ||
220 | } | ||
221 | |||
184 | size_t pcm_get_bytes_waiting(void) | 222 | size_t pcm_get_bytes_waiting(void) |
185 | { | 223 | { |
186 | return REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_EN ? | 224 | int bytes, flags = disable_irq_save(); |
187 | (REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) * 16) & ~3 : 0; | 225 | |
226 | if(REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_EN) | ||
227 | bytes = get_dma_count() & ~3; | ||
228 | else | ||
229 | bytes = 0; | ||
230 | |||
231 | restore_irq(flags); | ||
232 | |||
233 | return bytes; | ||
188 | } | 234 | } |
189 | 235 | ||
190 | const void * pcm_play_dma_get_peak_buffer(int *count) | 236 | const void * pcm_play_dma_get_peak_buffer(int *count) |
@@ -194,8 +240,9 @@ const void * pcm_play_dma_get_peak_buffer(int *count) | |||
194 | const void* addr; | 240 | const void* addr; |
195 | if(REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_EN) | 241 | if(REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_EN) |
196 | { | 242 | { |
197 | *count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)*16 >> 2; | 243 | int bytes = get_dma_count(); |
198 | addr = (const void*)(playback_address + ((REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)*16 + 2) & ~3)); | 244 | *count = bytes >> 2; |
245 | addr = (const void*)((int)(playback_address + bytes + 2) & ~3); | ||
199 | } | 246 | } |
200 | else | 247 | else |
201 | { | 248 | { |
@@ -210,6 +257,7 @@ const void * pcm_play_dma_get_peak_buffer(int *count) | |||
210 | 257 | ||
211 | void audiohw_close(void) | 258 | void audiohw_close(void) |
212 | { | 259 | { |
260 | /* TODO: prevent pop */ | ||
213 | } | 261 | } |
214 | 262 | ||
215 | #ifdef HAVE_RECORDING | 263 | #ifdef HAVE_RECORDING |