[alsa-devel] Breakage in pcm_lib.c

Jon Smirl jonsmirl at gmail.com
Sun Apr 26 03:48:55 CEST 2009


This appears to be a bug in this code...

	if (delta < 0) {
		delta += runtime->period_size * runtime->periods;

it was adding, buffer_size. But buffer_size is not correct when the
periods don't evenly fit into the buffer

		if (delta < 0) {
			hw_ptr_error(substream,
				     "Unexpected hw_pointer value "
				     "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
				     substream->stream, (long)pos,
				     (long)hw_ptr_interrupt);
			/* rebase to interrupt position */
			hw_base = new_hw_ptr = hw_ptr_interrupt;
			/* align hw_base to buffer_size */
			hw_base -= hw_base % runtime->buffer_size;
			delta = 0;
		} else {
			hw_base += runtime->period_size * runtime->periods;

same here

			if (hw_base >= runtime->boundary)
				hw_base = 0;
			new_hw_ptr = hw_base + pos;
		}
	}

I have my hardware working again with this fix plus an estimator
function for how far the DMA hardware is into the buffer...

static snd_pcm_uframes_t
psc_dma_pcm_pointer(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
	struct psc_dma_stream *s;
	dma_addr_t count;
	snd_pcm_uframes_t frames;
	int delta;

	if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
		s = &psc_dma->capture;
	else
		s = &psc_dma->playback;

	count = s->period_current_pt - s->period_start;

	delta = jiffies - s->jiffies; /* s->jiffies recorded at DMA
interrrupt at end of buffer */
	delta = delta * runtime->rate / HZ;

	frames = bytes_to_frames(substream->runtime, count);
	printk("psc_dma_pcm_pointer pos %ld %d\n", frames, delta);
	return frames + delta;
}


-- 
Jon Smirl
jonsmirl at gmail.com


More information about the Alsa-devel mailing list