[Sound-open-firmware] [PATCH] dw-dma: recover dma status when release

From: Pan Xiuli xiuli.pan@linux.intel.com
Resume pause will re-start DMA, which will cause the DMA status diff from buffer COMP. Add a release function to recover the status mainily for LLI now.
This patch fixes pause/resume noise issues.
Tested-by: Keyon Jie yang.jie@linux.intel.com Signed-off-by: Pan Xiuli xiuli.pan@linux.intel.com
--- Test with: Mininow max rt5651 SOF 1.1-stable: 98d3a838cb397e91d6c032cf9b39d3748102803e SOF-Tool 1.1-stable: 78ad1ccce5ac689680adc32f8136f5bf551b0f7c https://github.com/plbossart/sound/tree/topic/sof-v4.14: c33cfed51fff5eb156dcf70ba849e6ffb3008377 --- src/audio/dai.c | 21 ++++++++++++++++++--- src/drivers/dw-dma.c | 16 ++++++++++------ 2 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 79e877f..9865e02 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -558,12 +558,27 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd) switch (cmd) { case COMP_TRIGGER_START: dai_pointer_init(dev); - /* fall through */ - case COMP_TRIGGER_RELEASE: - /* only start the DAI if we are not XRUN handling */ if (dd->xrun == 0) { + /* start the DAI */ + ret = dma_start(dd->dma, dd->chan); + if (ret < 0) + return ret; + dai_trigger(dd->dai, cmd, dev->params.direction); + } else { + dd->xrun = 0; + }
+ /* update starting wallclock */ + platform_dai_wallclock(dev, &dd->wallclock); + break; + case COMP_TRIGGER_RELEASE: + /* only start the DAI if we are not XRUN handling */ + if (dd->xrun == 0) { + /* recover the dma status */ + ret = dma_release(dd->dma, dd->chan); + if (ret < 0) + return ret; /* start the DAI */ ret = dma_start(dd->dma, dd->chan); if (ret < 0) diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index aac524e..a21ecc5 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -430,18 +430,22 @@ out: static int dw_dma_release(struct dma *dma, int channel) { struct dma_pdata *p = dma_get_drvdata(dma); + struct dw_lli2 *lli; uint32_t flags;
spin_lock_irq(&dma->lock, flags);
trace_dma("Dpr");
- if (p->chan[channel].status == COMP_STATE_PAUSED) { - dw_dma_chan_reload_lli(dma, channel); - } - - /* resume and reload DMA */ - p->chan[channel].status = COMP_STATE_ACTIVE; + /* get current lli */ +#if DW_USE_HW_LLI + lli = (struct dw_lli2 *)dw_read(dma, DW_LLP(channel)); +#else + lli = p->chan[channel].lli_current; +#endif + /* get next lli and recover the lli to head for restart */ + lli = (struct dw_lli2 *)lli->llp; + p->chan[channel].lli = lli;
spin_unlock_irq(&dma->lock, flags); return 0;

Ping.
On 3/30/2018 16:58, Xiuli Pan wrote:
From: Pan Xiuli xiuli.pan@linux.intel.com
Resume pause will re-start DMA, which will cause the DMA status diff from buffer COMP. Add a release function to recover the status mainily for LLI now.
This patch fixes pause/resume noise issues.
Tested-by: Keyon Jie yang.jie@linux.intel.com Signed-off-by: Pan Xiuli xiuli.pan@linux.intel.com
Test with: Mininow max rt5651 SOF 1.1-stable: 98d3a838cb397e91d6c032cf9b39d3748102803e SOF-Tool 1.1-stable: 78ad1ccce5ac689680adc32f8136f5bf551b0f7c https://github.com/plbossart/sound/tree/topic/sof-v4.14: c33cfed51fff5eb156dcf70ba849e6ffb3008377
src/audio/dai.c | 21 ++++++++++++++++++--- src/drivers/dw-dma.c | 16 ++++++++++------ 2 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 79e877f..9865e02 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -558,12 +558,27 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd) switch (cmd) { case COMP_TRIGGER_START: dai_pointer_init(dev);
/* fall through */
- case COMP_TRIGGER_RELEASE:
- /* only start the DAI if we are not XRUN handling */ if (dd->xrun == 0) {
/* start the DAI */
ret = dma_start(dd->dma, dd->chan);
if (ret < 0)
return ret;
dai_trigger(dd->dai, cmd, dev->params.direction);
} else {
dd->xrun = 0;
}
/* update starting wallclock */
platform_dai_wallclock(dev, &dd->wallclock);
break;
case COMP_TRIGGER_RELEASE:
/* only start the DAI if we are not XRUN handling */
if (dd->xrun == 0) {
/* recover the dma status */
ret = dma_release(dd->dma, dd->chan);
if (ret < 0)
return ret; /* start the DAI */ ret = dma_start(dd->dma, dd->chan); if (ret < 0)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index aac524e..a21ecc5 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -430,18 +430,22 @@ out: static int dw_dma_release(struct dma *dma, int channel) { struct dma_pdata *p = dma_get_drvdata(dma);
struct dw_lli2 *lli; uint32_t flags;
spin_lock_irq(&dma->lock, flags);
trace_dma("Dpr");
- if (p->chan[channel].status == COMP_STATE_PAUSED) {
dw_dma_chan_reload_lli(dma, channel);
- }
- /* resume and reload DMA */
- p->chan[channel].status = COMP_STATE_ACTIVE;
- /* get current lli */
+#if DW_USE_HW_LLI
- lli = (struct dw_lli2 *)dw_read(dma, DW_LLP(channel));
+#else
- lli = p->chan[channel].lli_current;
+#endif
/* get next lli and recover the lli to head for restart */
lli = (struct dw_lli2 *)lli->llp;
p->chan[channel].lli = lli;
spin_unlock_irq(&dma->lock, flags); return 0;

On Fri, 2018-03-30 at 16:58 +0800, Xiuli Pan wrote:
From: Pan Xiuli xiuli.pan@linux.intel.com
Resume pause will re-start DMA, which will cause the DMA status diff from buffer COMP. Add a release function to recover the status mainily for LLI now.
This patch fixes pause/resume noise issues.
Tested-by: Keyon Jie yang.jie@linux.intel.com Signed-off-by: Pan Xiuli xiuli.pan@linux.intel.com
Applied.
Thanks
Liam
participants (3)
-
Liam Girdwood
-
Pan, Xiuli
-
Xiuli Pan