summaryrefslogtreecommitdiff
path: root/firmware/target/arm
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
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')
-rw-r--r--firmware/target/arm/pcm-pp.c202
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/ata-e200.c11
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/audio-e200.c103
3 files changed, 264 insertions, 52 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
diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
index 29fe0d9109..10c13cdb2e 100644
--- a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
@@ -223,6 +223,7 @@ void sd_wait_for_state(tSDCardInfo* card, unsigned int state)
223 while(((response >> 9) & 0xf) != state) 223 while(((response >> 9) & 0xf) != state)
224 { 224 {
225 sd_send_command(SEND_STATUS, (card->rca) << 16, 1); 225 sd_send_command(SEND_STATUS, (card->rca) << 16, 1);
226 priority_yield();
226 sd_read_response(&response, 1); 227 sd_read_response(&response, 1);
227 /* TODO: Add a timeout and error handling */ 228 /* TODO: Add a timeout and error handling */
228 } 229 }
@@ -442,7 +443,7 @@ void sd_init_device(void)
442 dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */ 443 dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */
443 } 444 }
444 } 445 }
445 mutex_init(&sd_mtx); 446 spinlock_init(&sd_mtx);
446} 447}
447 448
448/* API Functions */ 449/* API Functions */
@@ -472,7 +473,7 @@ int ata_read_sectors(IF_MV2(int drive,)
472#ifdef HAVE_MULTIVOLUME 473#ifdef HAVE_MULTIVOLUME
473 (void)drive; /* unused for now */ 474 (void)drive; /* unused for now */
474#endif 475#endif
475 mutex_lock(&sd_mtx); 476 spinlock_lock(&sd_mtx);
476 477
477 last_disk_activity = current_tick; 478 last_disk_activity = current_tick;
478 spinup_start = current_tick; 479 spinup_start = current_tick;
@@ -530,7 +531,7 @@ int ata_read_sectors(IF_MV2(int drive,)
530 ata_led(false); 531 ata_led(false);
531 ata_enable(false); 532 ata_enable(false);
532 533
533 mutex_unlock(&sd_mtx); 534 spinlock_unlock(&sd_mtx);
534 535
535 return ret; 536 return ret;
536} 537}
@@ -551,7 +552,7 @@ int ata_write_sectors(IF_MV2(int drive,)
551 long timeout; 552 long timeout;
552 tSDCardInfo *card = &card_info[current_card]; 553 tSDCardInfo *card = &card_info[current_card];
553 554
554 mutex_lock(&sd_mtx); 555 spinlock_lock(&sd_mtx);
555 ata_enable(true); 556 ata_enable(true);
556 ata_led(true); 557 ata_led(true);
557 if(current_card == 0) 558 if(current_card == 0)
@@ -607,7 +608,7 @@ retry:
607 sd_wait_for_state(card, TRAN); 608 sd_wait_for_state(card, TRAN);
608 ata_led(false); 609 ata_led(false);
609 ata_enable(false); 610 ata_enable(false);
610 mutex_unlock(&sd_mtx); 611 spinlock_unlock(&sd_mtx);
611 612
612 return ret; 613 return ret;
613} 614}
diff --git a/firmware/target/arm/sandisk/sansa-e200/audio-e200.c b/firmware/target/arm/sandisk/sansa-e200/audio-e200.c
new file mode 100644
index 0000000000..a3f3284b98
--- /dev/null
+++ b/firmware/target/arm/sandisk/sansa-e200/audio-e200.c
@@ -0,0 +1,103 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Michael Sevakis
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "system.h"
20#include "cpu.h"
21#include "audio.h"
22#include "sound.h"
23
24int audio_channels = 2;
25int audio_output_source = AUDIO_SRC_PLAYBACK;
26
27void audio_set_output_source(int source)
28{
29 int oldmode = set_fiq_status(FIQ_DISABLED);
30
31 if ((unsigned)source >= AUDIO_NUM_SOURCES)
32 source = AUDIO_SRC_PLAYBACK;
33
34 audio_output_source = source;
35
36 if (source != AUDIO_SRC_PLAYBACK)
37 IISCONFIG |= (1 << 29);
38
39 set_fiq_status(oldmode);
40} /* audio_set_output_source */
41
42void audio_set_source(int source, unsigned flags)
43{
44 static int last_source = AUDIO_SRC_PLAYBACK;
45#if 0
46 static bool last_recording = false;
47 bool recording = flags & SRCF_RECORDING;
48#endif
49 (void)flags;
50
51 switch (source)
52 {
53 default: /* playback - no recording */
54 source = AUDIO_SRC_PLAYBACK;
55 case AUDIO_SRC_PLAYBACK:
56 audio_channels = 2;
57 if (source != last_source)
58 {
59 audiohw_set_monitor(false);
60 audiohw_disable_recording();
61 }
62 break;
63
64 case AUDIO_SRC_MIC: /* recording only */
65 audio_channels = 1;
66 if (source != last_source)
67 {
68 audiohw_set_monitor(false);
69 audiohw_enable_recording(true); /* source mic */
70 }
71 break;
72
73#if 0
74 case AUDIO_SRC_FMRADIO: /* recording and playback */
75 audio_channels = 2;
76
77 if (!recording)
78 audiohw_set_recvol(23, 23, AUDIO_GAIN_LINEIN);
79
80 if (source == last_source && recording == last_recording)
81 break;
82
83 last_recording = recording;
84
85 if (recording)
86 {
87 audiohw_set_monitor(false);
88 audiohw_enable_recording(false);
89 }
90 else
91 {
92 audiohw_disable_recording();
93 audiohw_set_monitor(true); /* line 1 analog audio path */
94 }
95
96 break;
97#endif
98 } /* end switch */
99
100 last_source = source;
101} /* audio_set_source */
102
103