From d97cd8befd849d7d2d9e4c2f6f00c9abb3707ed4 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Thu, 14 Mar 2019 10:22:06 +0100 Subject: [PATCH 1/2] pipeline: adjust flow to more scheduler flexible Adjusts pipeline flow to be more scheduler flexible and not only valid for DMA IRQ based schedulers. Signed-off-by: Tomasz Lauda --- src/audio/dai.c | 3 ++- src/audio/pipeline.c | 17 ++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/audio/dai.c b/src/audio/dai.c index abb30efe9e76..6401ef567616 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -615,7 +615,8 @@ static int dai_copy(struct comp_dev *dev) dev->params.direction); platform_dai_wallclock(dev, &dd->wallclock); - return ret; + /* let's not copy further */ + return 1; } /* get data sizes from DMA */ diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index e88b5423743d..08d72742a871 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -353,8 +353,11 @@ int pipeline_prepare(struct pipeline *p, struct comp_dev *dev) goto out; } - /* pipeline preload needed only for playback streams */ - p->preload = dev->params.direction == SOF_IPC_STREAM_PLAYBACK; + /* pipeline preload needed only for playback streams and capture + * streams scheduled with timer + */ + p->preload = dev->params.direction == SOF_IPC_STREAM_PLAYBACK || + pipeline_is_timer_driven(p); p->status = COMP_STATE_PREPARE; out: @@ -424,12 +427,12 @@ static void pipeline_comp_trigger_sched_comp(struct pipeline *p, case COMP_TRIGGER_START: p->xrun_bytes = 0; - /* playback pipelines need scheduled now, capture pipelines are - * scheduled once their initial DMA period is filled by the DAI - * or in resume process + /* playback pipelines need to be scheduled now, + * capture pipelines are scheduled only for + * timer driven scheduling */ if (comp->params.direction == SOF_IPC_STREAM_PLAYBACK || - p->status == COMP_STATE_PAUSED) { + pipeline_is_timer_driven(p)) { /* schedule initial pipeline fill when next idle */ pipeline_schedule_copy_idle(p); } @@ -596,7 +599,7 @@ static int pipeline_comp_copy(struct comp_dev *current, void *data, int dir) /* copy to downstream immediately */ if (dir == PPL_DIR_DOWNSTREAM) { err = comp_copy(current); - if (err < 0) + if (err < 0 || err > 0) return err; } From 649f00e6865099386dc6fdcd71c5b1868bff7b16 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Thu, 14 Mar 2019 10:26:32 +0100 Subject: [PATCH 2/2] dai: dw-dma: adjust flow to more scheduler flexible Adjusts dai and dw-dma configuration flows to be more scheduler flexible and not only working for DMA IRQ based schedulers. Note: due to the nature of timer scheduling we need to have restriction for dw-dma to support minimum 3 linked list items. Without such restriction we may not be able to clear done bits on time. Signed-off-by: Tomasz Lauda --- src/audio/dai.c | 5 ++++- src/drivers/dw/dma.c | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/audio/dai.c b/src/audio/dai.c index 6401ef567616..a649520d1693 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -456,6 +456,7 @@ static int dai_params(struct comp_dev *dev) static int dai_prepare(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); + struct dma_sg_config *config = &dd->config; int ret = 0; trace_dai_with_ids(dev, "dai_prepare()"); @@ -477,7 +478,9 @@ static int dai_prepare(struct comp_dev *dev) /* write back buffer contents from cache */ dcache_writeback_region(dd->dma_buffer->addr, dd->dma_buffer->size); - dd->cb_type = 0; + /* set default callback type if irq disabled */ + if (config->irq_disabled) + dd->cb_type = DMA_CB_TYPE_BLOCK; /* dma reconfig not required if XRUN handling */ if (dd->xrun) { diff --git a/src/drivers/dw/dma.c b/src/drivers/dw/dma.c index edc11f8df2df..29a7a501e147 100644 --- a/src/drivers/dw/dma.c +++ b/src/drivers/dw/dma.c @@ -267,6 +267,9 @@ /* number of tries to wait for reset */ #define DW_DMA_CFG_TRIES 10000 +/* min number of elems for config with irq disabled */ +#define DW_DMA_CFG_NO_IRQ_MIN_ELEMS 3 + /* linked list item address */ #define DW_DMA_LLI_ADDRESS(lli, dir) \ (((dir) == DMA_DIR_MEM_TO_DEV) ? ((lli)->sar) : ((lli)->dar)) @@ -797,6 +800,16 @@ static int dw_dma_set_config(struct dma *dma, int channel, goto out; } + if (config->irq_disabled && + config->elem_array.count < DW_DMA_CFG_NO_IRQ_MIN_ELEMS) { + trace_dwdma_error("dw-dma: %d channel %d not enough elems " + "for config with irq disabled", + dma->plat_data.id, channel, + config->elem_array.count); + ret = -EINVAL; + goto out; + } + /* do we need to realloc descriptors */ if (config->elem_array.count != chan->desc_count) {