[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