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