From 53f2f38c86f8a29fca03c5efd7d3a3e9ce9b0e19 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Tue, 11 Jun 2019 15:03:13 +0200 Subject: [PATCH] hda-dma: change preload from blocking to repeating Changes preload flow for host component using HDA-DMA. Instead of waiting for DMA status for a limited amount of time, it's better to just reschedule the pipeline and check again. At least this time if the status won't be set, we will know it's rather HW issue than too small delay. Signed-off-by: Tomasz Lauda --- src/audio/host.c | 11 +++++++++-- src/audio/pipeline.c | 9 +++++++-- src/drivers/intel/cavs/hda-dma.c | 10 +++++++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/audio/host.c b/src/audio/host.c index 07425657630e..b934be5e3ffe 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -763,10 +763,17 @@ static int host_copy(struct comp_dev *dev) /* here only do preload, further copies happen * in host_buffer_cb() */ - if (pipeline_is_preload(dev->pipeline)) { + if (pipeline_is_preload(dev->pipeline) && !dev->position) { ret = dma_copy(hd->dma, hd->chan, hd->dma_buffer->size, - DMA_COPY_PRELOAD | DMA_COPY_BLOCKING); + DMA_COPY_PRELOAD); if (ret < 0) { + if (ret == -ENODATA) { + /* preload not finished, so stop processing */ + trace_host("host_copy(), preload not yet " + "finished"); + return PPL_STATUS_PATH_STOP; + } + trace_host_error("host_copy() error: dma_copy() " "failed, ret = %u", ret); return ret; diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index 677943d256c4..1679b23484c2 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -780,7 +780,9 @@ static int pipeline_copy(struct pipeline *p) "->comp.id = %u, dir = %u", ret, start->comp.id, dir); - p->preload = false; + /* stop preload only after full walkthrough */ + if (ret != PPL_STATUS_PATH_STOP) + p->preload = false; return ret; } @@ -974,5 +976,8 @@ static uint64_t pipeline_task(void *arg) } tracev_pipe("pipeline_task() sched"); - return pipeline_is_timer_driven(p) ? p->ipc_pipe.period : 0; + + /* automatically reschedule for timer or not finished preload */ + return (pipeline_is_timer_driven(p) || p->preload) ? + p->ipc_pipe.period : 0; } diff --git a/src/drivers/intel/cavs/hda-dma.c b/src/drivers/intel/cavs/hda-dma.c index 6adb030adfa4..930c5d0262d4 100644 --- a/src/drivers/intel/cavs/hda-dma.c +++ b/src/drivers/intel/cavs/hda-dma.c @@ -422,11 +422,19 @@ static int hda_dma_host_copy(struct dma *dma, unsigned int channel, int bytes, hda_dma_get_dbg_vals(chan, HDA_DBG_PRE, HDA_DBG_HOST); - if (!(flags & DMA_COPY_PRELOAD)) + if (flags & DMA_COPY_PRELOAD) { + /* report lack of data if preload is not yet finished */ + ret = chan->direction == DMA_DIR_HMEM_TO_LMEM ? + hda_dma_is_buffer_full(dma, chan) : + hda_dma_is_buffer_empty(dma, chan); + if (!ret) + return -ENODATA; + } else { /* set BFPI to let host gateway know we have read size, * which will trigger next copy start. */ hda_dma_inc_fp(dma, chan->index, bytes); + } /* blocking mode copy */ if (flags & DMA_COPY_BLOCKING) {