summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s5l8700/pcm-s5l8700.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s5l8700/pcm-s5l8700.c')
-rw-r--r--firmware/target/arm/s5l8700/pcm-s5l8700.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/firmware/target/arm/s5l8700/pcm-s5l8700.c b/firmware/target/arm/s5l8700/pcm-s5l8700.c
index aeb3912cfb..5fd5c424ab 100644
--- a/firmware/target/arm/s5l8700/pcm-s5l8700.c
+++ b/firmware/target/arm/s5l8700/pcm-s5l8700.c
@@ -42,8 +42,9 @@
static volatile int locked = 0;
size_t nextsize;
+size_t dblbufsize;
int dmamode;
-unsigned char* dblbuf;
+const unsigned char* dblbuf;
/* table of recommended PLL/MCLK dividers for mode 256Fs from the datasheet */
static const struct div_entry {
@@ -96,8 +97,8 @@ void pcm_play_unlock(void)
}
}
-static void* dma_callback(void) ICODE_ATTR __attribute__((unused));
-static void* dma_callback(void)
+static const void* dma_callback(void) ICODE_ATTR __attribute__((unused));
+static const void* dma_callback(void)
{
if (dmamode)
{
@@ -106,9 +107,10 @@ static void* dma_callback(void)
if (get_more)
{
get_more(&dma_start_addr, &nextsize);
- if (nextsize > 4096)
+ if (nextsize >= 4096)
{
- nextsize = nextsize - 2048;
+ dblbufsize = nextsize >> 4;
+ nextsize = nextsize - dblbufsize;
dblbuf = dma_start_addr + nextsize;
dmamode = 0;
}
@@ -125,7 +127,7 @@ static void* dma_callback(void)
else
{
dmamode = 1;
- nextsize = 1023;
+ nextsize = (dblbufsize >> 1) - 1;
return dblbuf;
}
}
@@ -180,8 +182,10 @@ void bootstrap_fiq(const void* addr, size_t tcnt)
);
}
-void pcm_play_dma_start(const void *addr, size_t size)
+void pcm_play_dma_start(const void *addr_in, size_t size)
{
+ unsigned char* addr = (unsigned char*)addr_in;
+
/* S1: DMA channel 0 set */
DMACON0 = (0 << 30) | /* DEVSEL */
(1 << 29) | /* DIR */
@@ -221,10 +225,23 @@ void pcm_play_dma_start(const void *addr, size_t size)
#endif
/* S3: DMA channel 0 on */
+ if (!size)
+ {
+ register pcm_more_callback_type get_more = pcm_callback_for_more;
+ if (get_more) get_more(&addr, &size);
+ else return; /* Nothing to play!? */
+ }
+ if (!size) return; /* Nothing to play!? */
clean_dcache();
- dmamode = 0;
- dblbuf = (unsigned char*)addr + size - 2048;
- bootstrap_fiq(addr, (size >> 1) - 1025);
+ if (size >= 4096)
+ {
+ dblbufsize = size >> 4;
+ size = size - dblbufsize;
+ dblbuf = addr + size;
+ dmamode = 0;
+ }
+ else dmamode = 1;
+ bootstrap_fiq(addr, (size >> 1) - 1);
/* S4: IIS Tx clock on */
I2SCLKCON = (1 << 0); /* 1 = power on */
@@ -319,7 +336,7 @@ void pcm_dma_apply_settings(void)
size_t pcm_get_bytes_waiting(void)
{
- return (DMACTCNT0 + 1) << 1;
+ return (nextsize + DMACTCNT0 + 2) << 1;
}
const void * pcm_play_dma_get_peak_buffer(int *count)