dai: fix xrun handling

Fixes xrun handling by moving check from callback
to copy. Check in callback wasn't making any sense,
because bytes passed there have been already calculated
based on avail/free.

Signed-off-by: Tomasz Lauda <tomasz.lauda@linux.intel.com>
This commit is contained in:
Tomasz Lauda 2019-06-07 10:17:26 +02:00 committed by Liam Girdwood
parent 7546c0fdeb
commit 95372a0bb0
1 changed files with 34 additions and 18 deletions

View File

@ -101,29 +101,11 @@ static void dai_buffer_process(struct comp_dev *dev, struct dma_sg_elem *next)
}
if (dev->params.direction == SOF_IPC_STREAM_PLAYBACK) {
/* make sure there are available bytes for next period */
if (dd->dma_buffer->avail < bytes) {
trace_dai_error_with_ids(dev, "dai_buffer_process() "
"error: Insufficient bytes for"
" next period. "
"comp_underrun()");
comp_underrun(dev, dd->dma_buffer, bytes, 0);
}
/* recalc available buffer space */
comp_update_buffer_consume(dd->dma_buffer, bytes);
buffer_ptr = dd->dma_buffer->r_ptr;
} else {
/* make sure there are free bytes for next period */
if (dd->dma_buffer->free < bytes) {
trace_dai_error_with_ids(dev, "dai_buffer_process() "
"error: Insufficient free "
"bytes for next period. "
"comp_overrun()");
comp_overrun(dev, dd->dma_buffer, bytes, 0);
}
/* recalc available buffer space */
comp_update_buffer_produce(dd->dma_buffer, bytes);
@ -558,6 +540,35 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd)
return ret;
}
/* check if xrun occurred */
static int dai_check_for_xrun(struct comp_dev *dev, uint32_t copy_bytes)
{
struct dai_data *dd = comp_get_drvdata(dev);
/* data available for copy */
if (copy_bytes)
return 0;
/* no data yet, we're just starting */
if (!dev->position)
return PPL_STATUS_PATH_STOP;
/* xrun occurred */
if (dev->params.direction == SOF_IPC_STREAM_PLAYBACK) {
trace_dai_error_with_ids(dev, "dai_check_for_xrun() "
"error: underrun due to no data "
"available");
comp_underrun(dev, dd->dma_buffer, copy_bytes, 0);
} else {
trace_dai_error_with_ids(dev, "dai_check_for_xrun() "
"error: overrun due to no data "
"available");
comp_overrun(dev, dd->dma_buffer, copy_bytes, 0);
}
return -ENODATA;
}
/* copy and process stream data from source to sink buffers */
static int dai_copy(struct comp_dev *dev)
{
@ -595,6 +606,11 @@ static int dai_copy(struct comp_dev *dev)
tracev_dai_with_ids(dev, "dai_copy(), copy_bytes = 0x%x", copy_bytes);
/* check for underrun or overrun */
ret = dai_check_for_xrun(dev, copy_bytes);
if (ret < 0 || ret == PPL_STATUS_PATH_STOP)
return ret;
ret = dma_copy(dd->dma, dd->chan, copy_bytes, 0);
if (ret < 0)
trace_dai_error("dai_copy() error: ret = %u", ret);