summaryrefslogtreecommitdiff
path: root/firmware/target/arm/pcm-pp.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-06-05 07:03:30 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-06-05 07:03:30 +0000
commitbcb8a884ee256e31d45a46bdeb83423457ac48d2 (patch)
tree5452ef9fa0b3f968a30835d44360f35951f2a0d5 /firmware/target/arm/pcm-pp.c
parentfea88888f0bc271b57a6d6dfab387fddc1cbd20d (diff)
downloadrockbox-bcb8a884ee256e31d45a46bdeb83423457ac48d2.tar.gz
rockbox-bcb8a884ee256e31d45a46bdeb83423457ac48d2.zip
e200: Add recording. Just from MIC right now and FM integration will happen soon. Most every bit of weirdness is nescessary and no problems seem to exist that the retailos doesn't exhibit too (namely noise when LCD is on when recording from MIC).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13557 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/pcm-pp.c')
-rw-r--r--firmware/target/arm/pcm-pp.c202
1 files changed, 155 insertions, 47 deletions
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index 41bd92bd0d..9027ff13b3 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -160,7 +160,7 @@ void fiq(void)
160{ 160{
161 /* Clear interrupt */ 161 /* Clear interrupt */
162#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 162#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
163 IISCONFIG &= ~0x2; 163 IISCONFIG &= ~(1 << 1);
164#elif CONFIG_CPU == PP5002 164#elif CONFIG_CPU == PP5002
165 inl(0xcf001040); 165 inl(0xcf001040);
166 IISFIFO_CFG &= ~(1<<9); 166 IISFIFO_CFG &= ~(1<<9);
@@ -171,7 +171,7 @@ void fiq(void)
171 if (FIFO_FREE_COUNT < 2) { 171 if (FIFO_FREE_COUNT < 2) {
172 /* Enable interrupt */ 172 /* Enable interrupt */
173#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 173#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
174 IISCONFIG |= 0x2; 174 IISCONFIG |= (1 << 1);
175#elif CONFIG_CPU == PP5002 175#elif CONFIG_CPU == PP5002
176 IISFIFO_CFG |= (1<<9); 176 IISFIFO_CFG |= (1<<9);
177#endif 177#endif
@@ -221,7 +221,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
221 221
222 /* Enable playback FIFO */ 222 /* Enable playback FIFO */
223#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 223#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
224 IISCONFIG |= 0x20000000; 224 IISCONFIG |= (1 << 29);
225#elif CONFIG_CPU == PP5002 225#elif CONFIG_CPU == PP5002
226 IISCONFIG |= 0x4; 226 IISCONFIG |= 0x4;
227#endif 227#endif
@@ -232,7 +232,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
232 if (FIFO_FREE_COUNT < 2) { 232 if (FIFO_FREE_COUNT < 2) {
233 /* Enable interrupt */ 233 /* Enable interrupt */
234#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 234#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
235 IISCONFIG |= 0x2; 235 IISCONFIG |= (1 << 1);
236#elif CONFIG_CPU == PP5002 236#elif CONFIG_CPU == PP5002
237 IISFIFO_CFG |= (1<<9); 237 IISFIFO_CFG |= (1<<9);
238#endif 238#endif
@@ -257,13 +257,8 @@ void pcm_play_dma_stop(void)
257 pcm_paused = false; 257 pcm_paused = false;
258 258
259#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 259#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
260 260 /* Disable playback FIFO and interrupt */
261 /* Disable playback FIFO */ 261 IISCONFIG &= ~((1 << 29) | (1 << 1));
262 IISCONFIG &= ~0x20000000;
263
264 /* Disable the interrupt */
265 IISCONFIG &= ~0x2;
266
267#elif CONFIG_CPU == PP5002 262#elif CONFIG_CPU == PP5002
268 263
269 /* Disable playback FIFO */ 264 /* Disable playback FIFO */
@@ -279,10 +274,8 @@ void pcm_play_dma_stop(void)
279void pcm_play_pause_pause(void) 274void pcm_play_pause_pause(void)
280{ 275{
281#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 276#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
282 /* Disable the interrupt */ 277 /* Disable playback FIFO and interrupt */
283 IISCONFIG &= ~0x2; 278 IISCONFIG &= ~((1 << 29) | (1 << 1));
284 /* Disable playback FIFO */
285 IISCONFIG &= ~0x20000000;
286#elif CONFIG_CPU == PP5002 279#elif CONFIG_CPU == PP5002
287 /* Disable the interrupt */ 280 /* Disable the interrupt */
288 IISFIFO_CFG &= ~(1<<9); 281 IISFIFO_CFG &= ~(1<<9);
@@ -301,7 +294,7 @@ void pcm_play_pause_unpause(void)
301 294
302 /* Enable playback FIFO */ 295 /* Enable playback FIFO */
303#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 296#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
304 IISCONFIG |= 0x20000000; 297 IISCONFIG |= (1 << 29);
305#elif CONFIG_CPU == PP5002 298#elif CONFIG_CPU == PP5002
306 IISCONFIG |= 0x4; 299 IISCONFIG |= 0x4;
307#endif 300#endif
@@ -312,7 +305,7 @@ void pcm_play_pause_unpause(void)
312 if (FIFO_FREE_COUNT < 2) { 305 if (FIFO_FREE_COUNT < 2) {
313 /* Enable interrupt */ 306 /* Enable interrupt */
314#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 307#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
315 IISCONFIG |= 0x2; 308 IISCONFIG |= (1 << 1);
316#elif CONFIG_CPU == PP5002 309#elif CONFIG_CPU == PP5002
317 IISFIFO_CFG |= (1<<9); 310 IISFIFO_CFG |= (1<<9);
318#endif 311#endif
@@ -369,6 +362,79 @@ void pcm_postinit(void)
369 ** Recording DMA transfer 362 ** Recording DMA transfer
370 **/ 363 **/
371#ifdef HAVE_RECORDING 364#ifdef HAVE_RECORDING
365
366#ifdef HAVE_AS3514
367void fiq_record(void) ICODE_ATTR __attribute__((naked));
368void fiq_record(void)
369{
370 register pcm_more_callback_type2 more_ready;
371 register int32_t value1, value2;
372
373 asm volatile ("stmfd sp!, {r0-r7, ip, lr} \n"); /* Store context */
374
375 IISCONFIG &= ~(1 << 0);
376
377 if (audio_channels == 2) {
378 /* RX is stereo */
379 while (p_size > 0) {
380 if (FIFO_FREE_COUNT < 2) {
381 /* enable interrupt */
382 IISCONFIG |= (1 << 0);
383 goto fiq_record_exit;
384 }
385
386 /* Discard every other sample since ADC clock is 1/2 LRCK */
387 value1 = IISFIFO_RD;
388 value2 = IISFIFO_RD;
389
390 *(int32_t *)p = value1;
391 p += 2;
392 p_size -= 4;
393
394 /* TODO: Figure out how to do IIS loopback */
395 if (audio_output_source != AUDIO_SRC_PLAYBACK) {
396 IISFIFO_WR = value1;
397 IISFIFO_WR = value1;
398 }
399 }
400 }
401 else {
402 /* RX is left channel mono */
403 while (p_size > 0) {
404 if (FIFO_FREE_COUNT < 2) {
405 /* enable interrupt */
406 IISCONFIG |= (1 << 0);
407 goto fiq_record_exit;
408 }
409
410 /* Discard every other sample since ADC clock is 1/2 LRCK */
411 value1 = IISFIFO_RD;
412 value2 = IISFIFO_RD;
413 *p++ = value1;
414 *p++ = value1;
415 p_size -= 4;
416
417 if (audio_output_source != AUDIO_SRC_PLAYBACK) {
418 value1 = *((int32_t *)p - 1);
419 IISFIFO_WR = value1;
420 IISFIFO_WR = value1;
421 }
422 }
423 }
424
425 more_ready = pcm_callback_more_ready;
426
427 if (more_ready == NULL || more_ready(0) < 0) {
428 /* Finished recording */
429 pcm_rec_dma_stop();
430 }
431
432fiq_record_exit:
433 asm volatile("ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */
434 "subs pc, lr, #4 \n"); /* Return from FIQ */
435}
436
437#else
372static short peak_l, peak_r IBSS_ATTR; 438static short peak_l, peak_r IBSS_ATTR;
373 439
374void fiq_record(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ"))); 440void fiq_record(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
@@ -380,7 +446,7 @@ void fiq_record(void)
380 446
381 /* Clear interrupt */ 447 /* Clear interrupt */
382#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 448#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
383 IISCONFIG &= ~0x01; 449 IISCONFIG &= ~(1 << 0);
384#elif CONFIG_CPU == PP5002 450#elif CONFIG_CPU == PP5002
385 /* TODO */ 451 /* TODO */
386#endif 452#endif
@@ -389,12 +455,13 @@ void fiq_record(void)
389 if (FIFO_FREE_COUNT < 2) { 455 if (FIFO_FREE_COUNT < 2) {
390 /* enable interrupt */ 456 /* enable interrupt */
391#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 457#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
392 IISCONFIG |= 0x01; 458 IISCONFIG |= (1 << 0);
393#elif CONFIG_CPU == PP5002 459#elif CONFIG_CPU == PP5002
394 /* TODO */ 460 /* TODO */
395#endif 461#endif
396 return; 462 return;
397 } 463 }
464
398 value = (unsigned short)(IISFIFO_RD >> 16); 465 value = (unsigned short)(IISFIFO_RD >> 16);
399 if (value > peak_l) peak_l = value; 466 if (value > peak_l) peak_l = value;
400 else if (-value > peak_l) peak_l = -value; 467 else if (-value > peak_l) peak_l = -value;
@@ -424,16 +491,18 @@ void fiq_record(void)
424 pcm_rec_dma_stop(); 491 pcm_rec_dma_stop();
425} 492}
426 493
494#endif /* HAVE_AS3514 */
495
427/* Continue transferring data in */ 496/* Continue transferring data in */
428void pcm_record_more(void *start, size_t size) 497void pcm_record_more(void *start, size_t size)
429{ 498{
430 rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ 499 rec_peak_addr = start; /* Start peaking at dest */
431 p = start; 500 p = start; /* Start of RX buffer */
432 p_size = size; /* Bytes to transfer */ 501 p_size = size; /* Bytes to transfer */
433#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 502#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
434 IISCONFIG |= 0x01; 503 IISCONFIG |= (1 << 0);
435#elif CONFIG_CPU == PP5002 504#elif CONFIG_CPU == PP5002
436 /* TODO */ 505 /* TODO */
437#endif 506#endif
438} 507}
439 508
@@ -441,11 +510,14 @@ void pcm_rec_dma_stop(void)
441{ 510{
442 logf("pcm_rec_dma_stop"); 511 logf("pcm_rec_dma_stop");
443 512
444 /* disable fifo */
445 IISCONFIG &= ~0x10000000;
446
447 disable_fiq(); 513 disable_fiq();
448 514
515 /* clear interrupt, disable fifo */
516 IISCONFIG &= ~((1 << 28) | (1 << 0));
517
518 /* clear rx fifo */
519 IISFIFO_CFG |= (1 << 12);
520
449 pcm_recording = false; 521 pcm_recording = false;
450} 522}
451 523
@@ -455,7 +527,10 @@ void pcm_rec_dma_start(void *addr, size_t size)
455 527
456 pcm_recording = true; 528 pcm_recording = true;
457 529
530#ifndef HAVE_AS3514
458 peak_l = peak_r = 0; 531 peak_l = peak_r = 0;
532#endif
533
459 p_size = size; 534 p_size = size;
460 p = addr; 535 p = addr;
461 536
@@ -463,11 +538,8 @@ void pcm_rec_dma_start(void *addr, size_t size)
463 CPU_INT_PRIORITY |= I2S_MASK; 538 CPU_INT_PRIORITY |= I2S_MASK;
464 CPU_INT_EN = I2S_MASK; 539 CPU_INT_EN = I2S_MASK;
465 540
466 /* interrupt on full fifo */ 541 /* interrupt on full fifo, enable record fifo */
467 IISCONFIG |= 0x1; 542 IISCONFIG |= (1 << 28) | (1 << 0);
468
469 /* enable record fifo */
470 IISCONFIG |= 0x10000000;
471 543
472 set_fiq_handler(fiq_record); 544 set_fiq_handler(fiq_record);
473 enable_fiq(); 545 enable_fiq();
@@ -476,18 +548,7 @@ void pcm_rec_dma_start(void *addr, size_t size)
476void pcm_close_recording(void) 548void pcm_close_recording(void)
477{ 549{
478 logf("pcm_close_recording"); 550 logf("pcm_close_recording");
479
480 pcm_rec_dma_stop(); 551 pcm_rec_dma_stop();
481
482#if (CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024)
483 disable_fiq();
484
485 /* disable fifo */
486 IISCONFIG &= ~0x10000000;
487
488 /* Clear interrupt */
489 IISCONFIG &= ~0x01;
490#endif
491} /* pcm_close_recording */ 552} /* pcm_close_recording */
492 553
493void pcm_init_recording(void) 554void pcm_init_recording(void)
@@ -505,7 +566,7 @@ void pcm_init_recording(void)
505 GPIOA_OUTPUT_VAL &= ~0x4; 566 GPIOA_OUTPUT_VAL &= ~0x4;
506#endif 567#endif
507 /* Setup the recording FIQ handler */ 568 /* Setup the recording FIQ handler */
508 *((unsigned int*)(15*4)) = (unsigned int)&fiq_record; 569 set_fiq_handler(fiq_record);
509#endif 570#endif
510 571
511 pcm_rec_dma_stop(); 572 pcm_rec_dma_stop();
@@ -513,10 +574,57 @@ void pcm_init_recording(void)
513 574
514void pcm_calculate_rec_peaks(int *left, int *right) 575void pcm_calculate_rec_peaks(int *left, int *right)
515{ 576{
516 *left = rec_peak_left; 577#ifdef HAVE_AS3514
517 *right = rec_peak_right; 578 if (pcm_recording)
579 {
580 unsigned long *start = rec_peak_addr;
581 unsigned long *end = (unsigned long *)p;
582
583 if (start < end)
584 {
585 unsigned long *addr = start;
586 long peak_l = 0, peak_r = 0;
587 long peaksq_l = 0, peaksq_r = 0;
588
589 do
590 {
591 long value = *addr;
592 long ch, chsq;
593
594 ch = (int16_t)value;
595 chsq = ch*ch;
596 if (chsq > peaksq_l)
597 peak_l = ch, peaksq_l = chsq;
598
599 ch = value >> 16;
600 chsq = ch*ch;
601 if (chsq > peaksq_r)
602 peak_r = ch, peaksq_r = chsq;
603
604 addr += 4;
605 }
606 while (addr < end);
607
608 if (start == rec_peak_addr)
609 rec_peak_addr = end;
610
611 rec_peak_left = abs(peak_l);
612 rec_peak_right = abs(peak_r);
613 }
614 }
615 else
616 {
617 rec_peak_left = rec_peak_right = 0;
618 }
619#endif /* HAVE_AS3514 */
620
621 if (left)
622 *left = rec_peak_left;
623
624 if (right)
625 *right = rec_peak_right;
518} 626}
519#endif 627#endif /* HAVE_RECORDING */
520 628
521/* 629/*
522 * This function goes directly into the DMA buffer to calculate the left and 630 * This function goes directly into the DMA buffer to calculate the left and