diff options
Diffstat (limited to 'firmware/target/coldfire/pcm-coldfire.c')
-rw-r--r-- | firmware/target/coldfire/pcm-coldfire.c | 162 |
1 files changed, 94 insertions, 68 deletions
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c index 8738316aa9..2addcb9da8 100644 --- a/firmware/target/coldfire/pcm-coldfire.c +++ b/firmware/target/coldfire/pcm-coldfire.c | |||
@@ -41,23 +41,23 @@ enum | |||
41 | }; | 41 | }; |
42 | static int peaks[4]; /* p-l, p-r, r-l, r-r */ | 42 | static int peaks[4]; /* p-l, p-r, r-l, r-r */ |
43 | 43 | ||
44 | #define IIS_DEFPARM(output) ( (freq_ent[FPARM_CLOCKSEL] << 12) | \ | 44 | #define IIS_PLAY_DEFPARM ( (freq_ent[FPARM_CLOCKSEL] << 12) | \ |
45 | (output) | \ | 45 | (IIS_PLAY & (7 << 8)) | \ |
46 | (4 << 2) ) /* 64 bit clocks / word clock */ | 46 | (4 << 2) ) /* 64 bit clocks / word clock */ |
47 | #define IIS_RESET 0x800 | 47 | #define IIS_FIFO_RESET (1 << 11) |
48 | #define PDIR2_FIFO_RESET (1 << 9) | ||
48 | 49 | ||
49 | #if defined(IAUDIO_X5) || defined(IAUDIO_M5) | 50 | #if defined(IAUDIO_X5) || defined(IAUDIO_M5) |
50 | #define SET_IIS_CONFIG(x) IIS1CONFIG = (x); | 51 | #define SET_IIS_PLAY(x) IIS1CONFIG = (x) |
51 | #define IIS_CONFIG IIS1CONFIG | 52 | #define IIS_PLAY IIS1CONFIG |
52 | #define PLLCR_SET_AUDIO_BITS_DEFPARM \ | ||
53 | ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22)) | ||
54 | #else | 53 | #else |
55 | #define SET_IIS_CONFIG(x) IIS2CONFIG = (x); | 54 | #define SET_IIS_PLAY(x) IIS2CONFIG = (x) |
56 | #define IIS_CONFIG IIS2CONFIG | 55 | #define IIS_PLAY IIS2CONFIG |
57 | #define PLLCR_SET_AUDIO_BITS_DEFPARM \ | ||
58 | ((freq_ent[FPARM_CLSEL] << 28) | (3 << 22)) | ||
59 | #endif | 56 | #endif |
60 | 57 | ||
58 | #define PLLCR_SET_AUDIO_BITS_DEFPARM \ | ||
59 | ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22)) | ||
60 | |||
61 | /** Sample rates **/ | 61 | /** Sample rates **/ |
62 | #define FPARM_CLOCKSEL 0 | 62 | #define FPARM_CLOCKSEL 0 |
63 | #define FPARM_CLSEL 1 | 63 | #define FPARM_CLSEL 1 |
@@ -113,29 +113,31 @@ void pcm_set_frequency(unsigned int frequency) | |||
113 | } /* pcm_set_frequency */ | 113 | } /* pcm_set_frequency */ |
114 | 114 | ||
115 | /* apply audio settings */ | 115 | /* apply audio settings */ |
116 | void pcm_apply_settings(bool reset) | 116 | void _pcm_apply_settings(bool clear_reset) |
117 | { | 117 | { |
118 | static int last_pcm_freq = HW_SAMPR_DEFAULT; | 118 | static int last_pcm_freq = 0; |
119 | unsigned long output = IIS_CONFIG & (7 << 8); | 119 | |
120 | |||
121 | /* Playback must prevent pops and record monitoring won't work at all if | ||
122 | adding IIS_RESET when setting IIS_CONFIG. Use a different method for | ||
123 | each. */ | ||
124 | if (reset && output != (3 << 8)) | ||
125 | { | ||
126 | /* Not playback - reset first */ | ||
127 | SET_IIS_CONFIG(IIS_RESET); | ||
128 | reset = false; | ||
129 | } | ||
130 | |||
131 | if (pcm_freq != last_pcm_freq) | 120 | if (pcm_freq != last_pcm_freq) |
132 | { | 121 | { |
133 | last_pcm_freq = pcm_freq; | 122 | last_pcm_freq = pcm_freq; |
123 | /* Reprogramming bits 15-12 requires FIFO to be in a reset | ||
124 | condition - Users Manual 17-8, Note 11 */ | ||
125 | or_l(IIS_FIFO_RESET, &IIS_PLAY); | ||
134 | audiohw_set_frequency(freq_ent[FPARM_FSEL]); | 126 | audiohw_set_frequency(freq_ent[FPARM_FSEL]); |
135 | coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM); | 127 | coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM); |
136 | } | 128 | } |
137 | 129 | ||
138 | SET_IIS_CONFIG(IIS_DEFPARM(output) | (reset ? IIS_RESET : 0)); | 130 | SET_IIS_PLAY(IIS_PLAY_DEFPARM | |
131 | (clear_reset ? 0 : (IIS_PLAY & IIS_FIFO_RESET))); | ||
132 | #if 0 | ||
133 | logf("IISPLAY: %08X", IIS_PLAY); | ||
134 | #endif | ||
135 | } /* _pcm_apply_settings */ | ||
136 | |||
137 | /* This clears the reset bit to enable monitoring immediately */ | ||
138 | void pcm_apply_settings(void) | ||
139 | { | ||
140 | _pcm_apply_settings(true); | ||
139 | } /* pcm_apply_settings */ | 141 | } /* pcm_apply_settings */ |
140 | 142 | ||
141 | /** DMA **/ | 143 | /** DMA **/ |
@@ -157,27 +159,31 @@ void pcm_play_dma_start(const void *addr, size_t size) | |||
157 | /* Set up DMA transfer */ | 159 | /* Set up DMA transfer */ |
158 | SAR0 = (unsigned long)addr; /* Source address */ | 160 | SAR0 = (unsigned long)addr; /* Source address */ |
159 | DAR0 = (unsigned long)&PDOR3; /* Destination address */ | 161 | DAR0 = (unsigned long)&PDOR3; /* Destination address */ |
160 | BCR0 = size; /* Bytes to transfer */ | 162 | BCR0 = (unsigned long)size; /* Bytes to transfer */ |
161 | 163 | ||
162 | /* Enable the FIFO and force one write to it */ | 164 | /* Enable the FIFO and force one write to it */ |
163 | pcm_apply_settings(false); | 165 | pcm_apply_settings(); |
164 | 166 | ||
165 | DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | | 167 | DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | |
166 | DMA_SINC | DMA_SSIZE(3) | DMA_START; | 168 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) | DMA_START; |
167 | } /* pcm_play_dma_start */ | 169 | } /* pcm_play_dma_start */ |
168 | 170 | ||
169 | /* Stops the DMA transfer and interrupt */ | 171 | /* Stops the DMA transfer and interrupt */ |
170 | void pcm_play_dma_stop(void) | 172 | void pcm_play_dma_stop(void) |
171 | { | 173 | { |
174 | #if 0 | ||
172 | logf("pcm_play_dma_stop"); | 175 | logf("pcm_play_dma_stop"); |
176 | #endif | ||
173 | 177 | ||
174 | pcm_playing = false; | 178 | pcm_playing = false; |
175 | 179 | ||
176 | DCR0 = 0; | ||
177 | DSR0 = 1; | 180 | DSR0 = 1; |
181 | DCR0 = 0; | ||
178 | 182 | ||
179 | /* Reset the FIFO */ | 183 | /* Place FIFO in reset condition */ |
180 | pcm_apply_settings(false); | 184 | or_l(IIS_FIFO_RESET, &IIS_PLAY); |
185 | |||
186 | pcm_playing = false; | ||
181 | } /* pcm_play_dma_stop */ | 187 | } /* pcm_play_dma_stop */ |
182 | 188 | ||
183 | void pcm_init(void) | 189 | void pcm_init(void) |
@@ -188,17 +194,26 @@ void pcm_init(void) | |||
188 | pcm_paused = false; | 194 | pcm_paused = false; |
189 | pcm_callback_for_more = NULL; | 195 | pcm_callback_for_more = NULL; |
190 | 196 | ||
197 | AUDIOGLOB = (1 << 8) /* IIS1 fifo auto sync */ | ||
198 | | (1 << 7) /* PDIR2 fifo auto sync */ | ||
199 | #ifdef HAVE_SPDIF_OUT | ||
200 | | (1 << 10) /* EBU TX auto sync */ | ||
201 | #endif | ||
202 | ; | ||
191 | DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */ | 203 | DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */ |
192 | DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1; | 204 | and_l(0xffffff00, &DMAROUTE); |
205 | or_l(DMA0_REQ_AUDIO_1, &DMAROUTE); | ||
193 | DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ | 206 | DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ |
194 | 207 | ||
195 | /* Reset the audio FIFO */ | 208 | /* Call pcm_play_dma_stop to initialize everything. */ |
196 | SET_IIS_CONFIG(IIS_RESET); | 209 | pcm_play_dma_stop(); |
197 | 210 | /* Call pcm_close_recording to put in closed state */ | |
211 | pcm_close_recording(); | ||
212 | audio_set_output_source(AUDIO_SRC_PLAYBACK); | ||
213 | audio_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); | ||
198 | pcm_set_frequency(HW_FREQ_DEFAULT); | 214 | pcm_set_frequency(HW_FREQ_DEFAULT); |
199 | 215 | ||
200 | /* Prevent pops (resets DAC to zero point) */ | 216 | _pcm_apply_settings(false); |
201 | SET_IIS_CONFIG(IIS_DEFPARM(3 << 8) | IIS_RESET); | ||
202 | 217 | ||
203 | #if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT) | 218 | #if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT) |
204 | spdif_init(); | 219 | spdif_init(); |
@@ -221,12 +236,9 @@ void pcm_init(void) | |||
221 | (DAC should be at zero point now). */ | 236 | (DAC should be at zero point now). */ |
222 | audiohw_mute(false); | 237 | audiohw_mute(false); |
223 | 238 | ||
224 | /* Call pcm_play_dma_stop to initialize everything. */ | ||
225 | pcm_play_dma_stop(); | ||
226 | |||
227 | /* Enable interrupt at level 7, priority 0 */ | 239 | /* Enable interrupt at level 7, priority 0 */ |
228 | ICR6 = (7 << 2); | 240 | ICR6 = (7 << 2); |
229 | IMR &= ~(1 << 14); /* bit 14 is DMA0 */ | 241 | and_l(~(1 << 14), &IMR); /* bit 14 is DMA0 */ |
230 | } /* pcm_init */ | 242 | } /* pcm_init */ |
231 | 243 | ||
232 | size_t pcm_get_bytes_waiting(void) | 244 | size_t pcm_get_bytes_waiting(void) |
@@ -241,9 +253,8 @@ void DMA0(void) | |||
241 | { | 253 | { |
242 | int res = DSR0; | 254 | int res = DSR0; |
243 | 255 | ||
244 | DSR0 = 1; /* Clear interrupt */ | 256 | DSR0 = 1; /* Clear interrupt */ |
245 | DCR0 &= ~DMA_EEXT; | 257 | and_l(~DMA_EEXT, &DCR0); /* Disable peripheral request */ |
246 | |||
247 | /* Stop on error */ | 258 | /* Stop on error */ |
248 | if ((res & 0x70) == 0) | 259 | if ((res & 0x70) == 0) |
249 | { | 260 | { |
@@ -258,7 +269,7 @@ void DMA0(void) | |||
258 | { | 269 | { |
259 | SAR0 = (unsigned long)next_start; /* Source address */ | 270 | SAR0 = (unsigned long)next_start; /* Source address */ |
260 | BCR0 = next_size; /* Bytes to transfer */ | 271 | BCR0 = next_size; /* Bytes to transfer */ |
261 | DCR0 |= DMA_EEXT; | 272 | or_l(DMA_EEXT, &DCR0); /* Enable peripheral request */ |
262 | return; | 273 | return; |
263 | } | 274 | } |
264 | else | 275 | else |
@@ -272,7 +283,13 @@ void DMA0(void) | |||
272 | } | 283 | } |
273 | else | 284 | else |
274 | { | 285 | { |
275 | logf("DMA Error:0x%04x", res); | 286 | logf("DMA0 err: %02x", res); |
287 | #if 0 | ||
288 | logf(" SAR0: %08x", SAR0); | ||
289 | logf(" DAR0: %08x", DAR0); | ||
290 | logf(" BCR0: %08x", BCR0); | ||
291 | logf(" DCR0: %08x", DCR0); | ||
292 | #endif | ||
276 | } | 293 | } |
277 | 294 | ||
278 | pcm_play_dma_stop(); | 295 | pcm_play_dma_stop(); |
@@ -290,7 +307,10 @@ void pcm_rec_dma_start(void *addr, size_t size) | |||
290 | 307 | ||
291 | pcm_recording = true; | 308 | pcm_recording = true; |
292 | 309 | ||
293 | pcm_apply_settings(false); | 310 | and_l(~PDIR2_FIFO_RESET, &DATAINCONTROL); |
311 | /* Clear reset bit if the source is not set to monitor playback | ||
312 | otherwise maintain independence between playback and recording. */ | ||
313 | _pcm_apply_settings((IIS_PLAY & (7 << 8)) != (3 << 8)); | ||
294 | 314 | ||
295 | /* Start the DMA transfer.. */ | 315 | /* Start the DMA transfer.. */ |
296 | #ifdef HAVE_SPDIF_IN | 316 | #ifdef HAVE_SPDIF_IN |
@@ -303,7 +323,7 @@ void pcm_rec_dma_start(void *addr, size_t size) | |||
303 | BCR1 = (unsigned long)size; /* Bytes to transfer */ | 323 | BCR1 = (unsigned long)size; /* Bytes to transfer */ |
304 | 324 | ||
305 | DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC | | 325 | DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC | |
306 | DMA_DSIZE(3) | DMA_START; | 326 | DMA_DSIZE(DMA_SIZE_LINE) /* | DMA_START */; |
307 | } /* pcm_dma_start */ | 327 | } /* pcm_dma_start */ |
308 | 328 | ||
309 | void pcm_rec_dma_stop(void) | 329 | void pcm_rec_dma_stop(void) |
@@ -314,6 +334,7 @@ void pcm_rec_dma_stop(void) | |||
314 | DCR1 = 0; | 334 | DCR1 = 0; |
315 | 335 | ||
316 | pcm_recording = false; | 336 | pcm_recording = false; |
337 | or_l(PDIR2_FIFO_RESET, &DATAINCONTROL); | ||
317 | } /* pcm_dma_stop */ | 338 | } /* pcm_dma_stop */ |
318 | 339 | ||
319 | void pcm_init_recording(void) | 340 | void pcm_init_recording(void) |
@@ -323,16 +344,15 @@ void pcm_init_recording(void) | |||
323 | pcm_recording = false; | 344 | pcm_recording = false; |
324 | pcm_callback_more_ready = NULL; | 345 | pcm_callback_more_ready = NULL; |
325 | 346 | ||
326 | AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */ | 347 | DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */ |
327 | 348 | DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ | |
328 | DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */ | 349 | and_l(0xffff00ff, &DMAROUTE); |
329 | DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ | 350 | or_l(DMA1_REQ_AUDIO_2, &DMAROUTE); |
330 | DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2; | ||
331 | 351 | ||
332 | pcm_rec_dma_stop(); | 352 | pcm_rec_dma_stop(); |
333 | 353 | ||
334 | ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */ | 354 | ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */ |
335 | IMR &= ~(1 << 15); /* bit 15 is DMA1 */ | 355 | and_l(~(1 << 15), &IMR); /* bit 15 is DMA1 */ |
336 | } /* pcm_init_recording */ | 356 | } /* pcm_init_recording */ |
337 | 357 | ||
338 | void pcm_close_recording(void) | 358 | void pcm_close_recording(void) |
@@ -341,9 +361,9 @@ void pcm_close_recording(void) | |||
341 | 361 | ||
342 | pcm_rec_dma_stop(); | 362 | pcm_rec_dma_stop(); |
343 | 363 | ||
344 | DMAROUTE &= 0xffff00ff; | 364 | and_l(0xffff00ff, &DMAROUTE); |
345 | ICR7 = 0x00; /* Disable interrupt */ | 365 | ICR7 = 0x00; /* Disable interrupt */ |
346 | IMR |= (1 << 15); /* bit 15 is DMA1 */ | 366 | or_l((1 << 15), &IMR); /* bit 15 is DMA1 */ |
347 | } /* pcm_close_recording */ | 367 | } /* pcm_close_recording */ |
348 | 368 | ||
349 | /* DMA1 Interrupt is called when the DMA has finished transfering a chunk | 369 | /* DMA1 Interrupt is called when the DMA has finished transfering a chunk |
@@ -355,13 +375,19 @@ void DMA1(void) | |||
355 | int status = 0; | 375 | int status = 0; |
356 | pcm_more_callback_type2 more_ready; | 376 | pcm_more_callback_type2 more_ready; |
357 | 377 | ||
358 | DSR1 = 1; /* Clear interrupt */ | 378 | DSR1 = 1; /* Clear interrupt */ |
359 | DCR1 &= ~DMA_EEXT; /* Disable peripheral request */ | 379 | and_l(~DMA_EEXT, &DCR1); /* Disable peripheral request */ |
360 | 380 | ||
361 | if (res & 0x70) | 381 | if (res & 0x70) |
362 | { | 382 | { |
363 | status = DMA_REC_ERROR_DMA; | 383 | status = DMA_REC_ERROR_DMA; |
364 | logf("DMA1 err: 0x%x", res); | 384 | logf("DMA1 err: %02x", res); |
385 | #if 0 | ||
386 | logf(" SAR1: %08x", SAR1); | ||
387 | logf(" DAR1: %08x", DAR1); | ||
388 | logf(" BCR1: %08x", BCR1); | ||
389 | logf(" DCR1: %08x", DCR1); | ||
390 | #endif | ||
365 | } | 391 | } |
366 | #ifdef HAVE_SPDIF_IN | 392 | #ifdef HAVE_SPDIF_IN |
367 | else if (DATAINCONTROL == 0xc038 && | 393 | else if (DATAINCONTROL == 0xc038 && |
@@ -392,7 +418,7 @@ void pcm_record_more(void *start, size_t size) | |||
392 | rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ | 418 | rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ |
393 | DAR1 = (unsigned long)start; /* Destination address */ | 419 | DAR1 = (unsigned long)start; /* Destination address */ |
394 | BCR1 = (unsigned long)size; /* Bytes to transfer */ | 420 | BCR1 = (unsigned long)size; /* Bytes to transfer */ |
395 | DCR1 |= DMA_EEXT; | 421 | or_l(DMA_EEXT, &DCR1); /* Enable peripheral request */ |
396 | } | 422 | } |
397 | 423 | ||
398 | void pcm_mute(bool mute) | 424 | void pcm_mute(bool mute) |
@@ -405,15 +431,15 @@ void pcm_mute(bool mute) | |||
405 | void pcm_play_pause_pause(void) | 431 | void pcm_play_pause_pause(void) |
406 | { | 432 | { |
407 | /* Disable DMA peripheral request. */ | 433 | /* Disable DMA peripheral request. */ |
408 | DCR0 &= ~DMA_EEXT; | 434 | and_l(~DMA_EEXT, &DCR0); |
409 | pcm_apply_settings(true); | 435 | or_l(IIS_FIFO_RESET, &IIS_PLAY); |
410 | } /* pcm_play_pause_pause */ | 436 | } /* pcm_play_pause_pause */ |
411 | 437 | ||
412 | void pcm_play_pause_unpause(void) | 438 | void pcm_play_pause_unpause(void) |
413 | { | 439 | { |
414 | /* Enable the FIFO and force one write to it */ | 440 | /* Enable the FIFO and force one write to it */ |
415 | pcm_apply_settings(false); | 441 | pcm_apply_settings(); |
416 | DCR0 |= DMA_EEXT | DMA_START; | 442 | or_l(DMA_EEXT | DMA_START, &DCR0); |
417 | } /* pcm_play_pause_unpause */ | 443 | } /* pcm_play_pause_unpause */ |
418 | 444 | ||
419 | /** | 445 | /** |