-
Notifications
You must be signed in to change notification settings - Fork 350
Fixes for HDA-DMA driver #4820
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes for HDA-DMA driver #4820
Changes from all commits
c86271a
a1158c8
1973a66
10e25f7
0e092f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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; | ||
plbossart marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| 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) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would agree with @keyonjie that it's not clear why we need to keep setting this FIFORDY bit in hda_dma_set_config(), when it's already set in enable_dma() and cleared in stop_dma() |
||
| 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, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the original logic is that we don't need to force L1 exit for the pause/release iteration, while we need it for a _start, as there will be preloading for a hda_dma_start() while there isn't for the _release().
We do have dma_pause() and dma_release() calling in dai.c, even though there might not be trigger pause/release IPCs from the Linux host side, so I would suggest to keep this as it is in case it doesn't bring any issues like Xruns to us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@keyonjie DAI uses link DMA and we have the ops for link DMA here. There is no need for host DMA pause/release when it is not used