summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-13 12:14:07 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-29 09:47:53 -0700
commite999dc50404d401150a5429b6459473a691fd1a0 (patch)
tree7715fe9e51e7591a16c8c133b1c1347927ba9147
parent53dea36c70c1857149a8c447224e3936eb8b5339 (diff)
downloadlinux-e999dc50404d401150a5429b6459473a691fd1a0.tar.gz
linux-e999dc50404d401150a5429b6459473a691fd1a0.tar.bz2
linux-e999dc50404d401150a5429b6459473a691fd1a0.zip
ASoC: Fix Blackfin I2S _pointer() implementation return in bounds values
The Blackfin DMA controller can report one frame beyond the end of the buffer in the wraparound case but ALSA requires that the pointer always be in the buffer. Do the wraparound to handle this. A similar bug is likely to apply to the other Blackfin PCM drivers but the code is less obvious to inspection and I don't have a user to test. Reported-by: Kieran O'Leary <Kieran.O'Leary@wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Cc: stable@kernel.org
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index b5101efd1c87..f1fd95bb6416 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -138,11 +138,20 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
pr_debug("%s enter\n", __func__);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
diff = sport_curr_offset_tx(sport);
- frames = bytes_to_frames(substream->runtime, diff);
} else {
diff = sport_curr_offset_rx(sport);
- frames = bytes_to_frames(substream->runtime, diff);
}
+
+ /*
+ * TX at least can report one frame beyond the end of the
+ * buffer if we hit the wraparound case - clamp to within the
+ * buffer as the ALSA APIs require.
+ */
+ if (diff == snd_pcm_lib_buffer_bytes(substream))
+ diff = 0;
+
+ frames = bytes_to_frames(substream->runtime, diff);
+
return frames;
}