diff options
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | 121 |
1 files changed, 64 insertions, 57 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c index 05c89be158..1fbc94065b 100644 --- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | |||
@@ -32,8 +32,6 @@ | |||
32 | ** Playback DMA transfer | 32 | ** Playback DMA transfer |
33 | **/ | 33 | **/ |
34 | 34 | ||
35 | static bool playback_started = false; | ||
36 | static void* playback_address; | ||
37 | void pcm_postinit(void) | 35 | void pcm_postinit(void) |
38 | { | 36 | { |
39 | audiohw_postinit(); | 37 | audiohw_postinit(); |
@@ -64,21 +62,12 @@ void pcm_dma_apply_settings(void) | |||
64 | audiohw_set_frequency(pcm_sampr); | 62 | audiohw_set_frequency(pcm_sampr); |
65 | } | 63 | } |
66 | 64 | ||
67 | static void play_start_pcm(void) | 65 | static void* playback_address; |
68 | { | ||
69 | __aic_enable_transmit_dma(); | ||
70 | __aic_enable_replay(); | ||
71 | |||
72 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; | ||
73 | |||
74 | playback_started = true; | ||
75 | } | ||
76 | |||
77 | static inline void set_dma(const void *addr, size_t size) | 66 | static inline void set_dma(const void *addr, size_t size) |
78 | { | 67 | { |
79 | 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 | logf("%x %x %d %d %x", (unsigned int)addr, size, (REG_AIC_SR>>24) & 0x20, (REG_AIC_SR>>8) & 0x20, REG_AIC_SR & 0xF); |
80 | 69 | ||
81 | //__dcache_writeback_all(); | 70 | __dcache_writeback_all(); |
82 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = DMAC_DCCSR_NDES; | 71 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = DMAC_DCCSR_NDES; |
83 | REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)addr); | 72 | REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)addr); |
84 | REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)AIC_DR); | 73 | REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)AIC_DR); |
@@ -90,27 +79,6 @@ static inline void set_dma(const void *addr, size_t size) | |||
90 | playback_address = (void*)addr; | 79 | playback_address = (void*)addr; |
91 | } | 80 | } |
92 | 81 | ||
93 | static void play_stop_pcm(void) | ||
94 | { | ||
95 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) | DMAC_DCCSR_HLT) & ~DMAC_DCCSR_EN; | ||
96 | |||
97 | dma_disable(); | ||
98 | |||
99 | __aic_disable_transmit_dma(); | ||
100 | __aic_disable_replay(); | ||
101 | |||
102 | playback_started = false; | ||
103 | } | ||
104 | |||
105 | void pcm_play_dma_start(const void *addr, size_t size) | ||
106 | { | ||
107 | dma_enable(); | ||
108 | |||
109 | set_dma(addr, size); | ||
110 | play_start_pcm(); | ||
111 | } | ||
112 | |||
113 | |||
114 | static inline void play_dma_callback(void) | 82 | static inline void play_dma_callback(void) |
115 | { | 83 | { |
116 | unsigned char *start; | 84 | unsigned char *start; |
@@ -130,6 +98,7 @@ static inline void play_dma_callback(void) | |||
130 | } | 98 | } |
131 | } | 99 | } |
132 | 100 | ||
101 | void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) __attribute__ ((section(".icode"))); | ||
133 | void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) | 102 | void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) |
134 | { | 103 | { |
135 | if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_AR) | 104 | if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_AR) |
@@ -151,52 +120,90 @@ void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) | |||
151 | } | 120 | } |
152 | } | 121 | } |
153 | 122 | ||
154 | size_t pcm_get_bytes_waiting(void) | 123 | void pcm_play_dma_start(const void *addr, size_t size) |
155 | { | 124 | { |
156 | if(playback_started) | 125 | dma_enable(); |
157 | return (REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) * 16) & ~3; | ||
158 | else | ||
159 | return 0; | ||
160 | } | ||
161 | 126 | ||
162 | const void * pcm_play_dma_get_peak_buffer(int *count) | 127 | set_dma(addr, size); |
163 | { | 128 | |
164 | /* TODO */ | 129 | __aic_enable_transmit_dma(); |
165 | if(playback_started) | 130 | __aic_enable_replay(); |
166 | { | 131 | |
167 | *count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) >> 2; | 132 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; |
168 | return (void*)(playback_address + ((REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)*16 + 2) & ~3)); | ||
169 | } | ||
170 | else | ||
171 | { | ||
172 | *count = 0; | ||
173 | return NULL; | ||
174 | } | ||
175 | } | 133 | } |
176 | 134 | ||
177 | void pcm_play_dma_stop(void) | 135 | void pcm_play_dma_stop(void) |
178 | { | 136 | { |
179 | play_stop_pcm(); | 137 | int flags = disable_irq_save(); |
180 | 138 | ||
181 | /* TODO */ | 139 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) | DMAC_DCCSR_HLT) & ~DMAC_DCCSR_EN; |
140 | |||
141 | dma_disable(); | ||
142 | |||
143 | __aic_disable_transmit_dma(); | ||
144 | __aic_disable_replay(); | ||
145 | |||
146 | restore_irq(flags); | ||
182 | } | 147 | } |
183 | 148 | ||
149 | static unsigned int play_lock = 0; | ||
184 | void pcm_play_lock(void) | 150 | void pcm_play_lock(void) |
185 | { | 151 | { |
186 | /* TODO */ | 152 | int flags = disable_irq_save(); |
153 | |||
154 | if (++play_lock == 1) | ||
155 | __dmac_channel_disable_irq(DMA_AIC_TX_CHANNEL); | ||
156 | |||
157 | restore_irq(flags); | ||
187 | } | 158 | } |
188 | 159 | ||
189 | void pcm_play_unlock(void) | 160 | void pcm_play_unlock(void) |
190 | { | 161 | { |
191 | /* TODO */ | 162 | int flags = disable_irq_save(); |
163 | |||
164 | if (--play_lock == 0) | ||
165 | __dmac_channel_enable_irq(DMA_AIC_TX_CHANNEL); | ||
166 | |||
167 | restore_irq(flags); | ||
192 | } | 168 | } |
193 | 169 | ||
194 | void pcm_play_dma_pause(bool pause) | 170 | void pcm_play_dma_pause(bool pause) |
195 | { | 171 | { |
172 | int flags = disable_irq_save(); | ||
173 | |||
196 | if(pause) | 174 | if(pause) |
197 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~DMAC_DCCSR_EN; | 175 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~DMAC_DCCSR_EN; |
198 | else | 176 | else |
199 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; | 177 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; |
178 | |||
179 | restore_irq(flags); | ||
180 | } | ||
181 | |||
182 | size_t pcm_get_bytes_waiting(void) | ||
183 | { | ||
184 | return REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_EN ? | ||
185 | (REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) * 16) & ~3 : 0; | ||
186 | } | ||
187 | |||
188 | const void * pcm_play_dma_get_peak_buffer(int *count) | ||
189 | { | ||
190 | int flags = disable_irq_save(); | ||
191 | |||
192 | const void* addr; | ||
193 | if(REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_EN) | ||
194 | { | ||
195 | *count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)*16 >> 2; | ||
196 | addr = (const void*)(playback_address + ((REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)*16 + 2) & ~3)); | ||
197 | } | ||
198 | else | ||
199 | { | ||
200 | *count = 0; | ||
201 | addr = NULL; | ||
202 | } | ||
203 | |||
204 | restore_irq(flags); | ||
205 | |||
206 | return addr; | ||
200 | } | 207 | } |
201 | 208 | ||
202 | void audiohw_close(void) | 209 | void audiohw_close(void) |