[alsa-devel] Breakage in pcm_lib.c
Jaroslav Kysela
perex at perex.cz
Sun Apr 26 10:12:42 CEST 2009
On Sat, 25 Apr 2009, Jon Smirl wrote:
> 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
Could you show real values what you're getting here with your driver?
The buffer_size is always a wrap point. For example:
buffer_size = 4096
period_size = 1536
hw_ptr_interrupt => 1536, 3072, 4608
For example, if we receive update_hw_interrupt for second period
late when pos (.pointer callback) = 100 and hw_ptr_interrupt = 3072
(hw_base is 0 at the moment):
new_hw_ptr = 100
hw_ptr_interrupt = 3072
delta = -2972
delta += buffer_size -> delta = 1124 - seems correct
Appearently, your .pointer callback returns wrong values.
> 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
hw_base is always aligned to buffer_size (start of ring buffer)
> delta = jiffies - s->jiffies; /* s->jiffies recorded at DMA
> interrrupt at end of buffer */
> delta = delta * runtime->rate / HZ;
Using jiffies to correct stream position seems correct to me.
Jaroslav
-----
Jaroslav Kysela <perex at perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.
More information about the Alsa-devel
mailing list