[Sound-open-firmware] [RFC/RFT] dai: Make system stable by moving DAI buffer pointer update location

Ranjani Sridharan ranjani.sridharan at linux.intel.com
Fri Mar 30 18:42:34 CEST 2018


On Sat, 2018-03-31 at 00:31 +0800, Keyon Jie wrote:
> From: Wu Zhigang <zhigang.wu at linux.intel.com>
> 
> Move the DAI's buffer pointer update location from dai_dma_cb()
> to dai_copy(). This will make pipeline more stable. The xrun
> possibility
> will be lower.Even in xrun it will recover, it will not have dsp
> oops.
> DAI's buffer pointer will be updated in the pipeline copy sequence
> as other components did. Then the DMA will not update the buffer
> pointer
> by itself. in HOST--->VOL--->DAI pipeline, when DMA finished, it has
> to
> reschedule the pipeline to let the pointer update. this could avoid
> the xrun when adjust the read and write pointers by different
> componets.

I may be wrong here but how do we make sure we are always in sync with
the clock rate in this case? 

> 
> Signed-off-by: Wu Zhigang <zhigang.wu at linux.intel.com>
> Tested-by: Keyon Jie <yang.jie at linux.intel.com>
> ---
> Tested on APL-GPMRB
> kernel: sof-v4.14   commit <c33cfed51fff5eb156dcf70ba849e6ffb3008377>
> sof:    1.1-stable  commit <949de92142aa9cdd4a31fda68f05d29212683cc1>
> tools:  1.1-stable  commit <b799e3fa3bab7f5df70f2458bda42de167e65fb3>
> 
> RFT: can someone help test it on byt also?
> 
>  src/audio/dai.c | 108 +++++++++++++++++++++++++++++-----------------
> ----------
>  1 file changed, 56 insertions(+), 52 deletions(-)
> 
> diff --git a/src/audio/dai.c b/src/audio/dai.c
> index e1ea9ab..6d0c1fa 100644
> --- a/src/audio/dai.c
> +++ b/src/audio/dai.c
> @@ -78,7 +78,6 @@ static void dai_dma_cb(void *data, uint32_t type,
> struct dma_sg_elem *next)
>  	struct comp_dev *dev = (struct comp_dev *)data;
>  	struct dai_data *dd = comp_get_drvdata(dev);
>  	struct comp_buffer *dma_buffer;
> -	uint32_t copied_size;
>  
>  	trace_dai("irq");
>  
> @@ -114,57 +113,6 @@ static void dai_dma_cb(void *data, uint32_t
> type, struct dma_sg_elem *next)
>  		return;
>  	}
>  
> -	if (dev->params.direction == SOF_IPC_STREAM_PLAYBACK) {
> -		dma_buffer = list_first_item(&dev->bsource_list,
> -			struct comp_buffer, sink_list);
> -
> -		copied_size = dd->last_bytes ? dd->last_bytes : dd-
> >period_bytes;
> -
> -		/* recalc available buffer space */
> -		comp_update_buffer_consume(dma_buffer, copied_size);
> -
> -		/* writeback buffer contents from cache */
> -		dcache_writeback_region(dma_buffer->r_ptr,
> copied_size);
> -
> -		/* update host position(in bytes offset) for drivers
> */
> -		dev->position += copied_size;
> -		if (dd->dai_pos) {
> -			dd->dai_pos_blks += copied_size;
> -			*dd->dai_pos = dd->dai_pos_blks +
> -				dma_buffer->r_ptr - dma_buffer-
> >addr;
> -		}
> -
> -		/* make sure there is availble bytes for next period
> */
> -		if (dma_buffer->avail < dd->period_bytes) {
> -			trace_dai_error("xru");
> -			comp_underrun(dev, dma_buffer, copied_size,
> 0);
> -		}
> -
> -	} else {
> -		dma_buffer = list_first_item(&dev->bsink_list,
> -			struct comp_buffer, source_list);
> -
> -		/* invalidate buffer contents */
> -		dcache_invalidate_region(dma_buffer->w_ptr, dd-
> >period_bytes);
> -
> -		/* recalc available buffer space */
> -		comp_update_buffer_produce(dma_buffer, dd-
> >period_bytes);
> -
> -		/* update positions */
> -		dev->position += dd->period_bytes;
> -		if (dd->dai_pos) {
> -			dd->dai_pos_blks += dd->period_bytes;
> -			*dd->dai_pos = dd->dai_pos_blks +
> -				dma_buffer->w_ptr - dma_buffer-
> >addr;
> -		}
> -
> -		/* make sure there is free bytes for next period */
> -		if (dma_buffer->free < dd->period_bytes) {
> -			trace_dai_error("xro");
> -			comp_overrun(dev, dma_buffer, dd-
> >period_bytes, 0);
> -		}
> -	}
> -
>  	/* notify pipeline that DAI needs its buffer processed */
>  	if (dev->state == COMP_STATE_ACTIVE)
>  		pipeline_schedule_copy(dev->pipeline, 0);
> @@ -607,6 +555,62 @@ static int dai_comp_trigger(struct comp_dev
> *dev, int cmd)
>  /* copy and process stream data from source to sink buffers */
>  static int dai_copy(struct comp_dev *dev)
>  {
> +	struct dai_data *dd = comp_get_drvdata(dev);
> +	struct comp_buffer *dma_buffer;
> +	uint32_t copied_size;
> +
> +	if (dev->params.direction == SOF_IPC_STREAM_PLAYBACK) {
> +		dma_buffer = list_first_item(&dev->bsource_list,
> +					     struct comp_buffer,
> sink_list);
> +
> +		copied_size = dd->last_bytes ?
> +			dd->last_bytes : dd->period_bytes;
> +
> +		/* recalc available buffer space */
> +		comp_update_buffer_consume(dma_buffer, copied_size);
> +
> +		/* writeback buffer contents from cache */
> +		dcache_writeback_region(dma_buffer->r_ptr,
> copied_size);
> +
> +		/* update host position(in bytes offset) for drivers
> */
> +		dev->position += copied_size;
> +		if (dd->dai_pos) {
> +			dd->dai_pos_blks += copied_size;
> +			*dd->dai_pos = dd->dai_pos_blks +
> +				dma_buffer->r_ptr - dma_buffer-
> >addr;
> +		}
> +
> +		/* make sure there is available bytes for next
> period */
> +		if (dma_buffer->avail < dd->period_bytes) {
> +			trace_dai_error("xru");
> +			comp_underrun(dev, dma_buffer, copied_size,
> 0);
> +		}
> +
> +	} else {
> +		dma_buffer = list_first_item(&dev->bsink_list,
> +					     struct comp_buffer,
> source_list);
> +
> +		/* invalidate buffer contents */
> +		dcache_invalidate_region(dma_buffer->w_ptr, dd-
> >period_bytes);
> +
> +		/* recalc available buffer space */
> +		comp_update_buffer_produce(dma_buffer, dd-
> >period_bytes);
> +
> +		/* update positions */
> +		dev->position += dd->period_bytes;
> +		if (dd->dai_pos) {
> +			dd->dai_pos_blks += dd->period_bytes;
> +			*dd->dai_pos = dd->dai_pos_blks +
> +				dma_buffer->w_ptr - dma_buffer-
> >addr;
> +		}
> +
> +		/* make sure there is free bytes for next period */
> +		if (dma_buffer->free < dd->period_bytes) {
> +			trace_dai_error("xro");
> +			comp_overrun(dev, dma_buffer, dd-
> >period_bytes, 0);
> +		}
> +	}
> +
>  	return 0;
>  }
>  


More information about the Sound-open-firmware mailing list