[Sound-open-firmware] [PATCH v3 01/27] host: handle more possibility for playback spitting

Keyon Jie yang.jie at linux.intel.com
Sat Feb 11 03:17:41 CET 2017


We may meet src buffer bound, sink buffer bound, and
splitting may not finish at one time DMA copy, that
is, next_size < split_remaining, ...

This patch added to handle all of those cases, and
prepare for the buffer read/write pointer checking
in future.

Signed-off-by: Keyon Jie <yang.jie at linux.intel.com>
---
 src/audio/host.c | 63 ++++++++++++++++++++++++++------------------------------
 1 file changed, 29 insertions(+), 34 deletions(-)

diff --git a/src/audio/host.c b/src/audio/host.c
index 217ad4f..5fc99fa 100644
--- a/src/audio/host.c
+++ b/src/audio/host.c
@@ -111,6 +111,7 @@ static void host_dma_cb_playback(struct comp_dev *dev,
 	struct host_data *hd = comp_get_drvdata(dev);
 	struct dma_sg_elem *local_elem, *source_elem, *sink_elem;
 	struct comp_buffer *dma_buffer;
+	uint32_t next_size;
 
 	local_elem = list_first_item(&hd->config.elem_list,
 		struct dma_sg_elem, list);
@@ -148,48 +149,42 @@ static void host_dma_cb_playback(struct comp_dev *dev,
 		ipc_stream_send_notification(dev, &hd->cp);
 	}
 
-	/* are we dealing with a split transfer */
-	if (hd->split_remaining) {
-
-		/* update local elem */
-		local_elem->dest += local_elem->size;
+	local_elem->src += local_elem->size;
+	local_elem->dest += local_elem->size;
+	if (local_elem->src == hd->source->current_end) {
+		/* end of elem, so use next */
 		source_elem = next_buffer(hd->source);
 		hd->source->current_end = source_elem->src + source_elem->size;
 		local_elem->src = source_elem->src;
-
-		/* set up next elem */
-		local_elem->size = hd->split_remaining;
-		hd->next_inc = hd->split_remaining;
-		hd->split_remaining = 0;
-
-	} else {
-		/* destination is always DSP period size */
+	}
+	if (local_elem->dest == hd->sink->current_end) {
+		/* end of elem, so use next */
 		sink_elem = next_buffer(hd->sink);
-
+		hd->sink->current_end = sink_elem->dest + sink_elem->size;
 		local_elem->dest = sink_elem->dest;
-		local_elem->size = hd->period->size;
-		local_elem->src += hd->next_inc;
-		hd->next_inc = hd->period->size;
-
-		/* are we at end of elem */
-		if (local_elem->src == hd->source->current_end) {
-
-			/* end of elem, so use next */
-			source_elem = next_buffer(hd->source);
-			hd->source->current_end = source_elem->src + source_elem->size;
-			local_elem->src = source_elem->src;
+	}
 
-		} else if (local_elem->src + hd->period->size > hd->source->current_end) {
+	next_size = hd->period->size;
+	if (local_elem->src + hd->period->size > hd->source->current_end)
+		next_size = hd->source->current_end - local_elem->src;
+	if (local_elem->dest + next_size > hd->sink->current_end)
+		next_size = hd->sink->current_end - local_elem->dest;
 
-			/* split copy - split transaction into 2 copies */
-			local_elem->size = hd->source->current_end - local_elem->src;
-			hd->split_remaining = hd->period->size - local_elem->size;
+	if (!hd->split_remaining) {
+		if (next_size != hd->period->size)
+			hd->split_remaining = hd->period->size - next_size;
+	} else {
+		next_size = next_size < hd->split_remaining ?
+			next_size : hd->split_remaining;
+		hd->split_remaining -= next_size;
+	}
+	local_elem->size = next_size;
 
-			next->src = local_elem->src;
-			next->dest = local_elem->dest;
-			next->size = local_elem->size;
-			return;
-		}
+	if (hd->split_remaining) {
+		next->src = local_elem->src;
+		next->dest = local_elem->dest;
+		next->size = local_elem->size;
+		return;
 	}
 
 	/* let any waiters know we have completed */
-- 
2.7.4



More information about the Sound-open-firmware mailing list