summaryrefslogtreecommitdiff
path: root/firmware/target/coldfire/pcm-coldfire.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/coldfire/pcm-coldfire.c')
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c162
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};
42static int peaks[4]; /* p-l, p-r, r-l, r-r */ 42static 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 */
116void pcm_apply_settings(bool reset) 116void _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 */
138void 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 */
170void pcm_play_dma_stop(void) 172void 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
183void pcm_init(void) 189void 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
232size_t pcm_get_bytes_waiting(void) 244size_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
309void pcm_rec_dma_stop(void) 329void 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
319void pcm_init_recording(void) 340void 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
338void pcm_close_recording(void) 358void 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
398void pcm_mute(bool mute) 424void pcm_mute(bool mute)
@@ -405,15 +431,15 @@ void pcm_mute(bool mute)
405void pcm_play_pause_pause(void) 431void 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
412void pcm_play_pause_unpause(void) 438void 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/**