diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c index 39c0bc4969..9d2503f4e6 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c @@ -272,6 +272,12 @@ void pcm_play_dma_start(const void *addr, size_t size) addr = (void *)(((unsigned long)addr + 3) & ~3); size &= ~3; + if (size <= 0) + return; + + if (!sdma_channel_reset(DMA_PLAY_CH_NUM)) + return; + clean_dcache_range(addr, size); dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)(void *)addr); @@ -280,7 +286,7 @@ void pcm_play_dma_start(const void *addr, size_t size) dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR; play_start_pcm(); - sdma_channel_start(DMA_PLAY_CH_NUM); + sdma_channel_run(DMA_PLAY_CH_NUM); } void pcm_play_dma_stop(void) @@ -463,6 +469,12 @@ void pcm_rec_dma_start(void *addr, size_t size) addr = (void *)(((unsigned long)addr + 3) & ~3); size &= ~3; + if (size <= 0) + return; + + if (!sdma_channel_reset(DMA_REC_CH_NUM)) + return; + /* Invalidate - buffer must be coherent */ dump_dcache_range(addr, size); @@ -483,8 +495,7 @@ void pcm_rec_dma_start(void *addr, size_t size) /* Enable receive */ SSI_SCR2 |= SSI_SCR_RE; - - sdma_channel_start(DMA_REC_CH_NUM); + sdma_channel_run(DMA_REC_CH_NUM); } void pcm_rec_dma_close(void) diff --git a/firmware/target/arm/imx31/sdma-imx31.c b/firmware/target/arm/imx31/sdma-imx31.c index 0683ec3568..100bd51028 100644 --- a/firmware/target/arm/imx31/sdma-imx31.c +++ b/firmware/target/arm/imx31/sdma-imx31.c @@ -613,23 +613,23 @@ void sdma_channel_set_priority(unsigned int channel, unsigned int priority) SDMA_CHNPRI(channel) = priority; } -/* Start a channel cold - resets execution to start of script */ -void sdma_channel_start(unsigned int channel) +/* Resets a channel to start of script next time it runs. */ +bool sdma_channel_reset(unsigned int channel) { struct channel_control_block *ccb_p; if (channel == 0 || channel >= CH_NUM) - return; + return false; ccb_p = &ccb_array[channel]; if (ccb_p->status.opened_init == 0) - return; + return false; if (!setup_channel(ccb_p)) - return; + return false; - SDMA_HSTART = 1ul << channel; + return true; } /* Resume or start execution on a channel */ diff --git a/firmware/target/arm/imx31/sdma-imx31.h b/firmware/target/arm/imx31/sdma-imx31.h index fa8195198b..5daa33d7ba 100644 --- a/firmware/target/arm/imx31/sdma-imx31.h +++ b/firmware/target/arm/imx31/sdma-imx31.h @@ -212,7 +212,7 @@ void sdma_init(void); void sdma_read_words(unsigned long *buf, unsigned long start, int count); void sdma_write_words(const unsigned long *buf, unsigned long start, int count); void sdma_channel_set_priority(unsigned int channel, unsigned int priority); -void sdma_channel_start(unsigned int channel); +bool sdma_channel_reset(unsigned int channel); void sdma_channel_run(unsigned int channel); void sdma_channel_pause(unsigned int channel); void sdma_channel_stop(unsigned int channel);