ALSA: pcm - Fix delta calculation at boundary overlap
authorTakashi Iwai <tiwai@suse.de>
Thu, 19 Mar 2009 09:08:49 +0000 (10:08 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 19 Mar 2009 09:08:49 +0000 (10:08 +0100)
When the hw_ptr_interrupt reaches the boundary, it must check whether
the hw_base was already lapped and corret the delta value appropriately.

Also, rebasing the hw_ptr needs a correction because buffer_size isn't
always aligned to period_size.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/pcm_lib.c

index 92ed6d819225c48fb4f086796148afe30c166cde..063c675177a9dc53f12c84a0c297e20b48d5127b 100644 (file)
@@ -221,8 +221,11 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
        new_hw_ptr = hw_base + pos;
        hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
        delta = new_hw_ptr - hw_ptr_interrupt;
-       if (hw_ptr_interrupt == runtime->boundary)
-               hw_ptr_interrupt = 0;
+       if (hw_ptr_interrupt >= runtime->boundary) {
+               hw_ptr_interrupt %= runtime->boundary;
+               if (!hw_base) /* hw_base was already lapped; recalc delta */
+                       delta = new_hw_ptr - hw_ptr_interrupt;
+       }
        if (delta < 0) {
                delta += runtime->buffer_size;
                if (delta < 0) {
@@ -233,6 +236,8 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
                                     (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->buffer_size;