summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c64
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)
65static void* playback_address; 65static void* playback_address;
66static inline void set_dma(const void *addr, size_t size) 66static 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
203static 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
184size_t pcm_get_bytes_waiting(void) 222size_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
190const void * pcm_play_dma_get_peak_buffer(int *count) 236const 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
211void audiohw_close(void) 258void audiohw_close(void)
212{ 259{
260 /* TODO: prevent pop */
213} 261}
214 262
215#ifdef HAVE_RECORDING 263#ifdef HAVE_RECORDING