[PATCH 3/3] ASoC: Update pointer to account for pending dma transfers.

Padmavathi Venna padma.v at samsung.com
Wed Sep 11 02:08:05 EDT 2013


From: Dylan Reid <dgreid at chromium.org>

Make dma_pointer check how much of the current dma transfer has
completed.  This improves the accuracy of the pointer operation, which
previously was only updated once a period.  Before this change calling
snd_pcm_avail() right before a dma transfer completed would indicate
that the entire transfer was still pending, now it will indicate the
actual count of free frames.

If the dma being used doesn't support the residue operation to query a
pending transfer, then assume that no bytes have been transfered.  This
leads to the same behavior as before the change.

Signed-off-by: Dylan Reid <dgreid at chromium.org>
Reviewed-by: Olof Johansson <olofj at chromium.org>
Signed-off-by: Padmavathi Venna <padma.v at samsung.com>
---
 sound/soc/samsung/dma.c |   27 +++++++++++++++++++--------
 1 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 21b7926..6b2e55d 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -271,13 +271,24 @@ dma_pointer(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct runtime_data *prtd = runtime->private_data;
-	unsigned long res;
+	unsigned long offset;
+	unsigned long xfd; /* Number of bytes transfered by current dma. */
+	unsigned int ret = 0;
 
 	pr_debug("Entered %s\n", __func__);
 
-	res = prtd->dma_pos - prtd->dma_start;
+	/* If we can inspect how much of the transfer is left, use that for a
+	 * more accurate number.  Otherwise, assume no bytes have been
+	 * transfered.
+	 */
+	if (prtd->params->ops->residue)
+		ret = prtd->params->ops->residue(prtd->params->ch);
+
+	spin_lock(&prtd->lock);
+	xfd = prtd->dma_period - ret;
 
-	pr_debug("Pointer offset: %lu\n", res);
+	offset = prtd->dma_pos + xfd - prtd->dma_start;
+	spin_unlock(&prtd->lock);
 
 	/* we seem to be getting the odd error from the pcm library due
 	 * to out-of-bounds pointers. this is maybe due to the dma engine
@@ -285,12 +296,12 @@ dma_pointer(struct snd_pcm_substream *substream)
 	 * called... (todo - fix )
 	 */
 
-	if (res >= snd_pcm_lib_buffer_bytes(substream)) {
-		if (res == snd_pcm_lib_buffer_bytes(substream))
-			res = 0;
-	}
+	if (offset >= snd_pcm_lib_buffer_bytes(substream))
+		offset = 0;
+
+	pr_debug("Pointer offset: %lu\n", offset);
 
-	return bytes_to_frames(substream->runtime, res);
+	return bytes_to_frames(substream->runtime, offset);
 }
 
 static int dma_open(struct snd_pcm_substream *substream)
-- 
1.7.4.4




More information about the linux-arm-kernel mailing list