]> git.itanic.dy.fi Git - linux-stable/commitdiff
ASoC: Fix Blackfin I2S _pointer() implementation return in bounds values
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 13 Jun 2011 11:14:07 +0000 (12:14 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 8 Aug 2011 17:23:06 +0000 (10:23 -0700)
commit e999dc50404d401150a5429b6459473a691fd1a0 upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
sound/soc/blackfin/bf5xx-i2s-pcm.c

index 62fbb8459569a6d78690bbf7b100a3aa47ea745a..77dae1643997d228728c8f072350c42636e6ca7d 100644 (file)
@@ -139,11 +139,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;
 }