diff --git a/src/drivers/intel/hda/hda-dma.c b/src/drivers/intel/hda/hda-dma.c index 8d3e56b40bb6..0e911afd2181 100644 --- a/src/drivers/intel/hda/hda-dma.c +++ b/src/drivers/intel/hda/hda-dma.c @@ -348,9 +348,8 @@ static int hda_dma_host_start(struct dma_chan_data *channel) struct hda_chan_data *hda_chan = dma_chan_get_data(channel); int ret = 0; - /* Force Host DMA to exit L1 only on start*/ - if (!(hda_chan->state & HDA_STATE_RELEASE)) - pm_runtime_put(PM_RUNTIME_HOST_DMA_L1, 0); + /* Force Host DMA to exit L1 on start */ + pm_runtime_put(PM_RUNTIME_HOST_DMA_L1, 0); if (!hda_chan->irq_disabled) return ret; @@ -390,20 +389,21 @@ static int hda_dma_enable_unlock(struct dma_chan_data *channel) hda_dma_get_dbg_vals(channel, HDA_DBG_PRE, HDA_DBG_BOTH); - /* enable the channel */ - dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN | DGCS_FIFORDY, - DGCS_GEN | DGCS_FIFORDY); - /* full buffer is copied at startup */ hda_chan = dma_chan_get_data(channel); hda_chan->desc_avail = channel->desc_count; + /* enable the channel */ if (channel->direction == DMA_DIR_HMEM_TO_LMEM || channel->direction == DMA_DIR_LMEM_TO_HMEM) { + dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN | DGCS_FIFORDY, + DGCS_FIFORDY | DGCS_GEN); pm_runtime_get(PM_RUNTIME_HOST_DMA_L1, 0); ret = hda_dma_host_start(channel); if (ret < 0) return ret; + } else { + dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN, DGCS_GEN); } /* start link output transfer now */ @@ -565,16 +565,8 @@ static int hda_dma_release(struct dma_chan_data *channel) tr_dbg(&hdma_tr, "hda-dmac: %d channel %d -> release", channel->dma->plat_data.id, channel->index); - /* - * Prepare for the handling of release condition on the first work cb. - * This flag will be unset afterwards. - */ hda_chan->state |= HDA_STATE_RELEASE; - if (channel->direction == DMA_DIR_HMEM_TO_LMEM || - channel->direction == DMA_DIR_LMEM_TO_HMEM) - ret = hda_dma_host_start(channel); - irq_local_enable(flags); return ret; } @@ -613,12 +605,15 @@ static int hda_dma_stop(struct dma_chan_data *channel) tr_dbg(&hdma_tr, "hda-dmac: %d channel %d -> stop", channel->dma->plat_data.id, channel->index); + /* disable the channel */ if (channel->direction == DMA_DIR_HMEM_TO_LMEM || - channel->direction == DMA_DIR_LMEM_TO_HMEM) + channel->direction == DMA_DIR_LMEM_TO_HMEM) { hda_dma_host_stop(channel); - /* disable the channel */ - dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN | DGCS_FIFORDY, 0); + dma_chan_reg_update_bits(channel, DGCS, DGCS_FIFORDY | DGCS_GEN, 0); + } else { + dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN, 0); + } channel->status = COMP_STATE_PREPARE; hda_chan = dma_chan_get_data(channel); hda_chan->state = 0; @@ -756,9 +751,8 @@ static int hda_dma_set_config(struct dma_chan_data *channel, config->src_width <= 2)) dgcs |= DGCS_SCS; - /* set DGCS.FIFORDY for output dma */ - if ((config->cyclic && config->direction == DMA_DIR_MEM_TO_DEV) || - (!config->cyclic && config->direction == DMA_DIR_LMEM_TO_HMEM)) + /* set DGCS.FIFORDY for input/output host DMA only. It is not relevant for link DMA's */ + if (config->direction == DMA_DIR_HMEM_TO_LMEM || config->direction == DMA_DIR_LMEM_TO_HMEM) dgcs |= DGCS_FIFORDY; dma_chan_reg_write(channel, DGCS, dgcs); @@ -986,8 +980,6 @@ const struct dma_ops hda_host_dma_ops = { .start = hda_dma_start, .stop = hda_dma_stop, .copy = hda_dma_host_copy, - .pause = hda_dma_pause, - .release = hda_dma_release, .status = hda_dma_status, .set_config = hda_dma_set_config, .pm_context_restore = hda_dma_pm_context_restore, diff --git a/src/include/sof/lib/dma.h b/src/include/sof/lib/dma.h index 43726b52441c..fac3d0c6ef9d 100644 --- a/src/include/sof/lib/dma.h +++ b/src/include/sof/lib/dma.h @@ -335,16 +335,18 @@ static inline int dma_copy(struct dma_chan_data *channel, int bytes, static inline int dma_pause(struct dma_chan_data *channel) { - int ret = channel->dma->ops->pause(channel); + if (channel->dma->ops->pause) + return channel->dma->ops->pause(channel); - return ret; + return 0; } static inline int dma_release(struct dma_chan_data *channel) { - int ret = channel->dma->ops->release(channel); + if (channel->dma->ops->release) + return channel->dma->ops->release(channel); - return ret; + return 0; } static inline int dma_status(struct dma_chan_data *channel,