summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-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