summaryrefslogtreecommitdiff
path: root/firmware/target/arm/pcm-telechips.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/pcm-telechips.c')
-rw-r--r--firmware/target/arm/pcm-telechips.c62
1 files changed, 34 insertions, 28 deletions
diff --git a/firmware/target/arm/pcm-telechips.c b/firmware/target/arm/pcm-telechips.c
index ae4aa5ef38..3d62fcd1a9 100644
--- a/firmware/target/arm/pcm-telechips.c
+++ b/firmware/target/arm/pcm-telechips.c
@@ -33,7 +33,12 @@ struct dma_data
33{ 33{
34/* NOTE: The order of size and p is important if you use assembler 34/* NOTE: The order of size and p is important if you use assembler
35 optimised fiq handler, so don't change it. */ 35 optimised fiq handler, so don't change it. */
36 uint16_t *p; 36 union
37 {
38 uint16_t *p;
39 const void *p_r;
40 void *p_w;
41 };
37 size_t size; 42 size_t size;
38#if NUM_CORES > 1 43#if NUM_CORES > 1
39 unsigned core; 44 unsigned core;
@@ -143,7 +148,7 @@ static void play_stop_pcm(void)
143 148
144void pcm_play_dma_start(const void *addr, size_t size) 149void pcm_play_dma_start(const void *addr, size_t size)
145{ 150{
146 dma_play_data.p = (uint16_t*)addr; 151 dma_play_data.p_r = addr;
147 dma_play_data.size = size; 152 dma_play_data.size = size;
148 153
149#if NUM_CORES > 1 154#if NUM_CORES > 1
@@ -248,8 +253,9 @@ void fiq_handler(void)
248 * r0-r3 and r12 is a working register. 253 * r0-r3 and r12 is a working register.
249 */ 254 */
250 asm volatile ( 255 asm volatile (
251 "stmfd sp!, { r0-r4, lr } \n" /* stack scratch regs and lr */ 256 "sub lr, lr, #4 \n"
252 "mov r4, #0 \n" /* Was the callback called? */ 257 "stmfd sp!, { r0-r3, lr } \n" /* stack scratch regs and lr */
258 "mov r14, #0 \n" /* Was the callback called? */
253#if defined(CPU_TCC780X) 259#if defined(CPU_TCC780X)
254 "mov r8, #0xc000 \n" /* DAI_TX_IRQ_MASK | DAI_RX_IRQ_MASK */ 260 "mov r8, #0xc000 \n" /* DAI_TX_IRQ_MASK | DAI_RX_IRQ_MASK */
255 "ldr r9, =0xf3001004 \n" /* CREQ */ 261 "ldr r9, =0xf3001004 \n" /* CREQ */
@@ -260,7 +266,7 @@ void fiq_handler(void)
260 "str r8, [r9] \n" /* clear DAI IRQs */ 266 "str r8, [r9] \n" /* clear DAI IRQs */
261 "ldmia r11, { r8-r9 } \n" /* r8 = p, r9 = size */ 267 "ldmia r11, { r8-r9 } \n" /* r8 = p, r9 = size */
262 "cmp r9, #0x10 \n" /* is size <16? */ 268 "cmp r9, #0x10 \n" /* is size <16? */
263 "blt .more_data \n" /* if so, ask pcmbuf for more data */ 269 "blo .more_data \n" /* if so, ask pcmbuf for more data */
264 270
265 ".fill_fifo: \n" 271 ".fill_fifo: \n"
266 "ldr r12, [r8], #4 \n" /* load two samples */ 272 "ldr r12, [r8], #4 \n" /* load two samples */
@@ -282,29 +288,30 @@ void fiq_handler(void)
282 "sub r9, r9, #0x10 \n" /* 4 words written */ 288 "sub r9, r9, #0x10 \n" /* 4 words written */
283 "stmia r11, { r8-r9 } \n" /* save p and size */ 289 "stmia r11, { r8-r9 } \n" /* save p and size */
284 290
285 "cmp r4, #0 \n" /* Callback called? */ 291 "cmp r14, #0 \n" /* Callback called? */
286 "beq .exit \n" 292 "ldmeqfd sp!, { r0-r3, pc }^ \n" /* no? -> exit */
287 /* "mov r4, #0 \n" If get_more could be called multiple times! */
288 "ldr r2, =pcm_play_dma_started\n"
289 "ldr r2, [r2] \n"
290 "cmp r2, #0 \n"
291 "blxne r2 \n"
292 293
293 ".exit: \n" 294 "ldr r1, =pcm_play_status_callback \n"
294 "ldmfd sp!, { r0-r4, lr } \n" 295 "ldr r1, [r1] \n"
295 "subs pc, lr, #4 \n" /* FIQ specific return sequence */ 296 "cmp r1, #0 \n"
297 "movne r0, %1 \n"
298 "blxne r1 \n"
299 "ldmfd sp!, { r0-r3, pc }^ \n" /* exit */
296 300
297 ".more_data: \n" 301 ".more_data: \n"
298 "mov r4, #1 \n" /* Remember we got more data in this FIQ */ 302 "mov r14, #1 \n" /* Remember we got more data in this FIQ */
299 "ldr r2, =pcm_play_get_more_callback \n" 303 "mov r0, %0 \n" /* r0 = status */
300 "mov r0, r11 \n" /* r0 = &p */ 304 "mov r1, r11 \n" /* r1 = &dma_play_data.p_r */
301 "add r1, r11, #4 \n" /* r1 = &size */ 305 "add r2, r11, #4 \n" /* r2 = &dma_play_data.size */
302 "blx r2 \n" /* call pcm_play_get_more_callback */ 306 "mov lr, pc \n"
303 "ldmia r11, { r8-r9 } \n" /* load new p and size */ 307 "ldr pc, =pcm_play_dma_complete_callback \n"
304 "cmp r9, #0x10 \n" /* did we actually get enough data? */ 308 "cmp r0, #0 \n" /* any more to play? */
305 "bpl .fill_fifo \n" /* not stop and enough? refill */ 309 "ldmneia r11, { r8-r9 } \n" /* load new p and size */
306 "b .exit \n" 310 "cmpne r9, #0x0f \n" /* did we actually get enough data? */
311 "bhi .fill_fifo \n" /* not stop and enough? refill */
312 "ldmfd sp!, { r0-r3, pc }^ \n" /* exit */
307 ".ltorg \n" 313 ".ltorg \n"
314 : : "i"(PCM_DMAST_OK), "i"(PCM_DMAST_STARTED)
308 ); 315 );
309} 316}
310#else /* C version for reference */ 317#else /* C version for reference */
@@ -316,9 +323,8 @@ void fiq_handler(void)
316 if (dma_play_data.size < 16) 323 if (dma_play_data.size < 16)
317 { 324 {
318 /* p is empty, get some more data */ 325 /* p is empty, get some more data */
319 new_buffer = true; 326 new_buffer = pcm_play_dma_complete_callback(&dma_play_data.p_r,
320 pcm_play_get_more_callback((void**)&dma_play_data.p, 327 &dma_play_data.size);
321 &dma_play_data.size);
322 } 328 }
323 329
324 if (dma_play_data.size >= 16) 330 if (dma_play_data.size >= 16)
@@ -339,7 +345,7 @@ void fiq_handler(void)
339 CREQ = DAI_TX_IRQ_MASK | DAI_RX_IRQ_MASK; 345 CREQ = DAI_TX_IRQ_MASK | DAI_RX_IRQ_MASK;
340 346
341 if (new_buffer) 347 if (new_buffer)
342 pcm_play_dma_started_callback(); 348 pcm_play_dma_status_callback(PCM_DMAST_STARTED);
343} 349}
344#endif 350#endif
345 351