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) {