summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
authorDaniel Ankers <dan@weirdo.org.uk>2007-03-11 17:38:08 +0000
committerDaniel Ankers <dan@weirdo.org.uk>2007-03-11 17:38:08 +0000
commitdfad406aa14a735b2cd071d8d399c79be0f98e43 (patch)
tree2993687589af53e570e27e6a025fe1c24b8f1a96 /firmware/target
parente21d21720556bb069f7ceb5669c5b693138838bb (diff)
Sound for Sansa E200 - based on work by myself, Rene Peinthor, Barry Wardell and Christian Gmeiner from the AS3514 datasheet.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12727 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/i2s-pp.c6
-rw-r--r--firmware/target/arm/pcm-pp.c67
2 files changed, 38 insertions, 35 deletions
diff --git a/firmware/target/arm/i2s-pp.c b/firmware/target/arm/i2s-pp.c
index af698fddd6..a2a74bf72b 100644
--- a/firmware/target/arm/i2s-pp.c
+++ b/firmware/target/arm/i2s-pp.c
@@ -84,6 +84,12 @@ void i2s_reset(void)
/* FIFO.FORMAT */
/* If BIT.SIZE < FIFO.FORMAT low bits will be 0 */
IISCONFIG = ((IISCONFIG & ~FIFO_FORMAT_MASK) | FIFO_FORMAT_32LSB);
+#ifdef HAVE_AS3514
+ /* AS3514 can only operate as I2S Slave */
+ IISCONFIG |= I2S_MASTER;
+ /* Set I2S to 44.1kHz */
+ outl((inl(0x70002808) & ~(0x1ff)) | 271, 0x70002808);
+#endif
/* RX_ATN_LVL=1 == when 12 slots full */
/* TX_ATN_LVL=1 == when 12 slots empty */
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index efe6c9b4e6..6ecc3dae31 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -30,12 +30,10 @@ static int rec_peak_left, rec_peak_right;
#endif
/** DMA **/
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
#define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x3f000000) >> 24)
#elif CONFIG_CPU == PP5002
#define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x7800000) >> 23)
-#elif CONFIG_CPU == PP5024
-#define FIFO_FREE_COUNT 4 /* TODO: make this sensible */
#endif
/****************************************************************************
@@ -54,7 +52,7 @@ size_t p_size IBSS_ATTR;
actually needs to do so when calling pcm_callback_for_more. C version is
still included below for reference.
*/
-#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
+#ifdef CPU_PP
void fiq(void) ICODE_ATTR __attribute__((naked));
void fiq(void)
{
@@ -94,10 +92,20 @@ void fiq(void)
#endif
"bls .fifo_full \n\t" /* FIFO full, exit */
"ldr r10, [r9], #4 \n\t" /* load two samples */
+#ifdef HAVE_AS3514
+ /* The AS3514 reads 3 bytes at a time, it seems, ignoring the lowest.
+ This code seems to work well, but we may have to mask off the extra
+ bits - at the expense of a few extra cycles in the FIQ */
+ "mov r10, r10, ror #2\n\t" /* put left sample at the top bits */
+ "str r10, [r12, #0x40]\n\t" /* write top sample, lower sample ignored */
+ "mov r10, r10, ror #16\n\t" /* put left sample at the top bits */
+ "str r10, [r12, #0x40]\n\t" /* then write it */
+#else
"mov r10, r10, ror #16\n\t" /* put left sample at the top bits */
"str r10, [r12, #0x40]\n\t" /* write top sample, lower sample ignored */
"mov r10, r10, lsl #16\n\t" /* shift lower sample up */
"str r10, [r12, #0x40]\n\t" /* then write it */
+#endif
"subs r8, r8, #4 \n\t" /* check if we have more samples */
"bne .fifo_loop \n\t" /* yes, continue */
".more_data: \n\t"
@@ -155,7 +163,7 @@ void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
void fiq(void)
{
/* Clear interrupt */
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
IISCONFIG &= ~0x2;
#elif CONFIG_CPU == PP5002
inl(0xcf001040);
@@ -166,7 +174,7 @@ void fiq(void)
while (p_size) {
if (FIFO_FREE_COUNT < 2) {
/* Enable interrupt */
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
IISCONFIG |= 0x2;
#elif CONFIG_CPU == PP5002
IISFIFO_CFG |= (1<<9);
@@ -197,10 +205,9 @@ void pcm_play_dma_start(const void *addr, size_t size)
pcm_playing = true;
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
CPU_INT_PRIORITY |= I2S_MASK; /* FIQ priority for I2S */
CPU_INT_EN = I2S_MASK; /* Enable I2S interrupt */
-#elif CONFIG_CPU == PP5024
#else
/* setup I2S interrupt for FIQ */
outl(inl(0xcf00102c) | DMA_OUT_MASK, 0xcf00102c);
@@ -212,7 +219,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
enable_fiq();
/* Enable playback FIFO */
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
IISCONFIG |= 0x20000000;
#elif CONFIG_CPU == PP5002
IISCONFIG |= 0x4;
@@ -223,7 +230,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
while (p_size > 0) {
if (FIFO_FREE_COUNT < 2) {
/* Enable interrupt */
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
IISCONFIG |= 0x2;
#elif CONFIG_CPU == PP5002
IISFIFO_CFG |= (1<<9);
@@ -242,7 +249,7 @@ void pcm_play_dma_stop(void)
{
pcm_playing = false;
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
/* Disable playback FIFO */
IISCONFIG &= ~0x20000000;
@@ -264,7 +271,7 @@ void pcm_play_dma_stop(void)
void pcm_play_pause_pause(void)
{
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
/* Disable the interrupt */
IISCONFIG &= ~0x2;
/* Disable playback FIFO */
@@ -286,7 +293,7 @@ void pcm_play_pause_unpause(void)
enable_fiq();
/* Enable playback FIFO */
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
IISCONFIG |= 0x20000000;
#elif CONFIG_CPU == PP5002
IISCONFIG |= 0x4;
@@ -297,7 +304,7 @@ void pcm_play_pause_unpause(void)
while (p_size > 0) {
if (FIFO_FREE_COUNT < 2) {
/* Enable interrupt */
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
IISCONFIG |= 0x2;
#elif CONFIG_CPU == PP5002
IISFIFO_CFG |= (1<<9);
@@ -322,14 +329,6 @@ size_t pcm_get_bytes_waiting(void)
return p_size;
}
-#ifdef HAVE_PP5024_CODEC
-void pcm_init(void)
-{
-}
-void pcm_postinit(void)
-{
-}
-#else
void pcm_init(void)
{
pcm_playing = false;
@@ -338,7 +337,7 @@ void pcm_init(void)
/* Initialize default register values. */
audiohw_init();
-
+
/* Power on */
audiohw_enable_output(true);
@@ -353,8 +352,6 @@ void pcm_postinit(void)
{
audiohw_postinit();
}
-#endif /* HAVE_PP5024_CODEC */
-
/****************************************************************************
** Recording DMA transfer
@@ -370,7 +367,7 @@ void fiq_record(void)
int status = 0;
/* Clear interrupt */
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
IISCONFIG &= ~0x01;
#elif CONFIG_CPU == PP5002
/* TODO */
@@ -379,7 +376,7 @@ void fiq_record(void)
while (p_size > 0) {
if (FIFO_FREE_COUNT < 2) {
/* enable interrupt */
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
IISCONFIG |= 0x01;
#elif CONFIG_CPU == PP5002
/* TODO */
@@ -405,7 +402,7 @@ void fiq_record(void)
peak_l = peak_r = 0;
}
}
-
+
more_ready = pcm_callback_more_ready;
if (more_ready != NULL && more_ready(status) >= 0)
@@ -421,7 +418,7 @@ void pcm_record_more(void *start, size_t size)
rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */
p = start;
p_size = size; /* Bytes to transfer */
-#if CONFIG_CPU == PP5020
+#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
IISCONFIG |= 0x01;
#elif CONFIG_CPU == PP5002
/* TODO */
@@ -431,12 +428,12 @@ void pcm_record_more(void *start, size_t size)
void pcm_rec_dma_stop(void)
{
logf("pcm_rec_dma_stop");
-
+
/* disable fifo */
IISCONFIG &= ~0x10000000;
disable_fiq();
-
+
pcm_recording = false;
}
@@ -445,11 +442,11 @@ void pcm_rec_dma_start(void *addr, size_t size)
logf("pcm_rec_dma_start");
pcm_recording = true;
-
+
peak_l = peak_r = 0;
p_size = size;
p = addr;
-
+
/* setup FIQ */
CPU_INT_PRIORITY |= I2S_MASK;
CPU_INT_EN = I2S_MASK;
@@ -470,7 +467,7 @@ void pcm_close_recording(void)
pcm_rec_dma_stop();
-#if (CONFIG_CPU == PP5020)
+#if (CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024)
disable_fiq();
/* disable fifo */
@@ -488,7 +485,7 @@ void pcm_init_recording(void)
pcm_recording = false;
pcm_callback_more_ready = NULL;
-#if (CONFIG_CPU == PP5020)
+#if (CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024)
#if defined(IPOD_COLOR) || defined (IPOD_4G)
/* The usual magic from IPL - I'm guessing this configures the headphone
socket to be input or output - in this case, input. */