summaryrefslogtreecommitdiff
path: root/firmware/pcm_playback.c
diff options
context:
space:
mode:
authorBarry Wardell <rockbox@barrywardell.net>2006-12-18 01:52:21 +0000
committerBarry Wardell <rockbox@barrywardell.net>2006-12-18 01:52:21 +0000
commitdf0dc2262ea10f621677c0f97aae1c205e253b87 (patch)
treed25085132fe9f0504d221360092537492cedd3b8 /firmware/pcm_playback.c
parent440353a9aa1159584b977a2852e723ae07bad2a6 (diff)
downloadrockbox-df0dc2262ea10f621677c0f97aae1c205e253b87.tar.gz
rockbox-df0dc2262ea10f621677c0f97aae1c205e253b87.zip
FS#6096. Recording on PortalPlayer targets (H10, iPod Video, iPod 4g, iPod Color, iPod Nano).
* Fix failed compile of enc_config.c when HAVE_MPEG2_SAMPR is not defined. * Fix bug in AIFF encoder header creation on little endian targets. * Add recording screen keymaps for H10 and iPod. * Move pcm_playback PP specific code to target tree. * Add recording code to wmcodec drivers. * Add pcm_record code. Some problems still remain: * Playback doesn't work after recording until Rockbox is restarted. * Gain control not implemented. * Only 16-bit/44KHz for now. The hardware should be capable of up to 24-bit/96KHz. * Line-in recording not tested on H10. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11794 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/pcm_playback.c')
-rw-r--r--firmware/pcm_playback.c328
1 files changed, 3 insertions, 325 deletions
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index 46a458fa8a..92a4c3e5c7 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -98,326 +98,6 @@ size_t pcm_get_bytes_waiting(void)
98 return 0; 98 return 0;
99} 99}
100 100
101#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
102 || defined(HAVE_WM8731) || defined(HAVE_WM8721) \
103 || defined(HAVE_PP5024_CODEC)
104
105/* We need to unify this code with the uda1380 code as much as possible, but
106 we will keep it separate during early development.
107*/
108
109#if CONFIG_CPU == PP5020
110#define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x3f0000) >> 16)
111#elif CONFIG_CPU == PP5002
112#define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x7800000) >> 23)
113#elif CONFIG_CPU == PP5024
114#define FIFO_FREE_COUNT 4 /* TODO: make this sensible */
115#endif
116
117static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
118
119/* NOTE: The order of these two variables is important if you use the iPod
120 assembler optimised fiq handler, so don't change it. */
121unsigned short* p IBSS_ATTR;
122size_t p_size IBSS_ATTR;
123
124void pcm_play_dma_start(const void *addr, size_t size)
125{
126 p=(unsigned short*)addr;
127 p_size=size;
128
129 pcm_playing = true;
130
131#if CONFIG_CPU == PP5020
132 /* setup I2S interrupt for FIQ */
133 outl(inl(0x6000402c) | I2S_MASK, 0x6000402c);
134 outl(I2S_MASK, 0x60004024);
135#elif CONFIG_CPU == PP5024
136#else
137 /* setup I2S interrupt for FIQ */
138 outl(inl(0xcf00102c) | DMA_OUT_MASK, 0xcf00102c);
139 outl(DMA_OUT_MASK, 0xcf001024);
140#endif
141
142 /* Clear the FIQ disable bit in cpsr_c */
143 enable_fiq();
144
145 /* Enable playback FIFO */
146#if CONFIG_CPU == PP5020
147 IISCONFIG |= 0x20000000;
148#elif CONFIG_CPU == PP5002
149 IISCONFIG |= 0x4;
150#endif
151
152 /* Fill the FIFO - we assume there are enough bytes in the pcm buffer to
153 fill the 32-byte FIFO. */
154 while (p_size > 0) {
155 if (FIFO_FREE_COUNT < 2) {
156 /* Enable interrupt */
157#if CONFIG_CPU == PP5020
158 IISCONFIG |= 0x2;
159#elif CONFIG_CPU == PP5002
160 IISFIFO_CFG |= (1<<9);
161#endif
162 return;
163 }
164
165 IISFIFO_WR = (*(p++))<<16;
166 IISFIFO_WR = (*(p++))<<16;
167 p_size-=4;
168 }
169}
170
171/* Stops the DMA transfer and interrupt */
172void pcm_play_dma_stop(void)
173{
174 pcm_playing = false;
175
176#if CONFIG_CPU == PP5020
177
178 /* Disable playback FIFO */
179 IISCONFIG &= ~0x20000000;
180
181 /* Disable the interrupt */
182 IISCONFIG &= ~0x2;
183
184#elif CONFIG_CPU == PP5002
185
186 /* Disable playback FIFO */
187 IISCONFIG &= ~0x4;
188
189 /* Disable the interrupt */
190 IISFIFO_CFG &= ~(1<<9);
191#endif
192
193 disable_fiq();
194}
195
196void pcm_play_pause_pause(void)
197{
198#if CONFIG_CPU == PP5020
199 /* Disable the interrupt */
200 IISCONFIG &= ~0x2;
201 /* Disable playback FIFO */
202 IISCONFIG &= ~0x20000000;
203#elif CONFIG_CPU == PP5002
204 /* Disable the interrupt */
205 IISFIFO_CFG &= ~(1<<9);
206 /* Disable playback FIFO */
207 IISCONFIG &= ~0x4;
208#endif
209 disable_fiq();
210}
211
212void pcm_play_pause_unpause(void)
213{
214 /* Enable the FIFO and fill it */
215
216 enable_fiq();
217
218 /* Enable playback FIFO */
219#if CONFIG_CPU == PP5020
220 IISCONFIG |= 0x20000000;
221#elif CONFIG_CPU == PP5002
222 IISCONFIG |= 0x4;
223#endif
224
225 /* Fill the FIFO - we assume there are enough bytes in the
226 pcm buffer to fill the 32-byte FIFO. */
227 while (p_size > 0) {
228 if (FIFO_FREE_COUNT < 2) {
229 /* Enable interrupt */
230#if CONFIG_CPU == PP5020
231 IISCONFIG |= 0x2;
232#elif CONFIG_CPU == PP5002
233 IISFIFO_CFG |= (1<<9);
234#endif
235 return;
236 }
237
238 IISFIFO_WR = (*(p++))<<16;
239 IISFIFO_WR = (*(p++))<<16;
240 p_size-=4;
241 }
242}
243
244void pcm_set_frequency(unsigned int frequency)
245{
246 (void)frequency;
247 pcm_freq = HW_SAMPR_DEFAULT;
248}
249
250size_t pcm_get_bytes_waiting(void)
251{
252 return p_size;
253}
254
255/* ASM optimised FIQ handler. GCC fails to make use of the fact that FIQ mode
256 has registers r8-r14 banked, and so does not need to be saved. This routine
257 uses only these registers, and so will never touch the stack unless it
258 actually needs to do so when calling pcm_callback_for_more. C version is
259 still included below for reference.
260 */
261#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
262void fiq(void) ICODE_ATTR __attribute__((naked));
263void fiq(void)
264{
265 /* r12 contains IISCONFIG address (set in crt0.S to minimise code in actual
266 * FIQ handler. r11 contains address of p (also set in crt0.S). Most other
267 * addresses we need are generated by using offsets with these two.
268 * r12 + 0x40 is IISFIFO_WR, and r12 + 0x0c is IISFIFO_CFG.
269 * r8 and r9 contains local copies of p_size and p respectively.
270 * r10 is a working register.
271 */
272 asm volatile (
273#if CONFIG_CPU == PP5002
274 "ldr r10, =0xcf001040 \n\t" /* Some magic from iPodLinux */
275 "ldr r10, [r10] \n\t"
276 "ldr r10, [r12, #0x1c]\n\t"
277 "bic r10, r10, #0x200 \n\t" /* clear interrupt */
278 "str r10, [r12, #0x1c]\n\t"
279#else
280 "ldr r10, [r12] \n\t"
281 "bic r10, r10, #0x2 \n\t" /* clear interrupt */
282 "str r10, [r12] \n\t"
283#endif
284 "ldr r8, [r11, #4] \n\t" /* r8 = p_size */
285 "ldr r9, [r11] \n\t" /* r9 = p */
286 ".loop: \n\t"
287 "cmp r8, #0 \n\t" /* is p_size 0? */
288 "beq .more_data \n\t" /* if so, ask pcmbuf for more data */
289 ".fifo_loop: \n\t"
290#if CONFIG_CPU == PP5002
291 "ldr r10, [r12, #0x1c]\n\t" /* read IISFIFO_CFG to check FIFO status */
292 "and r10, r10, #0x7800000\n\t"
293 "cmp r10, #0x800000 \n\t"
294#else
295 "ldr r10, [r12, #0x0c]\n\t" /* read IISFIFO_CFG to check FIFO status */
296 "and r10, r10, #0x3f0000\n\t"
297 "cmp r10, #0x10000 \n\t"
298#endif
299 "bls .fifo_full \n\t" /* FIFO full, exit */
300 "ldr r10, [r9], #4 \n\t" /* load two samples */
301 "mov r10, r10, ror #16\n\t" /* put left sample at the top bits */
302 "str r10, [r12, #0x40]\n\t" /* write top sample, lower sample ignored */
303 "mov r10, r10, lsl #16\n\t" /* shift lower sample up */
304 "str r10, [r12, #0x40]\n\t" /* then write it */
305 "subs r8, r8, #4 \n\t" /* check if we have more samples */
306 "bne .fifo_loop \n\t" /* yes, continue */
307 ".more_data: \n\t"
308 "stmdb sp!, { r0-r3, r12, lr}\n\t" /* stack scratch regs and lr */
309 "mov r0, r11 \n\t" /* r0 = &p */
310 "add r1, r11, #4 \n\t" /* r1 = &p_size */
311 "str r9, [r0] \n\t" /* save internal copies of variables back */
312 "str r8, [r1] \n\t"
313 "ldr r2, =pcm_callback_for_more\n\t"
314 "ldr r2, [r2] \n\t" /* get callback address */
315 "cmp r2, #0 \n\t" /* check for null pointer */
316 "movne lr, pc \n\t" /* call pcm_callback_for_more */
317 "bxne r2 \n\t"
318 "ldmia sp!, { r0-r3, r12, lr}\n\t"
319 "ldr r8, [r11, #4] \n\t" /* reload p_size and p */
320 "ldr r9, [r11] \n\t"
321 "cmp r8, #0 \n\t" /* did we actually get more data? */
322 "bne .loop \n\t" /* yes, continue to try feeding FIFO */
323 ".dma_stop: \n\t" /* no more data, do dma_stop() and exit */
324 "ldr r10, =pcm_playing\n\t"
325 "strb r8, [r10] \n\t" /* pcm_playing = false (r8=0, look above) */
326 "ldr r10, [r12] \n\t"
327#if CONFIG_CPU == PP5002
328 "bic r10, r10, #0x4\n\t" /* disable playback FIFO */
329 "str r10, [r12] \n\t"
330 "ldr r10, [r12, #0x1c] \n\t"
331 "bic r10, r10, #0x200 \n\t" /* clear interrupt */
332 "str r10, [r12, #0x1c] \n\t"
333#else
334 "bic r10, r10, #0x20000002\n\t" /* disable playback FIFO and IRQ */
335 "str r10, [r12] \n\t"
336#endif
337 "mrs r10, cpsr \n\t"
338 "orr r10, r10, #0x40 \n\t" /* disable FIQ */
339 "msr cpsr_c, r10 \n\t"
340 ".exit: \n\t"
341 "str r8, [r11, #4] \n\t"
342 "str r9, [r11] \n\t"
343 "subs pc, lr, #4 \n\t" /* FIQ specific return sequence */
344 ".fifo_full: \n\t" /* enable IRQ and exit */
345#if CONFIG_CPU == PP5002
346 "ldr r10, [r12, #0x1c]\n\t"
347 "orr r10, r10, #0x200 \n\t" /* set interrupt */
348 "str r10, [r12, #0x1c]\n\t"
349#else
350 "ldr r10, [r12] \n\t"
351 "orr r10, r10, #0x2 \n\t" /* set interrupt */
352 "str r10, [r12] \n\t"
353#endif
354 "b .exit \n\t"
355 );
356}
357#else /* !(CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002) */
358void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
359void fiq(void)
360{
361 /* Clear interrupt */
362#if CONFIG_CPU == PP5020
363 IISCONFIG &= ~0x2;
364#elif CONFIG_CPU == PP5002
365 inl(0xcf001040);
366 IISFIFO_CFG &= ~(1<<9);
367#endif
368
369 do {
370 while (p_size) {
371 if (FIFO_FREE_COUNT < 2) {
372 /* Enable interrupt */
373#if CONFIG_CPU == PP5020
374 IISCONFIG |= 0x2;
375#elif CONFIG_CPU == PP5002
376 IISFIFO_CFG |= (1<<9);
377#endif
378 return;
379 }
380
381 IISFIFO_WR = (*(p++))<<16;
382 IISFIFO_WR = (*(p++))<<16;
383 p_size-=4;
384 }
385
386 /* p is empty, get some more data */
387 if (pcm_callback_for_more) {
388 pcm_callback_for_more((unsigned char**)&p,&p_size);
389 }
390 } while (p_size);
391
392 /* No more data, so disable the FIFO/FIQ */
393 pcm_play_dma_stop();
394}
395#endif /* CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 */
396
397#ifdef HAVE_PP5024_CODEC
398void pcm_init(void)
399{
400}
401#else
402void pcm_init(void)
403{
404 pcm_playing = false;
405 pcm_paused = false;
406 pcm_callback_for_more = NULL;
407
408 /* Initialize default register values. */
409 audiohw_init();
410
411 /* Power on */
412 audiohw_enable_output(true);
413
414 /* Unmute the master channel (DAC should be at zero point now). */
415 audiohw_mute(false);
416
417 /* Call pcm_play_dma_stop to initialize everything. */
418 pcm_play_dma_stop();
419}
420#endif /* HAVE_PP5024_CODEC */
421#elif (CONFIG_CPU == PNX0101) 101#elif (CONFIG_CPU == PNX0101)
422 102
423#define DMA_BUF_SAMPLES 0x100 103#define DMA_BUF_SAMPLES 0x100
@@ -608,7 +288,7 @@ void pcm_mute(bool mute)
608 if (mute) 288 if (mute)
609 sleep(HZ/16); 289 sleep(HZ/16);
610} 290}
611 291#if !defined(CPU_PP)
612/* 292/*
613 * This function goes directly into the DMA buffer to calculate the left and 293 * This function goes directly into the DMA buffer to calculate the left and
614 * right peak values. To avoid missing peaks it tries to look forward two full 294 * right peak values. To avoid missing peaks it tries to look forward two full
@@ -632,9 +312,7 @@ void pcm_calculate_peaks(int *left, int *right)
632 short *addr; 312 short *addr;
633 short *end; 313 short *end;
634 { 314 {
635#if defined(HAVE_WM8975) || defined(HAVE_WM8758) \ 315#if CONFIG_CPU == PNX0101
636 || defined(HAVE_WM8731) || defined(HAVE_WM8721) \
637 || (CONFIG_CPU == PNX0101) || defined(HAVE_PP5024_CODEC)
638 size_t samples = p_size / 4; 316 size_t samples = p_size / 4;
639 addr = p; 317 addr = p;
640#endif 318#endif
@@ -690,7 +368,7 @@ void pcm_calculate_peaks(int *left, int *right)
690 } 368 }
691#endif 369#endif
692} 370}
693 371#endif
694#endif /* CPU_COLDFIRE */ 372#endif /* CPU_COLDFIRE */
695 373
696/**************************************************************************** 374/****************************************************************************