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 @@
42 42
43static volatile int locked = 0; 43static volatile int locked = 0;
44size_t nextsize; 44size_t nextsize;
45size_t dblbufsize;
45int dmamode; 46int dmamode;
46unsigned char* dblbuf; 47const unsigned char* dblbuf;
47 48
48/* table of recommended PLL/MCLK dividers for mode 256Fs from the datasheet */ 49/* table of recommended PLL/MCLK dividers for mode 256Fs from the datasheet */
49static const struct div_entry { 50static const struct div_entry {
@@ -96,8 +97,8 @@ void pcm_play_unlock(void)
96 } 97 }
97} 98}
98 99
99static void* dma_callback(void) ICODE_ATTR __attribute__((unused)); 100static const void* dma_callback(void) ICODE_ATTR __attribute__((unused));
100static void* dma_callback(void) 101static const void* dma_callback(void)
101{ 102{
102 if (dmamode) 103 if (dmamode)
103 { 104 {
@@ -106,9 +107,10 @@ static void* dma_callback(void)
106 if (get_more) 107 if (get_more)
107 { 108 {
108 get_more(&dma_start_addr, &nextsize); 109 get_more(&dma_start_addr, &nextsize);
109 if (nextsize > 4096) 110 if (nextsize >= 4096)
110 { 111 {
111 nextsize = nextsize - 2048; 112 dblbufsize = nextsize >> 4;
113 nextsize = nextsize - dblbufsize;
112 dblbuf = dma_start_addr + nextsize; 114 dblbuf = dma_start_addr + nextsize;
113 dmamode = 0; 115 dmamode = 0;
114 } 116 }
@@ -125,7 +127,7 @@ static void* dma_callback(void)
125 else 127 else
126 { 128 {
127 dmamode = 1; 129 dmamode = 1;
128 nextsize = 1023; 130 nextsize = (dblbufsize >> 1) - 1;
129 return dblbuf; 131 return dblbuf;
130 } 132 }
131} 133}
@@ -180,8 +182,10 @@ void bootstrap_fiq(const void* addr, size_t tcnt)
180 ); 182 );
181} 183}
182 184
183void pcm_play_dma_start(const void *addr, size_t size) 185void pcm_play_dma_start(const void *addr_in, size_t size)
184{ 186{
187 unsigned char* addr = (unsigned char*)addr_in;
188
185 /* S1: DMA channel 0 set */ 189 /* S1: DMA channel 0 set */
186 DMACON0 = (0 << 30) | /* DEVSEL */ 190 DMACON0 = (0 << 30) | /* DEVSEL */
187 (1 << 29) | /* DIR */ 191 (1 << 29) | /* DIR */
@@ -221,10 +225,23 @@ void pcm_play_dma_start(const void *addr, size_t size)
221#endif 225#endif
222 226
223 /* S3: DMA channel 0 on */ 227 /* S3: DMA channel 0 on */
228 if (!size)
229 {
230 register pcm_more_callback_type get_more = pcm_callback_for_more;
231 if (get_more) get_more(&addr, &size);
232 else return; /* Nothing to play!? */
233 }
234 if (!size) return; /* Nothing to play!? */
224 clean_dcache(); 235 clean_dcache();
225 dmamode = 0; 236 if (size >= 4096)
226 dblbuf = (unsigned char*)addr + size - 2048; 237 {
227 bootstrap_fiq(addr, (size >> 1) - 1025); 238 dblbufsize = size >> 4;
239 size = size - dblbufsize;
240 dblbuf = addr + size;
241 dmamode = 0;
242 }
243 else dmamode = 1;
244 bootstrap_fiq(addr, (size >> 1) - 1);
228 245
229 /* S4: IIS Tx clock on */ 246 /* S4: IIS Tx clock on */
230 I2SCLKCON = (1 << 0); /* 1 = power on */ 247 I2SCLKCON = (1 << 0); /* 1 = power on */
@@ -319,7 +336,7 @@ void pcm_dma_apply_settings(void)
319 336
320size_t pcm_get_bytes_waiting(void) 337size_t pcm_get_bytes_waiting(void)
321{ 338{
322 return (DMACTCNT0 + 1) << 1; 339 return (nextsize + DMACTCNT0 + 2) << 1;
323} 340}
324 341
325const void * pcm_play_dma_get_peak_buffer(int *count) 342const void * pcm_play_dma_get_peak_buffer(int *count)