1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 by Michael Sevakis
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
24 #if defined(HAVE_UDA1380)
26 #elif defined(HAVE_TLV320)
29 #if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT)
34 static unsigned long *rec_peak_addr
;
42 static int peaks
[4]; /* p-l, p-r, r-l, r-r */
44 #define IIS_PLAY_DEFPARM ( (freq_ent[FPARM_CLOCKSEL] << 12) | \
45 (IIS_PLAY & (7 << 8)) | \
46 (4 << 2) ) /* 64 bit clocks / word clock */
47 #define IIS_FIFO_RESET (1 << 11)
48 #define PDIR2_FIFO_RESET (1 << 9)
50 #if defined(IAUDIO_X5) || defined(IAUDIO_M5)
51 #define SET_IIS_PLAY(x) IIS1CONFIG = (x)
52 #define IIS_PLAY IIS1CONFIG
54 #define SET_IIS_PLAY(x) IIS2CONFIG = (x)
55 #define IIS_PLAY IIS2CONFIG
58 #define PLLCR_SET_AUDIO_BITS_DEFPARM \
59 ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22))
62 #define FPARM_CLOCKSEL 0
65 #if CONFIG_CPU == MCF5249 && defined(HAVE_UDA1380)
66 static const unsigned char pcm_freq_parms
[HW_NUM_FREQ
][3] =
68 [HW_FREQ_88
] = { 0x0c, 0x01, 0x03 },
69 [HW_FREQ_44
] = { 0x06, 0x01, 0x02 },
70 [HW_FREQ_22
] = { 0x04, 0x02, 0x01 },
71 [HW_FREQ_11
] = { 0x02, 0x02, 0x00 },
75 #if CONFIG_CPU == MCF5250 && defined(HAVE_TLV320)
76 static const unsigned char pcm_freq_parms
[HW_NUM_FREQ
][3] =
78 [HW_FREQ_88
] = { 0x0c, 0x01, 0x02 },
79 [HW_FREQ_44
] = { 0x06, 0x01, 0x01 },
80 [HW_FREQ_22
] = { 0x04, 0x01, 0x00 },
81 [HW_FREQ_11
] = { 0x02, 0x02, 0x00 },
85 static int pcm_freq
= HW_SAMPR_DEFAULT
; /* 44.1 is default */
86 static const unsigned char *freq_ent
= pcm_freq_parms
[HW_FREQ_DEFAULT
];
88 /* set frequency used by the audio hardware */
89 void pcm_set_frequency(unsigned int frequency
)
110 /* remember table entry and rate */
111 freq_ent
= pcm_freq_parms
[index
];
112 pcm_freq
= hw_freq_sampr
[index
];
113 } /* pcm_set_frequency */
115 /* apply audio settings */
116 void _pcm_apply_settings(bool clear_reset
)
118 static int last_pcm_freq
= 0;
120 if (pcm_freq
!= last_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
);
126 audiohw_set_frequency(freq_ent
[FPARM_FSEL
]);
127 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM
);
130 SET_IIS_PLAY(IIS_PLAY_DEFPARM
|
131 (clear_reset
? 0 : (IIS_PLAY
& IIS_FIFO_RESET
)));
133 logf("IISPLAY: %08X", IIS_PLAY
);
135 } /* _pcm_apply_settings */
137 /* This clears the reset bit to enable monitoring immediately */
138 void pcm_apply_settings(void)
140 _pcm_apply_settings(true);
141 } /* pcm_apply_settings */
145 /****************************************************************************
146 ** Playback DMA transfer
149 /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
150 void pcm_play_dma_start(const void *addr
, size_t size
)
152 logf("pcm_play_dma_start");
154 addr
= (void *)((unsigned long)addr
& ~3); /* Align data */
155 size
&= ~3; /* Size must be multiple of 4 */
159 /* Set up DMA transfer */
160 SAR0
= (unsigned long)addr
; /* Source address */
161 DAR0
= (unsigned long)&PDOR3
; /* Destination address */
162 BCR0
= (unsigned long)size
; /* Bytes to transfer */
164 /* Enable the FIFO and force one write to it */
165 pcm_apply_settings();
167 DCR0
= DMA_INT
| DMA_EEXT
| DMA_CS
| DMA_AA
|
168 DMA_SINC
| DMA_SSIZE(DMA_SIZE_LINE
) | DMA_START
;
169 } /* pcm_play_dma_start */
171 /* Stops the DMA transfer and interrupt */
172 void pcm_play_dma_stop(void)
175 logf("pcm_play_dma_stop");
183 /* Place FIFO in reset condition */
184 or_l(IIS_FIFO_RESET
, &IIS_PLAY
);
187 } /* pcm_play_dma_stop */
195 pcm_callback_for_more
= NULL
;
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 */
203 DIVR0
= 54; /* DMA0 is mapped into vector 54 in system.c */
204 and_l(0xffffff00, &DMAROUTE
);
205 or_l(DMA0_REQ_AUDIO_1
, &DMAROUTE
);
206 DMACONFIG
= 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
208 /* Call pcm_play_dma_stop to initialize everything. */
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
);
214 pcm_set_frequency(HW_FREQ_DEFAULT
);
216 _pcm_apply_settings(false);
218 #if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT)
222 /* Initialize default register values. */
225 #if defined(HAVE_UDA1380)
226 /* Sleep a while so the power can stabilize (especially a long
227 delay is needed for the line out connector). */
229 /* Power on FSDAC and HP amp. */
230 audiohw_enable_output(true);
231 #elif defined(HAVE_TLV320)
235 /* UDA1380: Unmute the master channel
236 (DAC should be at zero point now). */
239 /* Enable interrupt at level 7, priority 0 */
241 and_l(~(1 << 14), &IMR
); /* bit 14 is DMA0 */
244 size_t pcm_get_bytes_waiting(void)
246 return BCR0
& 0xffffff;
247 } /* pcm_get_bytes_waiting */
249 /* DMA0 Interrupt is called when the DMA has finished transfering a chunk
250 from the caller's buffer */
251 void DMA0(void) __attribute__ ((interrupt_handler
, section(".icode")));
256 DSR0
= 1; /* Clear interrupt */
257 and_l(~DMA_EEXT
, &DCR0
); /* Disable peripheral request */
259 if ((res
& 0x70) == 0)
261 pcm_more_callback_type get_more
= pcm_callback_for_more
;
262 unsigned char *next_start
;
263 size_t next_size
= 0;
266 get_more(&next_start
, &next_size
);
270 SAR0
= (unsigned long)next_start
; /* Source address */
271 BCR0
= next_size
; /* Bytes to transfer */
272 or_l(DMA_EEXT
, &DCR0
); /* Enable peripheral request */
277 /* Finished playing */
279 /* int. logfs can trash the display */
280 logf("DMA0 No Data:0x%04x", res
);
286 logf("DMA0 err: %02x", res
);
288 logf(" SAR0: %08x", SAR0
);
289 logf(" DAR0: %08x", DAR0
);
290 logf(" BCR0: %08x", BCR0
);
291 logf(" DCR0: %08x", DCR0
);
298 /****************************************************************************
299 ** Recording DMA transfer
301 void pcm_rec_dma_start(void *addr
, size_t size
)
303 logf("pcm_rec_dma_start");
305 addr
= (void *)((unsigned long)addr
& ~3); /* Align data */
306 size
&= ~3; /* Size must be multiple of 4 */
308 pcm_recording
= true;
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));
315 /* Start the DMA transfer.. */
317 INTERRUPTCLEAR
= 0x03c00000;
320 SAR1
= (unsigned long)&PDIR2
; /* Source address */
321 rec_peak_addr
= (unsigned long *)addr
; /* Start peaking at dest */
322 DAR1
= (unsigned long)addr
; /* Destination address */
323 BCR1
= (unsigned long)size
; /* Bytes to transfer */
325 DCR1
= DMA_INT
| DMA_EEXT
| DMA_CS
| DMA_AA
| DMA_DINC
|
326 DMA_DSIZE(DMA_SIZE_LINE
) /* | DMA_START */;
327 } /* pcm_dma_start */
329 void pcm_rec_dma_stop(void)
331 logf("pcm_rec_dma_stop");
333 DSR1
= 1; /* Clear interrupt */
336 pcm_recording
= false;
337 or_l(PDIR2_FIFO_RESET
, &DATAINCONTROL
);
340 void pcm_init_recording(void)
342 logf("pcm_init_recording");
344 pcm_recording
= false;
345 pcm_callback_more_ready
= NULL
;
347 DIVR1
= 55; /* DMA1 is mapped into vector 55 in system.c */
348 DMACONFIG
= 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
349 and_l(0xffff00ff, &DMAROUTE
);
350 or_l(DMA1_REQ_AUDIO_2
, &DMAROUTE
);
354 ICR7
= (7 << 2); /* Enable interrupt at level 7, priority 0 */
355 and_l(~(1 << 15), &IMR
); /* bit 15 is DMA1 */
356 } /* pcm_init_recording */
358 void pcm_close_recording(void)
360 logf("pcm_close_recording");
364 and_l(0xffff00ff, &DMAROUTE
);
365 ICR7
= 0x00; /* Disable interrupt */
366 or_l((1 << 15), &IMR
); /* bit 15 is DMA1 */
367 } /* pcm_close_recording */
369 /* DMA1 Interrupt is called when the DMA has finished transfering a chunk
370 into the caller's buffer */
371 void DMA1(void) __attribute__ ((interrupt_handler
, section(".icode")));
376 pcm_more_callback_type2 more_ready
;
378 DSR1
= 1; /* Clear interrupt */
379 and_l(~DMA_EEXT
, &DCR1
); /* Disable peripheral request */
383 status
= DMA_REC_ERROR_DMA
;
384 logf("DMA1 err: %02x", res
);
386 logf(" SAR1: %08x", SAR1
);
387 logf(" DAR1: %08x", DAR1
);
388 logf(" BCR1: %08x", BCR1
);
389 logf(" DCR1: %08x", DCR1
);
393 else if (DATAINCONTROL
== 0xc038 &&
394 (INTERRUPTSTAT
& 0x01c00000)) /* valnogood, symbolerr, parityerr */
396 INTERRUPTCLEAR
= 0x03c00000;
397 status
= DMA_REC_ERROR_SPDIF
;
402 more_ready
= pcm_callback_more_ready
;
404 if (more_ready
!= NULL
&& more_ready(status
) >= 0)
408 /* int. logfs can trash the display */
409 logf("DMA1 done:%04x %d", res
, status
);
411 /* Finished recording */
415 /* Continue transferring data in */
416 void pcm_record_more(void *start
, size_t size
)
418 rec_peak_addr
= (unsigned long *)start
; /* Start peaking at dest */
419 DAR1
= (unsigned long)start
; /* Destination address */
420 BCR1
= (unsigned long)size
; /* Bytes to transfer */
421 or_l(DMA_EEXT
, &DCR1
); /* Enable peripheral request */
424 void pcm_mute(bool mute
)
431 void pcm_play_pause_pause(void)
433 /* Disable DMA peripheral request. */
434 and_l(~DMA_EEXT
, &DCR0
);
435 or_l(IIS_FIFO_RESET
, &IIS_PLAY
);
436 } /* pcm_play_pause_pause */
438 void pcm_play_pause_unpause(void)
440 /* Enable the FIFO and force one write to it */
441 pcm_apply_settings();
442 or_l(DMA_EEXT
| DMA_START
, &DCR0
);
443 } /* pcm_play_pause_unpause */
446 * Do peak calculation using distance squared from axis and save a lot
447 * of jumps and negation. Don't bother with the calculations of left or
448 * right only as it's never really used and won't save much time.
450 static void pcm_peak_peeker(unsigned long *addr
, unsigned long *end
,
453 long peak_l
= 0, peak_r
= 0;
454 long peaksq_l
= 0, peaksq_r
= 0;
464 peak_l
= ch
, peaksq_l
= chsq
;
469 peak_r
= ch
, peaksq_r
= chsq
;
475 peaks
[0] = abs(peak_l
);
476 peaks
[1] = abs(peak_r
);
477 } /* pcm_peak_peeker */
480 * Return playback peaks - Peaks ahead in the DMA buffer based upon the
481 * calling period to attempt to compensate for
484 void pcm_calculate_peaks(int *left
, int *right
)
486 static unsigned long last_peak_tick
= 0;
487 static unsigned long frame_period
= 0;
489 long samples
, samp_frames
;
492 /* Throttled peak ahead based on calling period */
493 unsigned long period
= current_tick
- last_peak_tick
;
495 /* Keep reasonable limits on period */
498 else if (period
> HZ
/5)
501 frame_period
= (3*frame_period
+ period
) >> 2;
503 last_peak_tick
= current_tick
;
505 if (pcm_playing
&& !pcm_paused
)
507 /* Snapshot as quickly as possible */
509 "move.l %c[sar0], %[start] \n"
510 "move.l %c[bcr0], %[count] \n"
511 : [start
]"=r"(addr
), [count
]"=r"(samples
)
512 : [sar0
]"p"(&SAR0
), [bcr0
]"p"(&BCR0
)
516 samp_frames
= frame_period
*pcm_freq
/(HZ
/4);
517 samples
= MIN(samp_frames
, samples
) >> 2;
521 addr
= (long *)((long)addr
& ~3);
522 pcm_peak_peeker(addr
, addr
+ samples
, &peaks
[PLAY_PEAK_LEFT
]);
527 peaks
[PLAY_PEAK_LEFT
] = peaks
[PLAY_PEAK_RIGHT
] = 0;
531 *left
= peaks
[PLAY_PEAK_LEFT
];
534 *right
= peaks
[PLAY_PEAK_RIGHT
];
535 } /* pcm_calculate_peaks */
538 * Return recording peaks - From the end of the last peak up to
539 * current write position.
541 void pcm_calculate_rec_peaks(int *left
, int *right
)
545 unsigned long *addr
, *end
;
547 /* Snapshot as quickly as possible */
549 "move.l %c[start], %[addr] \n"
550 "move.l %c[dar1], %[end] \n"
551 "and.l %[mask], %[addr] \n"
552 "and.l %[mask], %[end] \n"
553 : [addr
]"=r"(addr
), [end
]"=r"(end
)
554 : [start
]"p"(&rec_peak_addr
), [dar1
]"p"(&DAR1
), [mask
]"r"(~3)
559 pcm_peak_peeker(addr
, end
, &peaks
[REC_PEAK_LEFT
]);
561 if (addr
== rec_peak_addr
)
567 peaks
[REC_PEAK_LEFT
] = peaks
[REC_PEAK_RIGHT
] = 0;
571 *left
= peaks
[REC_PEAK_LEFT
];
574 *right
= peaks
[REC_PEAK_RIGHT
];
575 } /* pcm_calculate_rec_peaks */