diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c | 119 |
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 | ||
81 | static void play_dma_callback(void) | 81 | static 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 | ||
93 | static 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 | ||
112 | void pcm_play_lock(void) | 115 | void 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 | ||
235 | void pcm_play_dma_stop(void) | 234 | void 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 | ||
335 | static void rec_dma_callback(void) | 334 | static 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 | |||
348 | static 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 | ||
368 | void pcm_rec_lock(void) | 369 | void 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 | ||
454 | void pcm_rec_dma_close(void) | 447 | void pcm_rec_dma_close(void) |