diff options
Diffstat (limited to 'firmware/target/arm/pcm-pp.c')
-rw-r--r-- | firmware/target/arm/pcm-pp.c | 202 |
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) | |||
279 | void pcm_play_pause_pause(void) | 274 | void 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 | ||
367 | void fiq_record(void) ICODE_ATTR __attribute__((naked)); | ||
368 | void 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 | |||
432 | fiq_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 | ||
372 | static short peak_l, peak_r IBSS_ATTR; | 438 | static short peak_l, peak_r IBSS_ATTR; |
373 | 439 | ||
374 | void fiq_record(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ"))); | 440 | void 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 */ |
428 | void pcm_record_more(void *start, size_t size) | 497 | void 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) | |||
476 | void pcm_close_recording(void) | 548 | void 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 | ||
493 | void pcm_init_recording(void) | 554 | void 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 | ||
514 | void pcm_calculate_rec_peaks(int *left, int *right) | 575 | void 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 |