[alsa-devel] [PATCH 1/3] ASoC: davinci-pcm: latch EDMA errors

Ben Gardiner bengardiner at nanometrics.ca
Fri Sep 30 23:23:01 CEST 2011


The davinci-pcm driver currently ignores all EDMA completion callbacks that
could be indicating an error.

Latch any edma error-status callbacks and report them as SNDDRV_PCM_POS_XRUN
like is done in fsl_dma.c.

Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>

---

In testing when an error occured early-on in playback the stream did not halt,
but several underruns were reported until eventually the stream halted.

Is there a better way to report HW errors up the stack?
---
 sound/soc/davinci/davinci-pcm.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index d5fe08c..41a3b5b 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -155,6 +155,7 @@ struct davinci_runtime_data {
 	int ram_link2;
 	struct edmacc_param asp_params;
 	struct edmacc_param ram_params;
+	unsigned error:1;
 };
 
 static void davinci_pcm_period_elapsed(struct snd_pcm_substream *substream)
@@ -245,8 +246,12 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
 	print_buf_info(prtd->ram_channel, "i ram_channel");
 	pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status);
 
-	if (unlikely(ch_status != DMA_COMPLETE))
+	if (unlikely(ch_status != DMA_COMPLETE)) {
+		spin_lock(&prtd->lock);
+		prtd->error = 1;
+		spin_unlock(&prtd->lock);
 		return;
+	}
 
 	if (snd_pcm_running(substream)) {
 		spin_lock(&prtd->lock);
@@ -635,7 +640,7 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct davinci_runtime_data *prtd = runtime->private_data;
 	unsigned int offset;
-	int asp_count;
+	int asp_count, error;
 	unsigned int period_size = snd_pcm_lib_period_bytes(substream);
 
 	/*
@@ -647,8 +652,12 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)
 	 */
 	spin_lock(&prtd->lock);
 	asp_count = prtd->period - 2;
+	error = prtd->error;
 	spin_unlock(&prtd->lock);
 
+	if (error)
+		return SNDRV_PCM_POS_XRUN;
+
 	if (asp_count < 0)
 		asp_count += runtime->periods;
 	asp_count *= period_size;
-- 
1.7.4.1



More information about the Alsa-devel mailing list