From e954709386a030ceb6c830347fdfc17abf5a7896 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Tue, 10 Mar 2020 10:09:30 +0100 Subject: [PATCH] hda-dma: refactor xrun handling Changes behaviour of HDA Link overruns and underruns handling. Let's no longer stop the stream, but just report an error. It might happen that just after the release buffer is still full/not yet empty after the previous run, but it shouldn't affect the data, since stream has been paused anyway. Also adds additional bit to better reflect hardware registers. Signed-off-by: Tomasz Lauda --- src/drivers/intel/cavs/hda-dma.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/drivers/intel/cavs/hda-dma.c b/src/drivers/intel/cavs/hda-dma.c index 3f641d130219..19aef1b8fede 100644 --- a/src/drivers/intel/cavs/hda-dma.c +++ b/src/drivers/intel/cavs/hda-dma.c @@ -50,7 +50,9 @@ #define DGCS_GEN BIT(26) #define DGCS_FWCB BIT(23) #define DGCS_BSC BIT(11) -#define DGCS_BOR BIT(10) /* buffer overrun */ +/* NOTE: both XRUN bits are the same, just direction is different */ +#define DGCS_BOR BIT(10) /* buffer overrun (input streams) */ +#define DGCS_BUR BIT(10) /* buffer underrun (output streams) */ #define DGCS_BF BIT(9) /* buffer full */ #define DGCS_BNE BIT(8) /* buffer not empty */ #define DGCS_FIFORDY BIT(5) /* enable FIFO */ @@ -778,19 +780,14 @@ static int hda_dma_remove(struct dma *dma) static int hda_dma_link_check_xrun(struct dma_chan_data *chan) { - uint32_t dgcs; + uint32_t dgcs = dma_chan_reg_read(chan, DGCS); - if (chan->direction == DMA_DIR_MEM_TO_DEV || - chan->direction == DMA_DIR_DEV_TO_MEM) { - /* check for link xruns */ - dgcs = dma_chan_reg_read(chan, DGCS); - if (dgcs & DGCS_BOR) { - trace_hddma_error("hda_dma_link_check_xrun() error: " - "xrun detected"); - dma_chan_reg_update_bits(chan, DGCS, DGCS_BOR, - DGCS_BOR); - return -ENODATA; - } + if (chan->direction == DMA_DIR_MEM_TO_DEV && dgcs & DGCS_BUR) { + trace_hddma_error("hda_dma_link_check_xrun() error: underrun detected"); + dma_chan_reg_update_bits(chan, DGCS, DGCS_BUR, DGCS_BUR); + } else if (chan->direction == DMA_DIR_DEV_TO_MEM && dgcs & DGCS_BOR) { + trace_hddma_error("hda_dma_link_check_xrun() error: overrun detected"); + dma_chan_reg_update_bits(chan, DGCS, DGCS_BOR, DGCS_BOR); } return 0;