summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31
diff options
context:
space:
mode:
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)