diff options
Diffstat (limited to 'firmware/target/arm/pcm-telechips.c')
-rw-r--r-- | firmware/target/arm/pcm-telechips.c | 62 |
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 | ||
144 | void pcm_play_dma_start(const void *addr, size_t size) | 149 | void 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 | ||