[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