HD200 - Setup codec as I2S master and enable recording
[kugel-rb.git] / firmware / target / coldfire / pcm-coldfire.c
blobfa320dff3f9fe216c92e2cdfd46a96d8797f5505
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 by Michael Sevakis
11 * Copyright (C) 2005 by Linus Nielsen Feltzing
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
22 #include <stdlib.h>
23 #include "system.h"
24 #include "kernel.h"
25 #include "logf.h"
26 #include "audio.h"
27 #include "sound.h"
28 #if defined(HAVE_SPDIF_REC) || defined(HAVE_SPDIF_OUT)
29 #include "spdif.h"
30 #endif
32 #define IIS_PLAY_DEFPARM ( (freq_ent[FPARM_CLOCKSEL] << 12) | \
33 (IIS_PLAY & (7 << 8)) | \
34 (4 << 2) ) /* 64 bit clocks / word clock */
35 #define IIS_FIFO_RESET (1 << 11)
36 #define PDIR2_FIFO_RESET (1 << 9)
38 #if defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(IAUDIO_M3)
39 #define IIS_PLAY IIS1CONFIG
40 #else
41 #define IIS_PLAY IIS2CONFIG
42 #endif
44 #ifdef HAVE_SPDIF_OUT
45 /* EBU TX auto sync, PDIR2 fifo auto sync, IIS1 fifo auto sync */
46 #define AUDIOGLOB_DEFPARM ((1 << 10) | (1 << 8) | (1 << 7))
47 #else
48 /* PDIR2 fifo auto sync, IIS1 fifo auto sync */
49 #define AUDIOGLOB_DEFPARM ((1 << 8) | (1 << 7))
50 #endif
52 /** Sample rates **/
53 #define PLLCR_SET_AUDIO_BITS_DEFPARM \
54 ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22))
56 #define FPARM_CLOCKSEL 0
57 #define FPARM_CLSEL 1
59 /* SCLK = Fs * bit clocks per word
60 * so SCLK should be Fs * 64
62 * CLOCKSEL sets SCLK freq based on Audio CLK
63 * 0x0c SCLK = Audio CLK/2 88200 * 64 = 5644800 Hz
64 * 0x06 SCLK = Audio CLK/4 44100 * 64 = 2822400 Hz
65 * 0x04 SCLK = Audio CLK/8 22050 * 64 = 1411200 Hz
66 * 0x02 SCLK = Audio CLK/16 11025 * 64 = 705600 Hz
68 * CLSEL sets MCLK1/2 DAC freq based on XTAL freq
69 * 0x01 MCLK1/2 = XTAL freq
70 * 0x02 MCLK1/2 = XTAL/2 freq
72 * Audio CLK can be XTAL freq or XTAL/2 freq (bit22 in PLLCR)
73 * we always set bit22 so Audio CLK is always XTAL freq
76 #if CONFIG_CPU == MCF5249 && defined(HAVE_UDA1380)
77 static const unsigned char pcm_freq_parms[HW_NUM_FREQ][2] =
79 [HW_FREQ_88] = { 0x0c, 0x01 },
80 [HW_FREQ_44] = { 0x06, 0x01 },
81 [HW_FREQ_22] = { 0x04, 0x02 },
82 [HW_FREQ_11] = { 0x02, 0x02 },
84 #endif
86 #if CONFIG_CPU == MCF5249 && defined(HAVE_WM8750)
87 /* We run codec in master mode.
88 * Codec can reconstruct all frequencies
89 * from single 11.2896 MHz master clock
91 static const unsigned char pcm_freq_parms[HW_NUM_FREQ][2] =
93 [HW_FREQ_88] = { 0x00, 0x01 },
94 [HW_FREQ_44] = { 0x00, 0x01 },
95 [HW_FREQ_22] = { 0x00, 0x01 },
96 [HW_FREQ_11] = { 0x00, 0x01 },
99 #endif
101 #if (CONFIG_CPU == MCF5250 || CONFIG_CPU == MCF5249) && defined(HAVE_TLV320)
102 static const unsigned char pcm_freq_parms[HW_NUM_FREQ][2] =
104 [HW_FREQ_88] = { 0x0c, 0x01 },
105 [HW_FREQ_44] = { 0x06, 0x01 },
106 [HW_FREQ_22] = { 0x04, 0x01 },
107 [HW_FREQ_11] = { 0x02, 0x02 },
109 #endif
111 static const unsigned char *freq_ent;
113 /* Lock status struct for playback and recording */
114 struct dma_lock
116 int locked;
117 unsigned long state;
120 static void iis_play_reset(void)
122 or_l(IIS_FIFO_RESET, &IIS_PLAY);
123 and_l(~IIS_FIFO_RESET, &IIS_PLAY);
124 PDOR3 = 0;
127 static bool is_playback_monitoring(void)
129 return (IIS_PLAY & (7 << 8)) == (3 << 8);
132 static void iis_play_reset_if_playback(bool if_playback)
134 int level = set_irq_level(DMA_IRQ_LEVEL);
135 if (is_playback_monitoring() == if_playback)
136 iis_play_reset();
137 restore_irq(level);
140 /* apply audio settings */
141 /* This clears the reset bit to enable monitoring immediately if monitoring
142 recording sources or always if playback is in progress - we might be
143 switching samplerates on the fly */
144 void pcm_dma_apply_settings(void)
146 int level = set_irq_level(DMA_IRQ_LEVEL);
148 /* remember table entry */
149 freq_ent = pcm_freq_parms[pcm_fsel];
151 /* Reprogramming bits 15-12 requires FIFO to be in a reset
152 condition - Users Manual 17-8, Note 11 */
153 or_l(IIS_FIFO_RESET, &IIS_PLAY);
154 /* Important for TLV320 - this must happen in the correct order
155 or starting recording will sound absolutely awful once in
156 awhile - audiohw_set_frequency then coldfire_set_pllcr_audio_bits
158 IIS_PLAY = IIS_PLAY_DEFPARM | IIS_FIFO_RESET;
159 restore_irq(level);
161 audiohw_set_frequency(pcm_fsel);
162 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM);
164 level = set_irq_level(DMA_IRQ_LEVEL);
166 IIS_PLAY = IIS_PLAY_DEFPARM;
168 if ((DCR0 & DMA_EEXT) != 0 && is_playback_monitoring())
169 PDOR3 = 0; /* Kick FIFO out of reset by writing to it */
171 restore_irq(level);
172 } /* pcm_dma_apply_settings */
174 void pcm_play_dma_init(void)
176 freq_ent = pcm_freq_parms[pcm_fsel];
178 AUDIOGLOB = AUDIOGLOB_DEFPARM;
179 DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */
180 and_l(0xffffff00, &DMAROUTE);
181 or_l(DMA0_REQ_AUDIO_1, &DMAROUTE);
182 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
183 BCR0 = 0; /* No bytes waiting */
184 ICR6 = (6 << 2); /* Enable interrupt at level 6, priority 0 */
186 /* Setup Coldfire I2S before initializing hardware or changing
187 other settings. */
188 or_l(IIS_FIFO_RESET, &IIS_PLAY);
189 IIS_PLAY = IIS_PLAY_DEFPARM | IIS_FIFO_RESET;
190 audio_set_output_source(AUDIO_SRC_PLAYBACK);
192 /* Initialize default register values. */
193 audiohw_init();
195 audio_input_mux(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
197 audiohw_set_frequency(pcm_fsel);
198 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM);
200 #if defined(HAVE_SPDIF_REC) || defined(HAVE_SPDIF_OUT)
201 spdif_init();
202 #endif
203 } /* pcm_play_dma_init */
205 void pcm_postinit(void)
207 audiohw_postinit();
208 iis_play_reset();
211 /** DMA **/
213 /****************************************************************************
214 ** Playback DMA transfer
216 /* For the locks, DMA interrupt must be disabled when manipulating the lock
217 if the handler ever calls these - right now things are arranged so it
218 doesn't */
219 static struct dma_lock dma_play_lock =
221 .locked = 0,
222 .state = (0 << 14) /* bit 14 is DMA0 */
225 void pcm_play_lock(void)
227 if (++dma_play_lock.locked == 1)
228 or_l((1 << 14), &IMR);
231 void pcm_play_unlock(void)
233 if (--dma_play_lock.locked == 0)
234 and_l(~dma_play_lock.state, &IMR);
237 /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
238 void pcm_play_dma_start(const void *addr, size_t size)
240 /* Stop any DMA in progress */
241 pcm_play_dma_stop();
243 /* Set up DMA transfer */
244 SAR0 = (unsigned long)addr; /* Source address */
245 DAR0 = (unsigned long)&PDOR3; /* Destination address */
246 BCR0 = (unsigned long)size; /* Bytes to transfer */
248 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_SINC |
249 DMA_SSIZE(DMA_SIZE_LINE) | DMA_START;
251 dma_play_lock.state = (1 << 14);
252 } /* pcm_play_dma_start */
254 /* Stops the DMA transfer and interrupt */
255 void pcm_play_dma_stop(void)
257 and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */
258 BCR0 = 0; /* No bytes remaining */
259 DSR0 = 1; /* Clear interrupt, errors, stop transfer */
261 iis_play_reset_if_playback(true);
263 dma_play_lock.state = (0 << 14);
264 } /* pcm_play_dma_stop */
266 void pcm_play_dma_pause(bool pause)
268 if (pause)
270 /* pause playback on current buffer */
271 and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */
272 DSR0 = 1; /* stop channel */
273 iis_play_reset_if_playback(true);
274 dma_play_lock.state = (0 << 14);
276 else
278 /* restart playback on current buffer */
279 iis_play_reset_if_playback(true);
280 or_l(DMA_INT | DMA_EEXT | DMA_START, &DCR0); /* everything ON */
281 dma_play_lock.state = (1 << 14);
283 } /* pcm_play_dma_pause */
285 size_t pcm_get_bytes_waiting(void)
287 return BCR0 & 0xffffff;
288 } /* pcm_get_bytes_waiting */
290 /* DMA0 Interrupt is called when the DMA has finished transfering a chunk
291 from the caller's buffer */
292 void DMA0(void) __attribute__ ((interrupt_handler, section(".icode")));
293 void DMA0(void)
295 unsigned long res = DSR0;
296 void *start;
297 size_t size;
299 and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */
300 DSR0 = 1; /* Clear interrupt and errors */
302 if (res & 0x70)
304 logf("DMA0 err: %02x", res);
305 #if 0
306 logf(" SAR0: %08x", SAR0);
307 logf(" DAR0: %08x", DAR0);
308 logf(" BCR0: %08x", BCR0);
309 logf(" DCR0: %08x", DCR0);
310 #endif
313 /* Force stop on error */
314 pcm_play_get_more_callback((res & 0x70) ? NULL : &start, &size);
316 if (size != 0)
318 SAR0 = (unsigned long)start; /* Source address */
319 BCR0 = size; /* Bytes to transfer */
320 or_l(DMA_EEXT | DMA_INT, &DCR0); /* per request and int ON */
322 /* else inished playing */
323 } /* DMA0 */
325 const void * pcm_play_dma_get_peak_buffer(int *count)
327 unsigned long addr, cnt;
329 /* Make sure interrupt doesn't change the second value after we read the
330 * first value. */
331 int level = set_irq_level(DMA_IRQ_LEVEL);
332 addr = SAR0;
333 cnt = BCR0;
334 restore_irq(level);
336 *count = (cnt & 0xffffff) >> 2;
337 return (void *)((addr + 2) & ~3);
338 } /* pcm_play_dma_get_peak_buffer */
340 #ifdef HAVE_RECORDING
341 /****************************************************************************
342 ** Recording DMA transfer
344 static struct dma_lock dma_rec_lock =
346 .locked = 0,
347 .state = (0 << 15) /* bit 15 is DMA1 */
350 /* For the locks, DMA interrupt must be disabled when manipulating the lock
351 if the handler ever calls these - right now things are arranged so it
352 doesn't */
353 void pcm_rec_lock(void)
355 if (++dma_rec_lock.locked == 1)
356 or_l((1 << 15), &IMR);
359 void pcm_rec_unlock(void)
361 if (--dma_rec_lock.locked == 0)
362 and_l(~dma_rec_lock.state, &IMR);
365 void pcm_rec_dma_start(void *addr, size_t size)
367 /* stop any DMA in progress */
368 pcm_rec_dma_stop();
370 and_l(~PDIR2_FIFO_RESET, &DATAINCONTROL);
372 /* Start the DMA transfer.. */
373 #ifdef HAVE_SPDIF_REC
374 /* clear: ebu1cnew, valnogood, symbolerr, parityerr */
375 INTERRUPTCLEAR = (1 << 25) | (1 << 24) | (1 << 23) | (1 << 22);
376 #endif
378 SAR1 = (unsigned long)&PDIR2; /* Source address */
379 DAR1 = (unsigned long)addr; /* Destination address */
380 BCR1 = (unsigned long)size; /* Bytes to transfer */
382 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC |
383 DMA_DSIZE(DMA_SIZE_LINE) | DMA_START;
385 dma_rec_lock.state = (1 << 15);
386 } /* pcm_rec_dma_start */
388 void pcm_rec_dma_stop(void)
390 and_l(~(DMA_EEXT | DMA_INT), &DCR1); /* per request and int OFF */
391 DSR1 = 1; /* Clear interrupt, errors, stop transfer */
392 BCR1 = 0; /* No bytes received */
394 or_l(PDIR2_FIFO_RESET, &DATAINCONTROL);
396 iis_play_reset_if_playback(false);
398 dma_rec_lock.state = (0 << 15);
399 } /* pcm_rec_dma_stop */
401 void pcm_rec_dma_init(void)
403 DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */
404 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
405 and_l(0xffff00ff, &DMAROUTE);
406 or_l(DMA1_REQ_AUDIO_2, &DMAROUTE);
408 pcm_rec_dma_stop();
410 /* Enable interrupt at level 6, priority 1 */
411 ICR7 = (6 << 2) | (1 << 0);
412 } /* pcm_init_recording */
414 void pcm_rec_dma_close(void)
416 pcm_rec_dma_stop();
418 and_l(0xffff00ff, &DMAROUTE);
419 ICR7 = 0x00; /* Disable interrupt */
420 dma_rec_lock.state = (0 << 15);
421 } /* pcm_rec_dma_close */
423 /* DMA1 Interrupt is called when the DMA has finished transfering a chunk
424 into the caller's buffer */
425 void DMA1(void) __attribute__ ((interrupt_handler, section(".icode")));
426 void DMA1(void)
428 unsigned long res = DSR1;
429 int status = 0;
430 void *start;
431 size_t size;
433 and_l(~(DMA_EEXT | DMA_INT), &DCR1); /* per request and int OFF */
434 DSR1 = 1; /* Clear interrupt and errors */
436 if (res & 0x70)
438 status = DMA_REC_ERROR_DMA;
439 logf("DMA1 err: %02x", res);
440 #if 0
441 logf(" SAR1: %08x", SAR1);
442 logf(" DAR1: %08x", DAR1);
443 logf(" BCR1: %08x", BCR1);
444 logf(" DCR1: %08x", DCR1);
445 #endif
447 #ifdef HAVE_SPDIF_REC
448 else if (DATAINCONTROL == 0xc038 &&
449 (INTERRUPTSTAT & ((1 << 23) | (1 << 22))))
451 /* reason: symbolerr, parityerr.
452 * Ignore valnogood since several sources don't set it properly. */
453 /* clear: ebu1cnew, symbolerr, parityerr */
454 INTERRUPTCLEAR = (1 << 25) | (1 << 23) | (1 << 22);
455 status = DMA_REC_ERROR_SPDIF;
456 logf("spdif err");
458 #endif
460 /* Inform PCM we have more data (or error) */
461 pcm_rec_more_ready_callback(status, &start, &size);
463 if (size != 0)
465 DAR1 = (unsigned long)start; /* Destination address */
466 BCR1 = (unsigned long)size; /* Bytes to transfer */
467 or_l(DMA_EEXT | DMA_INT, &DCR1); /* per request and int ON */
469 } /* DMA1 */
471 const void * pcm_rec_dma_get_peak_buffer(void)
473 return (void *)(DAR1 & ~3);
474 } /* pcm_rec_dma_get_peak_buffer */
475 #endif