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

Xiuli Pan xiuli.pan at linux.intel.com
Fri Mar 30 10:58:58 CEST 2018


From: Pan Xiuli <xiuli.pan at 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 at linux.intel.com>
Signed-off-by: Pan Xiuli <xiuli.pan at 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;
-- 
2.7.4



More information about the Sound-open-firmware mailing list