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@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;