summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/as3525/pcm-as3525.c43
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c81
-rw-r--r--firmware/target/arm/pcm-pp.c83
-rw-r--r--firmware/target/arm/pcm-telechips.c43
-rw-r--r--firmware/target/arm/pnx0101/pcm-pnx0101.c7
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c34
-rw-r--r--firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c34
-rw-r--r--firmware/target/arm/s5l8700/pcm-s5l8700.c22
-rw-r--r--firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c15
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c63
-rw-r--r--firmware/target/hosted/sdl/pcm-sdl.c18
-rw-r--r--firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c21
12 files changed, 132 insertions, 332 deletions
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c
index cefca0fbe5..a2e3cfbf9f 100644
--- a/firmware/target/arm/as3525/pcm-as3525.c
+++ b/firmware/target/arm/as3525/pcm-as3525.c
@@ -74,18 +74,13 @@ static void dma_callback(void)
74{ 74{
75 if(!dma_size) 75 if(!dma_size)
76 { 76 {
77 register pcm_more_callback_type get_more = pcm_callback_for_more; 77 pcm_play_get_more_callback(&dma_start_addr, &dma_size);
78 if(get_more)
79 get_more(&dma_start_addr, &dma_size);
80 }
81 78
82 if(!dma_size) 79 if (!dma_size)
83 { 80 return;
84 pcm_play_dma_stop();
85 pcm_play_dma_stopped_callback();
86 } 81 }
87 else 82
88 play_start_pcm(); 83 play_start_pcm();
89} 84}
90 85
91void pcm_play_dma_start(const void *addr, size_t size) 86void pcm_play_dma_start(const void *addr, size_t size)
@@ -275,31 +270,19 @@ static void rec_dma_callback(void)
275 270
276 if(!rec_dma_size) 271 if(!rec_dma_size)
277 { 272 {
278 register pcm_more_callback_type2 more_ready = pcm_callback_more_ready; 273 pcm_rec_more_ready_callback(0, &rec_dma_start_addr, &rec_dma_size);
279 if (!more_ready || more_ready(0) < 0)
280 {
281 /* Finished recording */
282 pcm_rec_dma_stop();
283 pcm_rec_dma_stopped_callback();
284 return;
285 }
286 }
287
288 rec_dma_start();
289}
290
291 274
292void pcm_rec_dma_record_more(void *start, size_t size) 275 if(rec_dma_size != 0)
293{ 276 {
294 dump_dcache_range(start, size); 277 dump_dcache_range(rec_dma_start_addr, rec_dma_size);
295 rec_dma_start_addr = start;
296#if CONFIG_CPU == AS3525 278#if CONFIG_CPU == AS3525
297 mono_samples = AS3525_UNCACHED_ADDR(start); 279 mono_samples = AS3525_UNCACHED_ADDR(rec_dma_start_addr);
298#endif 280#endif
299 rec_dma_size = size; 281 rec_dma_start();
282 }
283 }
300} 284}
301 285
302
303void pcm_rec_dma_stop(void) 286void pcm_rec_dma_stop(void)
304{ 287{
305 dma_disable_channel(1); 288 dma_disable_channel(1);
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
index 02051fad90..2c65c70360 100644
--- a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
@@ -52,9 +52,9 @@ static struct dma_data dma_play_data =
52 52
53static void play_dma_callback(void) 53static void play_dma_callback(void)
54{ 54{
55 unsigned char *start; 55 void *start;
56 size_t size = 0; 56 size_t size;
57 pcm_more_callback_type get_more = pcm_callback_for_more; 57 bool rror;
58 58
59 if (dma_play_data.locked != 0) 59 if (dma_play_data.locked != 0)
60 { 60 {
@@ -63,28 +63,20 @@ static void play_dma_callback(void)
63 return; 63 return;
64 } 64 }
65 65
66 if (dma_play_bd.mode.status & BD_RROR) 66 rror = dma_play_bd.mode.status & BD_RROR;
67 { 67
68 /* Stop on error */ 68 pcm_play_get_more_callback(rror ? NULL : &start, &size);
69 } 69
70 else if (get_more != NULL && (get_more(&start, &size), size != 0)) 70 if (size == 0)
71 {
72 start = (void*)(((unsigned long)start + 3) & ~3);
73 size &= ~3;
74
75 /* Flush any pending cache writes */
76 clean_dcache_range(start, size);
77 dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)start);
78 dma_play_bd.mode.count = size;
79 dma_play_bd.mode.command = TRANSFER_16BIT;
80 dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
81 sdma_channel_run(DMA_PLAY_CH_NUM);
82 return; 71 return;
83 }
84 72
85 /* Error, callback missing or no more DMA to do */ 73 /* Flush any pending cache writes */
86 pcm_play_dma_stop(); 74 clean_dcache_range(start, size);
87 pcm_play_dma_stopped_callback(); 75 dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)start);
76 dma_play_bd.mode.count = size;
77 dma_play_bd.mode.command = TRANSFER_16BIT;
78 dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
79 sdma_channel_run(DMA_PLAY_CH_NUM);
88} 80}
89 81
90void pcm_play_lock(void) 82void pcm_play_lock(void)
@@ -272,12 +264,6 @@ void pcm_play_dma_start(const void *addr, size_t size)
272 SSI_STCR2 &= ~SSI_STCR_TFEN0; 264 SSI_STCR2 &= ~SSI_STCR_TFEN0;
273 SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); 265 SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN);
274 266
275 addr = (void *)(((unsigned long)addr + 3) & ~3);
276 size &= ~3;
277
278 if (size <= 0)
279 return;
280
281 if (!sdma_channel_reset(DMA_PLAY_CH_NUM)) 267 if (!sdma_channel_reset(DMA_PLAY_CH_NUM))
282 return; 268 return;
283 269
@@ -383,8 +369,9 @@ static struct dma_data dma_rec_data =
383 369
384static void rec_dma_callback(void) 370static void rec_dma_callback(void)
385{ 371{
386 pcm_more_callback_type2 more_ready;
387 int status = 0; 372 int status = 0;
373 void *start;
374 size_t size;
388 375
389 if (dma_rec_data.locked != 0) 376 if (dma_rec_data.locked != 0)
390 { 377 {
@@ -395,17 +382,22 @@ static void rec_dma_callback(void)
395 if (dma_rec_bd.mode.status & BD_RROR) 382 if (dma_rec_bd.mode.status & BD_RROR)
396 status = DMA_REC_ERROR_DMA; 383 status = DMA_REC_ERROR_DMA;
397 384
398 more_ready = pcm_callback_more_ready; 385 pcm_rec_more_ready_callback(status, &start, &size);
399 386
400 if (more_ready != NULL && more_ready(status) >= 0) 387 if (size == 0)
401 {
402 sdma_channel_run(DMA_REC_CH_NUM);
403 return; 388 return;
404 }
405 389
406 /* Finished recording */ 390 /* Invalidate - buffer must be coherent */
407 pcm_rec_dma_stop(); 391 dump_dcache_range(start, size);
408 pcm_rec_dma_stopped_callback(); 392
393 start = (void *)addr_virt_to_phys((unsigned long)start);
394
395 dma_rec_bd.buf_addr = start;
396 dma_rec_bd.mode.count = size;
397 dma_rec_bd.mode.command = TRANSFER_16BIT;
398 dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
399
400 sdma_channel_run(DMA_REC_CH_NUM);
409} 401}
410 402
411void pcm_rec_lock(void) 403void pcm_rec_lock(void)
@@ -432,19 +424,6 @@ void pcm_rec_unlock(void)
432 } 424 }
433} 425}
434 426
435void pcm_rec_dma_record_more(void *start, size_t size)
436{
437 /* Invalidate - buffer must be coherent */
438 dump_dcache_range(start, size);
439
440 start = (void *)addr_virt_to_phys((unsigned long)start);
441
442 dma_rec_bd.buf_addr = start;
443 dma_rec_bd.mode.count = size;
444 dma_rec_bd.mode.command = TRANSFER_16BIT;
445 dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
446}
447
448void pcm_rec_dma_stop(void) 427void pcm_rec_dma_stop(void)
449{ 428{
450 /* Stop receiving data */ 429 /* Stop receiving data */
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index e0b603c81f..6289b4c730 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -115,7 +115,6 @@ void pcm_dma_apply_settings(void)
115/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */ 115/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
116void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void) 116void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
117{ 117{
118 register pcm_more_callback_type get_more;
119 register size_t size; 118 register size_t size;
120 119
121 DMA0_STATUS; /* Clear any pending interrupt */ 120 DMA0_STATUS; /* Clear any pending interrupt */
@@ -141,15 +140,12 @@ void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
141 } 140 }
142 141
143 /* Buffer empty. Try to get more. */ 142 /* Buffer empty. Try to get more. */
144 get_more = pcm_callback_for_more; 143 pcm_play_get_more_callback((void **)&dma_play_data.addr,
145 if (get_more) { 144 &dma_play_data.size);
146 get_more((unsigned char **)&dma_play_data.addr, &dma_play_data.size);
147 dma_play_data.addr = (dma_play_data.addr + 2) & ~3;
148 dma_play_data.size &= ~3;
149 }
150 145
151 if (dma_play_data.size == 0) { 146 if (dma_play_data.size == 0) {
152 break; 147 /* No more data */
148 return;
153 } 149 }
154 150
155 if (dma_play_data.addr < UNCACHED_BASE_ADDR) { 151 if (dma_play_data.addr < UNCACHED_BASE_ADDR) {
@@ -158,10 +154,6 @@ void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
158 cpucache_flush(); 154 cpucache_flush();
159 } 155 }
160 } 156 }
161
162 /* Callback missing or no more DMA to do */
163 pcm_play_dma_stop();
164 pcm_play_dma_stopped_callback();
165} 157}
166#else 158#else
167/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by 159/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by
@@ -247,28 +239,16 @@ void fiq_playback(void)
247#endif 239#endif
248 240
249 ".more_data: \n" 241 ".more_data: \n"
250 "ldr r2, =pcm_callback_for_more \n" 242 "ldr r2, =pcm_play_get_more_callback \n"
251 "ldr r2, [r2] \n" /* get callback address */
252 "cmp r2, #0 \n" /* check for null pointer */
253 "beq .stop \n" /* callback removed, stop */
254 "stmia r11, { r8-r9 } \n" /* save internal copies of variables back */
255 "mov r0, r11 \n" /* r0 = &p */ 243 "mov r0, r11 \n" /* r0 = &p */
256 "add r1, r11, #4 \n" /* r1 = &size */ 244 "add r1, r11, #4 \n" /* r1 = &size */
257 "mov lr, pc \n" /* call pcm_callback_for_more */ 245 "mov lr, pc \n" /* call pcm_play_get_more_callback */
258 "bx r2 \n" 246 "bx r2 \n"
259 "ldmia r11, { r8-r9 } \n" /* reload p and size */ 247 "ldmia r11, { r8-r9 } \n" /* load new p and size */
260 "cmp r9, #0 \n" /* did we actually get more data? */ 248 "cmp r9, #0 \n"
261 "bne .check_fifo \n" 249 "bne .check_fifo \n" /* size != 0? refill */
262 250
263 ".stop: \n" /* call termination routines */ 251 ".exit: \n" /* (r9=0 if stopping, look above) */
264 "ldr r12, =pcm_play_dma_stop \n"
265 "mov lr, pc \n"
266 "bx r12 \n"
267 "ldr r12, =pcm_play_dma_stopped_callback \n"
268 "mov lr, pc \n"
269 "bx r12 \n"
270
271 ".exit: \n" /* (r8=0 if stopping, look above) */
272 "stmia r11, { r8-r9 } \n" /* save p and size */ 252 "stmia r11, { r8-r9 } \n" /* save p and size */
273 "ldmfd sp!, { r0-r3, lr } \n" 253 "ldmfd sp!, { r0-r3, lr } \n"
274 "subs pc, lr, #4 \n" /* FIQ specific return sequence */ 254 "subs pc, lr, #4 \n" /* FIQ specific return sequence */
@@ -284,8 +264,6 @@ void fiq_playback(void) __attribute__((interrupt ("FIQ"))) ICODE_ATTR;
284/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */ 264/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
285void fiq_playback(void) 265void fiq_playback(void)
286{ 266{
287 register pcm_more_callback_type get_more;
288
289#if CONFIG_CPU == PP5002 267#if CONFIG_CPU == PP5002
290 inl(0xcf001040); 268 inl(0xcf001040);
291#endif 269#endif
@@ -305,16 +283,11 @@ void fiq_playback(void)
305 } 283 }
306 284
307 /* p is empty, get some more data */ 285 /* p is empty, get some more data */
308 get_more = pcm_callback_for_more; 286 pcm_play_get_more_callback((void **)&dma_play_data.addr,
309 if (get_more) { 287 &dma_play_data.size);
310 get_more((unsigned char**)&dma_play_data.addr,
311 &dma_play_data.size);
312 }
313 } while (dma_play_data.size); 288 } while (dma_play_data.size);
314 289
315 /* No more data, so disable the FIFO/interrupt */ 290 /* No more data */
316 pcm_play_dma_stop();
317 pcm_play_dma_stopped_callback();
318} 291}
319#endif /* ASM / C selection */ 292#endif /* ASM / C selection */
320#endif /* CPU_PP502x */ 293#endif /* CPU_PP502x */
@@ -589,7 +562,6 @@ void fiq_record(void) ICODE_ATTR __attribute__((interrupt ("FIQ")));
589#if defined(SANSA_C200) || defined(SANSA_E200) 562#if defined(SANSA_C200) || defined(SANSA_E200)
590void fiq_record(void) 563void fiq_record(void)
591{ 564{
592 register pcm_more_callback_type2 more_ready;
593 register int32_t value; 565 register int32_t value;
594 566
595 if (audio_channels == 2) { 567 if (audio_channels == 2) {
@@ -648,20 +620,13 @@ void fiq_record(void)
648 } 620 }
649 } 621 }
650 622
651 more_ready = pcm_callback_more_ready; 623 pcm_rec_more_ready_callback(0, (void *)&dma_rec_data.addr,
652 624 &dma_rec_data.size);
653 if (more_ready == NULL || more_ready(0) < 0) {
654 /* Finished recording */
655 pcm_rec_dma_stop();
656 pcm_rec_dma_stopped_callback();
657 }
658} 625}
659 626
660#else 627#else
661void fiq_record(void) 628void fiq_record(void)
662{ 629{
663 register pcm_more_callback_type2 more_ready;
664
665 while (dma_rec_data.size > 0) { 630 while (dma_rec_data.size > 0) {
666 if (IIS_RX_FULL_COUNT < 2) { 631 if (IIS_RX_FULL_COUNT < 2) {
667 return; 632 return;
@@ -676,24 +641,12 @@ void fiq_record(void)
676 dma_rec_data.size -= 4; 641 dma_rec_data.size -= 4;
677 } 642 }
678 643
679 more_ready = pcm_callback_more_ready; 644 pcm_rec_more_ready_callback(0, (void *)&dma_rec_data.addr,
680 645 &dma_rec_data.size);
681 if (more_ready == NULL || more_ready(0) < 0) {
682 /* Finished recording */
683 pcm_rec_dma_stop();
684 pcm_rec_dma_stopped_callback();
685 }
686} 646}
687 647
688#endif /* SANSA_E200 */ 648#endif /* SANSA_E200 */
689 649
690/* Continue transferring data in */
691void pcm_rec_dma_record_more(void *start, size_t size)
692{
693 dma_rec_data.addr = (unsigned long)start; /* Start of RX buffer */
694 dma_rec_data.size = size; /* Bytes to transfer */
695}
696
697void pcm_rec_dma_stop(void) 650void pcm_rec_dma_stop(void)
698{ 651{
699 /* disable interrupt */ 652 /* disable interrupt */
diff --git a/firmware/target/arm/pcm-telechips.c b/firmware/target/arm/pcm-telechips.c
index 3ce038ffcd..d718ca38ac 100644
--- a/firmware/target/arm/pcm-telechips.c
+++ b/firmware/target/arm/pcm-telechips.c
@@ -233,12 +233,6 @@ const void * pcm_rec_dma_get_peak_buffer(void)
233{ 233{
234 return NULL; 234 return NULL;
235} 235}
236
237void pcm_record_more(void *start, size_t size)
238{
239 (void) start;
240 (void) size;
241}
242#endif 236#endif
243 237
244#if defined(CPU_TCC77X) || defined(CPU_TCC780X) 238#if defined(CPU_TCC77X) || defined(CPU_TCC780X)
@@ -289,21 +283,14 @@ void fiq_handler(void)
289 283
290 ".more_data: \n" 284 ".more_data: \n"
291 "stmfd sp!, { r0-r3, lr } \n" /* stack scratch regs and lr */ 285 "stmfd sp!, { r0-r3, lr } \n" /* stack scratch regs and lr */
292 "ldr r2, =pcm_callback_for_more \n" 286 "ldr r2, =pcm_play_get_more_callback \n"
293 "ldr r2, [r2] \n" /* get callback address */ 287 "mov r0, r11 \n" /* r0 = &p */
294 "cmp r2, #0 \n" /* check for null pointer */ 288 "add r1, r11, #4 \n" /* r1 = &size */
295 "movne r0, r11 \n" /* r0 = &p */ 289 "blx r2 \n" /* call pcm_play_get_more_callback */
296 "addne r1, r11, #4 \n" /* r1 = &size */ 290 "ldmia r11, { r8-r9 } \n" /* load new p and size */
297 "blxne r2 \n" /* call pcm_callback_for_more */ 291 "cmp r9, #0x10 \n" /* did we actually get enough data? */
298 "ldmia r11, { r8-r9 } \n" /* reload p and size */
299 "cmp r9, #0x10 \n" /* did we actually get more data? */
300 "ldmgefd sp!, { r0-r3, lr } \n"
301 "bge .fill_fifo \n" /* yes: fill the fifo */
302 "ldr r12, =pcm_play_dma_stop \n"
303 "blx r12 \n" /* no: stop playback */
304 "ldr r12, =pcm_play_dma_stopped_callback \n"
305 "blx r12 \n"
306 "ldmfd sp!, { r0-r3, lr } \n" 292 "ldmfd sp!, { r0-r3, lr } \n"
293 "bpl .fill_fifo \n" /* not stop and enough? refill */
307 "b .exit \n" 294 "b .exit \n"
308 ".ltorg \n" 295 ".ltorg \n"
309 ); 296 );
@@ -315,17 +302,11 @@ void fiq_handler(void)
315 asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */ 302 asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */
316 "sub sp, sp, #8 \n"); /* Reserve stack */ 303 "sub sp, sp, #8 \n"); /* Reserve stack */
317 304
318 register pcm_more_callback_type get_more;
319
320 if (dma_play_data.size < 16) 305 if (dma_play_data.size < 16)
321 { 306 {
322 /* p is empty, get some more data */ 307 /* p is empty, get some more data */
323 get_more = pcm_callback_for_more; 308 pcm_play_get_more_callback((void**)&dma_play_data.p,
324 if (get_more) 309 &dma_play_data.size);
325 {
326 get_more((unsigned char**)&dma_play_data.p,
327 &dma_play_data.size);
328 }
329 } 310 }
330 311
331 if (dma_play_data.size >= 16) 312 if (dma_play_data.size >= 16)
@@ -341,12 +322,6 @@ void fiq_handler(void)
341 322
342 dma_play_data.size -= 16; 323 dma_play_data.size -= 16;
343 } 324 }
344 else
345 {
346 /* No more data, so disable the FIFO/interrupt */
347 pcm_play_dma_stop();
348 pcm_play_dma_stopped_callback();
349 }
350 325
351 /* Clear FIQ status */ 326 /* Clear FIQ status */
352 CREQ = DAI_TX_IRQ_MASK | DAI_RX_IRQ_MASK; 327 CREQ = DAI_TX_IRQ_MASK | DAI_RX_IRQ_MASK;
diff --git a/firmware/target/arm/pnx0101/pcm-pnx0101.c b/firmware/target/arm/pnx0101/pcm-pnx0101.c
index fe1e05b79a..9d4ffbd773 100644
--- a/firmware/target/arm/pnx0101/pcm-pnx0101.c
+++ b/firmware/target/arm/pnx0101/pcm-pnx0101.c
@@ -104,13 +104,10 @@ static inline void fill_dma_buf(int offset)
104 p = tmp_p; 104 p = tmp_p;
105 if (l >= lend) 105 if (l >= lend)
106 return; 106 return;
107 else if (pcm_callback_for_more) 107
108 pcm_callback_for_more((unsigned char**)&p, 108 pcm_play_get_more_callback((void**)&p, &p_size);
109 &p_size);
110 } 109 }
111 while (p_size); 110 while (p_size);
112
113 pcm_play_dma_stopped_callback();
114 } 111 }
115 112
116 if (l < lend) 113 if (l < lend)
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
index bb1b2d9eaa..e9f55479c7 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
@@ -214,35 +214,27 @@ void pcm_play_dma_pause(bool pause)
214 214
215void fiq_handler(void) 215void fiq_handler(void)
216{ 216{
217 static unsigned char *start; 217 static void *start;
218 static size_t size; 218 static size_t size;
219 register pcm_more_callback_type get_more; /* No stack for this */
220 219
221 /* clear any pending interrupt */ 220 /* clear any pending interrupt */
222 SRCPND = DMA2_MASK; 221 SRCPND = DMA2_MASK;
223 222
224 /* Buffer empty. Try to get more. */ 223 /* Buffer empty. Try to get more. */
225 get_more = pcm_callback_for_more; 224 pcm_play_get_more_callback(&start, &size);
226 size = 0;
227 225
228 if (get_more == NULL || (get_more(&start, &size), size == 0)) 226 if (size == 0)
229 { 227 return;
230 /* Callback missing or no more DMA to do */
231 pcm_play_dma_stop();
232 pcm_play_dma_stopped_callback();
233 }
234 else
235 {
236 /* Flush any pending cache writes */
237 clean_dcache_range(start, size);
238 228
239 /* set the new DMA values */ 229 /* Flush any pending cache writes */
240 DCON2 = DMA_CONTROL_SETUP | (size >> 1); 230 clean_dcache_range(start, size);
241 DISRC2 = (unsigned int)start + 0x30000000;
242 231
243 /* Re-Activate the channel */ 232 /* set the new DMA values */
244 DMASKTRIG2 = 0x2; 233 DCON2 = DMA_CONTROL_SETUP | (size >> 1);
245 } 234 DISRC2 = (unsigned int)start + 0x30000000;
235
236 /* Re-Activate the channel */
237 DMASKTRIG2 = 0x2;
246} 238}
247 239
248size_t pcm_get_bytes_waiting(void) 240size_t pcm_get_bytes_waiting(void)
diff --git a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c b/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
index 486a235614..30db29c42c 100644
--- a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
+++ b/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
@@ -254,35 +254,27 @@ void pcm_play_dma_pause(bool pause)
254 254
255void fiq_handler(void) 255void fiq_handler(void)
256{ 256{
257 static unsigned char *start; 257 static void *start;
258 static size_t size; 258 static size_t size;
259 register pcm_more_callback_type get_more; /* No stack for this */
260 259
261 /* clear any pending interrupt */ 260 /* clear any pending interrupt */
262 SRCPND = DMA2_MASK; 261 SRCPND = DMA2_MASK;
263 262
264 /* Buffer empty. Try to get more. */ 263 /* Buffer empty. Try to get more. */
265 get_more = pcm_callback_for_more; 264 pcm_play_get_more_callback(&start, &size);
266 size = 0;
267 265
268 if (get_more == NULL || (get_more(&start, &size), size == 0)) 266 if (size == 0)
269 { 267 return;
270 /* Callback missing or no more DMA to do */
271 pcm_play_dma_stop();
272 pcm_play_dma_stopped_callback();
273 }
274 else
275 {
276 /* Flush any pending cache writes */
277 clean_dcache_range(start, size);
278 268
279 /* set the new DMA values */ 269 /* Flush any pending cache writes */
280 DCON2 = DMA_CONTROL_SETUP | (size >> 1); 270 clean_dcache_range(start, size);
281 DISRC2 = (unsigned int)start + 0x30000000;
282 271
283 /* Re-Activate the channel */ 272 /* set the new DMA values */
284 DMASKTRIG2 = 0x2; 273 DCON2 = DMA_CONTROL_SETUP | (size >> 1);
285 } 274 DISRC2 = (unsigned int)start + 0x30000000;
275
276 /* Re-Activate the channel */
277 DMASKTRIG2 = 0x2;
286} 278}
287 279
288size_t pcm_get_bytes_waiting(void) 280size_t pcm_get_bytes_waiting(void)
diff --git a/firmware/target/arm/s5l8700/pcm-s5l8700.c b/firmware/target/arm/s5l8700/pcm-s5l8700.c
index 7798f41d11..4d24b327af 100644
--- a/firmware/target/arm/s5l8700/pcm-s5l8700.c
+++ b/firmware/target/arm/s5l8700/pcm-s5l8700.c
@@ -102,11 +102,11 @@ static const void* dma_callback(void)
102{ 102{
103 if (dmamode) 103 if (dmamode)
104 { 104 {
105 unsigned char *dma_start_addr; 105 void *dma_start_addr;
106 register pcm_more_callback_type get_more = pcm_callback_for_more; 106 pcm_play_get_more_callback(&dma_start_addr, &nextsize);
107 if (get_more) 107
108 if (nextsize != 0)
108 { 109 {
109 get_more(&dma_start_addr, &nextsize);
110 if (nextsize >= 4096) 110 if (nextsize >= 4096)
111 { 111 {
112 dblbufsize = (nextsize >> 4) & ~3; 112 dblbufsize = (nextsize >> 4) & ~3;
@@ -148,7 +148,6 @@ void fiq_handler(void)
148 "mov r10, #0x00000400 \n" /* INT_DMA */ 148 "mov r10, #0x00000400 \n" /* INT_DMA */
149 "str r10, [r11] \n" /* ACK FIQ */ 149 "str r10, [r11] \n" /* ACK FIQ */
150 "stmfd sp!, {r0-r3,lr} \n" 150 "stmfd sp!, {r0-r3,lr} \n"
151 "ldreq r0, =pcm_play_dma_stopped_callback \n"
152 "ldrne r0, =dma_callback \n" 151 "ldrne r0, =dma_callback \n"
153 "mov lr, pc \n" 152 "mov lr, pc \n"
154 "bx r0 \n" 153 "bx r0 \n"
@@ -225,13 +224,6 @@ void pcm_play_dma_start(const void *addr_in, size_t size)
225#endif 224#endif
226 225
227 /* S3: DMA channel 0 on */ 226 /* 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!? */
235 clean_dcache(); 227 clean_dcache();
236 if (size >= 4096) 228 if (size >= 4096)
237 { 229 {
@@ -367,12 +359,6 @@ void pcm_rec_unlock(void)
367{ 359{
368} 360}
369 361
370void pcm_rec_dma_record_more(void *start, size_t size)
371{
372 (void)start;
373 (void)size;
374}
375
376void pcm_rec_dma_stop(void) 362void pcm_rec_dma_stop(void)
377{ 363{
378} 364}
diff --git a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
index ab3ceba0f3..d7d8f92a0c 100644
--- a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
+++ b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
@@ -132,8 +132,6 @@ char buffer[80];
132void DSPHINT(void) __attribute__ ((section(".icode"))); 132void DSPHINT(void) __attribute__ ((section(".icode")));
133void DSPHINT(void) 133void DSPHINT(void)
134{ 134{
135 register pcm_more_callback_type get_more; /* No stack for this */
136
137 unsigned int i; 135 unsigned int i;
138 136
139 IO_INTC_FIQ0 = 1 << 11; 137 IO_INTC_FIQ0 = 1 << 11;
@@ -152,16 +150,9 @@ void DSPHINT(void)
152 150
153 case MSG_REFILL: 151 case MSG_REFILL:
154 /* Buffer empty. Try to get more. */ 152 /* Buffer empty. Try to get more. */
155 get_more = pcm_callback_for_more; 153 pcm_play_get_more_callback(&start, &size);
156 size = 0; 154
157 155 if (size != 0)
158 if (get_more == NULL || (get_more(&start, &size), size == 0))
159 {
160 /* Callback missing or no more DMA to do */
161 pcm_play_dma_stop();
162 pcm_play_dma_stopped_callback();
163 }
164
165 { 156 {
166 unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START; 157 unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START;
167 /* Flush any pending cache writes */ 158 /* Flush any pending cache writes */
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c
index f9c0764d64..06f17d1170 100644
--- a/firmware/target/coldfire/pcm-coldfire.c
+++ b/firmware/target/coldfire/pcm-coldfire.c
@@ -288,13 +288,14 @@ void DMA0(void) __attribute__ ((interrupt_handler, section(".icode")));
288void DMA0(void) 288void DMA0(void)
289{ 289{
290 unsigned long res = DSR0; 290 unsigned long res = DSR0;
291 void *start;
292 size_t size;
291 293
292 and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */ 294 and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */
293 DSR0 = 1; /* Clear interrupt and errors */ 295 DSR0 = 1; /* Clear interrupt and errors */
294 296
295 if (res & 0x70) 297 if (res & 0x70)
296 { 298 {
297 /* Stop on error */
298 logf("DMA0 err: %02x", res); 299 logf("DMA0 err: %02x", res);
299#if 0 300#if 0
300 logf(" SAR0: %08x", SAR0); 301 logf(" SAR0: %08x", SAR0);
@@ -303,32 +304,17 @@ void DMA0(void)
303 logf(" DCR0: %08x", DCR0); 304 logf(" DCR0: %08x", DCR0);
304#endif 305#endif
305 } 306 }
306 else 307
308 /* Force stop on error */
309 pcm_play_get_more_callback((res & 0x70) ? NULL : &start, &size);
310
311 if (size != 0)
307 { 312 {
308 pcm_more_callback_type get_more = pcm_callback_for_more; 313 SAR0 = (unsigned long)start; /* Source address */
309 unsigned char *start; 314 BCR0 = size; /* Bytes to transfer */
310 size_t size = 0; 315 or_l(DMA_EEXT | DMA_INT, &DCR0); /* per request and int ON */
311
312 if (get_more)
313 get_more(&start, &size);
314
315 start = (unsigned char *)(((long)start + 3) & ~3);
316 size &= ~3;
317
318 if (size > 0)
319 {
320 SAR0 = (unsigned long)start; /* Source address */
321 BCR0 = size; /* Bytes to transfer */
322 or_l(DMA_EEXT | DMA_INT, &DCR0); /* per request and int ON */
323 return;
324 }
325 /* Finished playing */
326 } 316 }
327 317 /* else inished playing */
328 /* Stop interrupt and futher transfers */
329 pcm_play_dma_stop();
330 /* Inform PCM that we're done */
331 pcm_play_dma_stopped_callback();
332} /* DMA0 */ 318} /* DMA0 */
333 319
334const void * pcm_play_dma_get_peak_buffer(int *count) 320const void * pcm_play_dma_get_peak_buffer(int *count)
@@ -436,7 +422,8 @@ void DMA1(void)
436{ 422{
437 unsigned long res = DSR1; 423 unsigned long res = DSR1;
438 int status = 0; 424 int status = 0;
439 pcm_more_callback_type2 more_ready; 425 void *start;
426 size_t size;
440 427
441 and_l(~(DMA_EEXT | DMA_INT), &DCR1); /* per request and int OFF */ 428 and_l(~(DMA_EEXT | DMA_INT), &DCR1); /* per request and int OFF */
442 DSR1 = 1; /* Clear interrupt and errors */ 429 DSR1 = 1; /* Clear interrupt and errors */
@@ -465,25 +452,17 @@ void DMA1(void)
465 } 452 }
466#endif 453#endif
467 454
468 more_ready = pcm_callback_more_ready; 455 /* Inform PCM we have more data (or error) */
469 456 pcm_rec_more_ready_callback(status, &start, &size);
470 if (more_ready != NULL && more_ready(status) >= 0)
471 return;
472 457
473 /* Finished recording */ 458 if (size != 0)
474 pcm_rec_dma_stop(); 459 {
475 /* Inform PCM that we're done */ 460 DAR1 = (unsigned long)start; /* Destination address */
476 pcm_rec_dma_stopped_callback(); 461 BCR1 = (unsigned long)size; /* Bytes to transfer */
462 or_l(DMA_EEXT | DMA_INT, &DCR1); /* per request and int ON */
463 }
477} /* DMA1 */ 464} /* DMA1 */
478 465
479/* Continue transferring data in - call from interrupt callback */
480void pcm_rec_dma_record_more(void *start, size_t size)
481{
482 DAR1 = (unsigned long)start; /* Destination address */
483 BCR1 = (unsigned long)size; /* Bytes to transfer */
484 or_l(DMA_EEXT | DMA_INT, &DCR1); /* per request and int ON */
485} /* pcm_record_more */
486
487const void * pcm_rec_dma_get_peak_buffer(void) 466const void * pcm_rec_dma_get_peak_buffer(void)
488{ 467{
489 return (void *)(DAR1 & ~3); 468 return (void *)(DAR1 & ~3);
diff --git a/firmware/target/hosted/sdl/pcm-sdl.c b/firmware/target/hosted/sdl/pcm-sdl.c
index ee92fa208d..03e6e1336c 100644
--- a/firmware/target/hosted/sdl/pcm-sdl.c
+++ b/firmware/target/hosted/sdl/pcm-sdl.c
@@ -228,15 +228,9 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
228 228
229 /* Audio card wants more? Get some more then. */ 229 /* Audio card wants more? Get some more then. */
230 while (len > 0) { 230 while (len > 0) {
231 if ((ssize_t)pcm_data_size <= 0) { 231 pcm_play_get_more_callback(&pcm_data, &pcm_data_size);
232 pcm_data_size = 0;
233
234 if (pcm_callback_for_more)
235 pcm_callback_for_more(&pcm_data, &pcm_data_size);
236 }
237
238 if (pcm_data_size > 0) {
239 start: 232 start:
233 if (pcm_data_size != 0) {
240 udata->num_in = pcm_data_size / pcm_sample_bytes; 234 udata->num_in = pcm_data_size / pcm_sample_bytes;
241 udata->num_out = len / pcm_sample_bytes; 235 udata->num_out = len / pcm_sample_bytes;
242 236
@@ -251,8 +245,6 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
251 len -= udata->num_out; 245 len -= udata->num_out;
252 } else { 246 } else {
253 DEBUGF("sdl_audio_callback: No Data.\n"); 247 DEBUGF("sdl_audio_callback: No Data.\n");
254 pcm_play_dma_stop();
255 pcm_play_dma_stopped_callback();
256 break; 248 break;
257 } 249 }
258 } 250 }
@@ -292,12 +284,6 @@ void pcm_rec_dma_stop(void)
292{ 284{
293} 285}
294 286
295void pcm_rec_dma_record_more(void *start, size_t size)
296{
297 (void)start;
298 (void)size;
299}
300
301unsigned long pcm_rec_status(void) 287unsigned long pcm_rec_status(void)
302{ 288{
303 return 0; 289 return 0;
diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
index 993f70bad8..4cf43471eb 100644
--- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
@@ -100,23 +100,16 @@ static inline void set_dma(const void *addr, size_t size)
100 100
101static inline void play_dma_callback(void) 101static inline void play_dma_callback(void)
102{ 102{
103 unsigned char *start = NULL; 103 unsigned char *start;
104 size_t size = 0; 104 size_t size;
105 105
106 if(pcm_callback_for_more) 106 pcm_play_get_more_callback(&start, &size);
107 pcm_callback_for_more(&start, &size);
108 107
109 if(LIKELY(size > 0 && start)) 108 if (size != 0)
110 { 109 {
111 set_dma(start, size); 110 set_dma(start, size);
112 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; 111 REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN;
113 } 112 }
114 else
115 {
116 /* Error, callback missing or no more DMA to do */
117 pcm_play_dma_stop();
118 pcm_play_dma_stopped_callback();
119 }
120} 113}
121 114
122void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) __attribute__ ((section(".icode"))); 115void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) __attribute__ ((section(".icode")));
@@ -292,10 +285,4 @@ const void * pcm_rec_dma_get_peak_buffer(void)
292{ 285{
293 return NULL; 286 return NULL;
294} 287}
295
296void pcm_rec_dma_record_more(void *start, size_t size)
297{
298 (void) start;
299 (void) size;
300}
301#endif 288#endif