summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/export/pp5020.h14
-rw-r--r--firmware/target/arm/i2s-pp.c7
-rw-r--r--firmware/target/arm/pcm-pp.c51
3 files changed, 56 insertions, 16 deletions
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h
index 981ab318c5..2f49c50bad 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -311,7 +311,9 @@
#define IISCONFIG (*(volatile unsigned long*)(0x70002800))
#define IISFIFO_CFG (*(volatile unsigned long*)(0x7000280c))
#define IISFIFO_WR (*(volatile unsigned long*)(0x70002840))
+#define IISFIFO_WRH (*(volatile unsigned short*)(0x70002840))
#define IISFIFO_RD (*(volatile unsigned long*)(0x70002880))
+#define IISFIFO_RDH (*(volatile unsigned short*)(0x70002880))
/**
* IISCONFIG bits:
@@ -350,16 +352,16 @@
/* Other sizes not yet known */
/* Data size/format on IIS FIFO */
-#define IIS_FIFO_FORMAT_MASK (0x7 << 4)
-#define IIS_FIFO_FORMAT_0 (0x0 << 4)
+#define IIS_FIFO_FORMAT_MASK (0x7 << 4)
+#define IIS_FIFO_FORMAT_LE_HALFWORD (0x0 << 4)
/* Big-endian formats - data sent to the FIFO must be big endian.
* I forgot which is which size but did test them. */
-#define IIS_FIFO_FORMAT_1 (0x1 << 4)
-#define IIS_FIFO_FORMAT_2 (0x2 << 4)
+#define IIS_FIFO_FORMAT_1 (0x1 << 4)
+#define IIS_FIFO_FORMAT_2 (0x2 << 4)
/* 32bit-MSB-little endian */
-#define IIS_FIFO_FORMAT_LE32 (0x3 << 4)
+#define IIS_FIFO_FORMAT_LE32 (0x3 << 4)
/* 16bit-MSB-little endian */
-#define IIS_FIFO_FORMAT_LE16 (0x4 << 4)
+#define IIS_FIFO_FORMAT_LE16 (0x4 << 4)
/* FIFO formats 0x5 and above seem equivalent to 0x4 ?? */
diff --git a/firmware/target/arm/i2s-pp.c b/firmware/target/arm/i2s-pp.c
index 24d901a4c1..09170c818b 100644
--- a/firmware/target/arm/i2s-pp.c
+++ b/firmware/target/arm/i2s-pp.c
@@ -57,10 +57,9 @@ void i2s_reset(void)
IISCONFIG &= ~IIS_RESET;
/* BIT.FORMAT */
- IISCONFIG = ((IISCONFIG & ~IIS_FORMAT_MASK) | IIS_FORMAT_IIS);
-
- /* BIT.SIZE */
IISCONFIG = ((IISCONFIG & ~IIS_SIZE_MASK) | IIS_SIZE_16BIT);
+ /* BIT.SIZE */
+ IISCONFIG = ((IISCONFIG & ~IIS_FORMAT_MASK) | IIS_FORMAT_IIS);
/* FIFO.FORMAT */
/* If BIT.SIZE < FIFO.FORMAT low bits will be 0 */
@@ -71,6 +70,8 @@ void i2s_reset(void)
outl((inl(0x70002808) & ~(0x1ff)) | 33, 0x70002808);
outl(7, 0x60006080);
IISCONFIG = ((IISCONFIG & ~IIS_FIFO_FORMAT_MASK) | IIS_FIFO_FORMAT_LE16);
+#elif defined (IRIVER_H10) || defined (IRIVER_H10_5GB)
+ IISCONFIG = ((IISCONFIG & ~IIS_FIFO_FORMAT_MASK) | IIS_FIFO_FORMAT_LE_HALFWORD);
#else
IISCONFIG = ((IISCONFIG & ~IIS_FIFO_FORMAT_MASK) | IIS_FIFO_FORMAT_LE32);
#endif
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index 50e5b272aa..119c54d71b 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -25,12 +25,22 @@
/** DMA **/
-#if defined(HAVE_AS3514)
-/* E200 uses 16bit FIFO - all others should be able to as well -
- i2s-pp.c has to set the right size as well */
-#define SAMPLE_SIZE 16
+/* List of transfer settings. Defined by player in order to have an inventory
+ of working settings. DMA-compatible settings should be found for here, i2s,
+ and codec setup using "arithmetic" the hardware supports like halfword
+ swapping. Try to use 32-bit packed in IIS modes if possible. */
+#if defined(SANSA_C200) || defined(SANSA_E200)
+/* 16-bit, L-R packed into 32 bits with left in the least significant halfword */
+#define SAMPLE_SIZE 16
+#define TRANSFER_SIZE 32
+#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
+/* 16-bit, one left 16-bit sample followed by one right 16-bit sample */
+#define SAMPLE_SIZE 16
+#define TRANSFER_SIZE 16
#else
-#define SAMPLE_SIZE 32
+/* 32-bit, one left 32-bit sample followed by one right 32-bit sample */
+#define SAMPLE_SIZE 32
+#define TRANSFER_SIZE 32
#endif
struct dma_data
@@ -38,7 +48,11 @@ struct dma_data
/* NOTE: The order of size and p is important if you use assembler
optimised fiq handler, so don't change it. */
#if SAMPLE_SIZE == 16
+#if TRANSFER_SIZE == 16
+ uint16_t *p;
+#elif TRANSFER_SIZE == 32
uint32_t *p;
+#endif
#elif SAMPLE_SIZE == 32
uint16_t *p;
#endif
@@ -122,10 +136,18 @@ void fiq_playback(void)
"ldr r12, [r10, %[cfg]] \n" /* read IISFIFO_CFG to check FIFO status */
"ands r12, r12, %[mask] \n"
"beq .exit \n" /* FIFO full, exit */
- "ldr r12, [r8], #4 \n" /* load two samples */
#if SAMPLE_SIZE == 16
+#if TRANSFER_SIZE == 16
+ "ldrh r12, [r8], #2 \n" /* Load left channel */
+ "strh r12, [r10, %[wr]] \n" /* Store it */
+ "ldrh r12, [r8], #2 \n" /* Load right channel */
+ "strh r12, [r10, %[wr]] \n" /* Store it */
+#elif TRANSFER_SIZE == 32
+ "ldr r12, [r8], #4 \n" /* load two samples */
"str r12, [r10, %[wr]] \n" /* write them */
+#endif
#elif SAMPLE_SIZE == 32
+ "ldr r12, [r8], #4 \n" /* load two samples */
"mov r12, r12, ror #16 \n" /* put left sample at the top bits */
"str r12, [r10, %[wr]] \n" /* write top sample, lower sample ignored */
"mov r12, r12, lsl #16 \n" /* shift lower sample up */
@@ -181,7 +203,12 @@ void fiq_playback(void)
return;
}
#if SAMPLE_SIZE == 16
- IISFIFO_WR = *dma_play_data.p++;
+#if TRANSFER_SIZE == 16
+ IISFIFO_WRH = *dma_play_data.p++;
+ IISFIFO_WRH = *dma_play_data.p++;
+#elif TRANSFER_SIZE == 32
+ IISFIFO_WR = *dma_play_data.p++;
+#endif
#elif SAMPLE_SIZE == 32
IISFIFO_WR = *dma_play_data.p++ << 16;
IISFIFO_WR = *dma_play_data.p++ << 16;
@@ -244,7 +271,12 @@ static void play_start_pcm(void)
}
#if SAMPLE_SIZE == 16
+#if TRANSFER_SIZE == 16
+ IISFIFO_WRH = *dma_play_data.p++;
+ IISFIFO_WRH = *dma_play_data.p++;
+#elif TRANSFER_SIZE == 32
IISFIFO_WR = *dma_play_data.p++;
+#endif
#elif SAMPLE_SIZE == 32
IISFIFO_WR = *dma_play_data.p++ << 16;
IISFIFO_WR = *dma_play_data.p++ << 16;
@@ -461,7 +493,12 @@ void fiq_record(void)
}
#if SAMPLE_SIZE == 16
+#if TRANSFER_SIZE == 16
+ *dma_rec_data.p++ = IISFIFO_RDH;
+ *dma_rec_data.p++ = IISFIFO_RDH;
+#elif TRANSFER_SIZE == 32
*dma_rec_data.p++ = IISFIFO_RD;
+#endif
#elif SAMPLE_SIZE == 32
*dma_rec_data.p++ = IISFIFO_RD >> 16;
*dma_rec_data.p++ = IISFIFO_RD >> 16;