summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2012-02-23 08:14:46 -0500
committerMichael Sevakis <jethead71@rockbox.org>2012-03-03 07:23:38 +0100
commit286a4c5caa1945c8d1cb365a3d90fb09d5700cb2 (patch)
tree4835f46d16ec78d035ec9f49333079fe618384c1 /firmware/target/arm/imx31
parent3f82f3aca14eb954e55f761721ffdd2684f0e812 (diff)
downloadrockbox-286a4c5caa1945c8d1cb365a3d90fb09d5700cb2.tar.gz
rockbox-286a4c5caa1945c8d1cb365a3d90fb09d5700cb2.zip
Revise the PCM callback system after adding multichannel audio.
Additional status callback is added to pcm_play/rec_data instead of using a special function to set it. Status includes DMA error reporting to the status callback. Playback and recording callback become more alike except playback uses "const void **addr" (because the data should not be altered) and recording uses "void **addr". "const" is put in place throughout where appropriate. Most changes are fairly trivial. One that should be checked in particular because it isn't so much is telechips, if anyone cares to bother. PP5002 is not so trivial either but that tested as working. Change-Id: I4928d69b3b3be7fb93e259f81635232df9bd1df2 Reviewed-on: http://gerrit.rockbox.org/166 Reviewed-by: Michael Sevakis <jethead71@rockbox.org> Tested-by: Michael Sevakis <jethead71@rockbox.org>
Diffstat (limited to 'firmware/target/arm/imx31')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c119
1 files changed, 56 insertions, 63 deletions
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 e106cf78e3..c26349b72e 100644
--- a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
@@ -78,12 +78,20 @@ static struct dma_data dma_play_data =
78 .state = 0 78 .state = 0
79}; 79};
80 80
81static void play_dma_callback(void) 81static void play_start_dma(const void *addr, size_t size)
82{ 82{
83 void *start; 83 commit_dcache_range(addr, size);
84 size_t size; 84
85 bool rror; 85 dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)addr);
86 dma_play_bd.mode.count = size;
87 dma_play_bd.mode.command = TRANSFER_16BIT;
88 dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
89
90 sdma_channel_run(DMA_PLAY_CH_NUM);
91}
86 92
93static void play_dma_callback(void)
94{
87 if (dma_play_data.locked != 0) 95 if (dma_play_data.locked != 0)
88 { 96 {
89 /* Callback is locked out */ 97 /* Callback is locked out */
@@ -91,22 +99,17 @@ static void play_dma_callback(void)
91 return; 99 return;
92 } 100 }
93 101
94 rror = dma_play_bd.mode.status & BD_RROR; 102 /* Inform of status and get new buffer */
95 103 enum pcm_dma_status status = (dma_play_bd.mode.status & BD_RROR) ?
96 pcm_play_get_more_callback(rror ? NULL : &start, &size); 104 PCM_DMAST_ERR_DMA : PCM_DMAST_OK;
97 105 const void *addr;
98 if (size == 0) 106 size_t size;
99 return; 107
100 108 if (pcm_play_dma_complete_callback(status, &addr, &size))
101 /* Flush any pending cache writes */ 109 {
102 commit_dcache_range(start, size); 110 play_start_dma(addr, size);
103 dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)start); 111 pcm_play_dma_status_callback(PCM_DMAST_STARTED);
104 dma_play_bd.mode.count = size; 112 }
105 dma_play_bd.mode.command = TRANSFER_16BIT;
106 dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
107 sdma_channel_run(DMA_PLAY_CH_NUM);
108
109 pcm_play_dma_started_callback();
110} 113}
111 114
112void pcm_play_lock(void) 115void pcm_play_lock(void)
@@ -221,15 +224,11 @@ void pcm_play_dma_start(const void *addr, size_t size)
221 if (!sdma_channel_reset(DMA_PLAY_CH_NUM)) 224 if (!sdma_channel_reset(DMA_PLAY_CH_NUM))
222 return; 225 return;
223 226
224 commit_dcache_range(addr, size); 227 /* Begin I2S transmission */
225 dma_play_bd.buf_addr =
226 (void *)addr_virt_to_phys((unsigned long)(void *)addr);
227 dma_play_bd.mode.count = size;
228 dma_play_bd.mode.command = TRANSFER_16BIT;
229 dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
230
231 play_start_pcm(); 228 play_start_pcm();
232 sdma_channel_run(DMA_PLAY_CH_NUM); 229
230 /* Begin DMA transfer */
231 play_start_dma(addr, size);
233} 232}
234 233
235void pcm_play_dma_stop(void) 234void pcm_play_dma_stop(void)
@@ -332,37 +331,39 @@ static struct dma_data dma_rec_data =
332 .state = 0 331 .state = 0
333}; 332};
334 333
335static void rec_dma_callback(void) 334static void rec_start_dma(void *addr, size_t size)
336{ 335{
337 int status = 0; 336 discard_dcache_range(addr, size);
338 void *start; 337
339 size_t size; 338 addr = (void *)addr_virt_to_phys((unsigned long)addr);
340 339
340 dma_rec_bd.buf_addr = addr;
341 dma_rec_bd.mode.count = size;
342 dma_rec_bd.mode.command = TRANSFER_16BIT;
343 dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
344
345 sdma_channel_run(DMA_REC_CH_NUM);
346}
347
348static void rec_dma_callback(void)
349{
341 if (dma_rec_data.locked != 0) 350 if (dma_rec_data.locked != 0)
342 { 351 {
343 dma_rec_data.callback_pending = dma_rec_data.state; 352 dma_rec_data.callback_pending = dma_rec_data.state;
344 return; /* Callback is locked out */ 353 return; /* Callback is locked out */
345 } 354 }
346 355
347 if (dma_rec_bd.mode.status & BD_RROR) 356 /* Inform middle layer */
348 status = DMA_REC_ERROR_DMA; 357 enum pcm_dma_status status = (dma_rec_bd.mode.status & BD_RROR) ?
349 358 PCM_DMAST_ERR_DMA : PCM_DMAST_OK;
350 pcm_rec_more_ready_callback(status, &start, &size); 359 void *addr;
351 360 size_t size;
352 if (size == 0)
353 return;
354
355 /* Invalidate - buffer must be coherent */
356 discard_dcache_range(start, size);
357
358 start = (void *)addr_virt_to_phys((unsigned long)start);
359
360 dma_rec_bd.buf_addr = start;
361 dma_rec_bd.mode.count = size;
362 dma_rec_bd.mode.command = TRANSFER_16BIT;
363 dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
364 361
365 sdma_channel_run(DMA_REC_CH_NUM); 362 if (pcm_rec_dma_complete_callback(status, &addr, &size))
363 {
364 rec_start_dma(addr, size);
365 pcm_rec_dma_status_callback(PCM_DMAST_STARTED);
366 }
366} 367}
367 368
368void pcm_rec_lock(void) 369void pcm_rec_lock(void)
@@ -426,29 +427,21 @@ void pcm_rec_dma_start(void *addr, size_t size)
426 427
427 if (!sdma_channel_reset(DMA_REC_CH_NUM)) 428 if (!sdma_channel_reset(DMA_REC_CH_NUM))
428 return; 429 return;
429
430 /* Invalidate - buffer must be coherent */
431 discard_dcache_range(addr, size);
432 430
433 addr = (void *)addr_virt_to_phys((unsigned long)addr); 431 /* Ensure clear FIFO */
434 dma_rec_bd.buf_addr = addr; 432 while (SSI_SFCSR1 & SSI_SFCSR_RFCNT0)
435 dma_rec_bd.mode.count = size; 433 SSI_SRX0_1;
436 dma_rec_bd.mode.command = TRANSFER_16BIT;
437 dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
438 434
439 dma_rec_data.state = 1; /* Check callback on unlock */ 435 dma_rec_data.state = 1; /* Check callback on unlock */
440 436
441 SSI_SRCR1 |= SSI_SRCR_RFEN0; /* Enable RX FIFO */ 437 SSI_SRCR1 |= SSI_SRCR_RFEN0; /* Enable RX FIFO */
442 438
443 /* Ensure clear FIFO */
444 while (SSI_SFCSR1 & SSI_SFCSR_RFCNT0)
445 SSI_SRX0_1;
446
447 /* Enable receive */ 439 /* Enable receive */
448 SSI_SCR1 |= SSI_SCR_RE; 440 SSI_SCR1 |= SSI_SCR_RE;
449 SSI_SIER1 |= SSI_SIER_RDMAE; /* Enable DMA req. */ 441 SSI_SIER1 |= SSI_SIER_RDMAE; /* Enable DMA req. */
450 442
451 sdma_channel_run(DMA_REC_CH_NUM); 443 /* Begin DMA transfer */
444 rec_start_dma(addr, size);
452} 445}
453 446
454void pcm_rec_dma_close(void) 447void pcm_rec_dma_close(void)