[Sound-open-firmware] [PATCH 2/2] host: fix the increment offset in the callback

Keyon Jie yang.jie at linux.intel.com
Thu Dec 29 10:29:01 CET 2016


When the host buffer is not 1ms aligned and splitting happens,
the increment is not period size, this wrong pointer will make
pcm data missed/clipped and sound noisy.

Changing to use the actual size last dma copy consumed,
local_elem->size, to fix the issue.

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

diff --git a/src/audio/host.c b/src/audio/host.c
index f339bc2..fe43cf8 100644
--- a/src/audio/host.c
+++ b/src/audio/host.c
@@ -117,6 +117,37 @@ static void host_dma_cb_playback(struct comp_dev *dev,
 
 	trace_host("Cpp");
 
+	/* update buffer positions */
+	dma_buffer = hd->dma_buffer;
+
+	dma_buffer->w_ptr += local_elem->size;
+
+	if (dma_buffer->w_ptr >= dma_buffer->end_addr)
+		dma_buffer->w_ptr = dma_buffer->addr;
+
+#if 0
+	trace_value((uint32_t)(hd->dma_buffer->w_ptr - hd->dma_buffer->addr));
+#endif
+
+	/* recalc available buffer space */
+	comp_update_buffer(hd->dma_buffer);
+
+	/* new local period, update host buffer position blks */
+	hd->host_pos_blks += local_elem->size;
+
+	/* buffer overlap ? */
+	if (hd->host_pos_blks >= hd->host_size)
+		hd->host_pos_blks = 0;
+	if (hd->host_pos)
+		*hd->host_pos = hd->host_pos_blks;
+
+	/* send IPC message to driver if needed */
+	hd->host_period_pos += local_elem->size;
+	if (hd->host_period_pos >= hd->host_period_bytes) {
+		hd->host_period_pos = 0;
+		ipc_stream_send_notification(dev, &hd->cp);
+	}
+
 	/* are we dealing with a split transfer */
 	if (hd->split_remaining) {
 
@@ -161,36 +192,6 @@ static void host_dma_cb_playback(struct comp_dev *dev,
 		}
 	}
 
-	/* update buffer positions */
-	dma_buffer = hd->dma_buffer;
-
-	dma_buffer->w_ptr += hd->period->size;
-
-	if (dma_buffer->w_ptr >= dma_buffer->end_addr)
-		dma_buffer->w_ptr = dma_buffer->addr;
-#if 0
-	trace_value((uint32_t)(hd->dma_buffer->w_ptr - hd->dma_buffer->addr));
-#endif
-
-	/* new local period, update host buffer position blks */
-	hd->host_pos_blks += hd->period->size;
-
-	/* buffer overlap ? */
-	if (hd->host_pos_blks >= hd->host_size)
-		hd->host_pos_blks = 0;
-	if (hd->host_pos)
-		*hd->host_pos = hd->host_pos_blks;
-
-	/* recalc available buffer space */
-	comp_update_buffer(hd->dma_buffer);
-
-	/* send IPC message to driver if needed */
-	hd->host_period_pos += hd->period->size;
-	if (hd->host_period_pos >= hd->host_period_bytes) {
-		hd->host_period_pos = 0;
-		ipc_stream_send_notification(dev, &hd->cp);
-	}
-
 	/* let any waiters know we have completed */
 	wait_completed(&hd->complete);
 }
@@ -215,6 +216,35 @@ static void host_dma_cb_capture(struct comp_dev *dev,
 
 	trace_host("Cpc");
 
+	/* update buffer positions */
+	dma_buffer = hd->dma_buffer;
+	hd->dma_buffer->r_ptr += local_elem->size;
+
+	if (dma_buffer->r_ptr >= dma_buffer->end_addr)
+		dma_buffer->r_ptr = dma_buffer->addr;
+#if 0
+	trace_value((uint32_t)(hd->dma_buffer->r_ptr - hd->dma_buffer->addr));
+#endif
+
+	/* new local period, update host buffer position blks */
+	hd->host_pos_blks += local_elem->size;
+
+	/* buffer overlap ? */
+	if (hd->host_pos_blks >= hd->host_size)
+		hd->host_pos_blks = 0;
+	if (hd->host_pos)
+		*hd->host_pos = hd->host_pos_blks;
+
+	/* recalc available buffer space */
+	comp_update_buffer(hd->dma_buffer);
+
+	/* send IPC message to driver if needed */
+	hd->host_period_pos += local_elem->size;
+	if (hd->host_period_pos >= hd->host_period_bytes) {
+		hd->host_period_pos = 0;
+		ipc_stream_send_notification(dev, &hd->cp);
+	}
+
 	/* are we dealing with a split transfer */
 	if (hd->split_remaining) {
 
@@ -259,36 +289,6 @@ static void host_dma_cb_capture(struct comp_dev *dev,
 		}
 	}
 
-	/* update buffer positions */
-	dma_buffer = hd->dma_buffer;
-	hd->dma_buffer->r_ptr += hd->period->size;
-
-	if (dma_buffer->r_ptr >= dma_buffer->end_addr)
-		dma_buffer->r_ptr = dma_buffer->addr;
-#if 0
-	trace_value((uint32_t)(hd->dma_buffer->r_ptr - hd->dma_buffer->addr));
-#endif
-
-
-	/* new local period, update host buffer position blks */
-	hd->host_pos_blks += hd->period->size;
-
-	/* buffer overlap ? */
-	if (hd->host_pos_blks >= hd->host_size)
-		hd->host_pos_blks = 0;
-	if (hd->host_pos)
-		*hd->host_pos = hd->host_pos_blks;
-
-	/* recalc available buffer space */
-	comp_update_buffer(hd->dma_buffer);
-
-	/* send IPC message to driver if needed */
-	hd->host_period_pos += hd->period->size;
-	if (hd->host_period_pos >= hd->host_period_bytes) {
-		hd->host_period_pos = 0;
-		ipc_stream_send_notification(dev, &hd->cp);
-	}
-
 	/* let any waiters know we have completed */
 	wait_completed(&hd->complete);
 }
-- 
2.5.0



More information about the Sound-open-firmware mailing list