ALSA: pcm_lib - cleanup & merge hw_ptr update functions
authorJaroslav Kysela <perex@perex.cz>
Tue, 5 Jan 2010 16:19:34 +0000 (17:19 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 7 Jan 2010 14:47:38 +0000 (15:47 +0100)
Do general cleanup in snd_pcm_update_hw_ptr*() routines and merge them.
The main change is hw_ptr_interrupt variable removal to simplify code
logic. This variable can be computed directly from hw_ptr.

Ensure that updated hw_ptr is not lower than previous one (it was possible
with old code in some obscure situations when interrupt was delayed or
the lowlevel driver returns wrong ring buffer position value).

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
include/sound/pcm.h
include/sound/pcm_oss.h
sound/core/oss/pcm_oss.c
sound/core/pcm_lib.c
sound/core/pcm_native.c

index 4e18a6dbe69081ae7a0331c850b5097d3cf7b385..fe1b131842bedd3b7f67106b9b3939f3ece0bd8c 100644 (file)
@@ -271,7 +271,6 @@ struct snd_pcm_runtime {
        int overrange;
        snd_pcm_uframes_t avail_max;
        snd_pcm_uframes_t hw_ptr_base;  /* Position at buffer restart */
-       snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */
        unsigned long hw_ptr_jiffies;   /* Time when hw_ptr is updated */
        snd_pcm_sframes_t delay;        /* extra delay; typically FIFO size */
 
index cc4e226f35fd5b07a4c0aebbea8ea282aa1309b7..760c969d885d542997010ad8486662fc35731088 100644 (file)
@@ -61,7 +61,7 @@ struct snd_pcm_oss_runtime {
        struct snd_pcm_plugin *plugin_first;
        struct snd_pcm_plugin *plugin_last;
 #endif
-       unsigned int prev_hw_ptr_interrupt;
+       unsigned int prev_hw_ptr_period;
 };
 
 struct snd_pcm_oss_file {
index d9c96353121a567b53f040dc1b87207aac40cac4..255ad910077ae906cb4427a120f24ca92d0e9a32 100644 (file)
@@ -632,6 +632,13 @@ static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes)
        return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
 }
 
+static inline
+snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime)
+{
+       snd_pcm_uframes_t ptr = runtime->status->hw_ptr;
+       return ptr - (ptr % runtime->period_size);
+}
+
 /* define extended formats in the recent OSS versions (if any) */
 /* linear formats */
 #define AFMT_S32_LE      0x00001000
@@ -1102,7 +1109,7 @@ static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream)
                return err;
        }
        runtime->oss.prepare = 0;
-       runtime->oss.prev_hw_ptr_interrupt = 0;
+       runtime->oss.prev_hw_ptr_period = 0;
        runtime->oss.period_ptr = 0;
        runtime->oss.buffer_used = 0;
 
@@ -1950,7 +1957,8 @@ static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file)
        return result;
 }
 
-static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, snd_pcm_uframes_t hw_ptr)
+static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream,
+                                     snd_pcm_uframes_t hw_ptr)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_uframes_t appl_ptr;
@@ -1986,7 +1994,8 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
                        if (runtime->oss.trigger)
                                goto _skip1;
                        if (atomic_read(&psubstream->mmap_count))
-                               snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt);
+                               snd_pcm_oss_simulate_fill(psubstream,
+                                               get_hw_ptr_period(runtime));
                        runtime->oss.trigger = 1;
                        runtime->start_threshold = 1;
                        cmd = SNDRV_PCM_IOCTL_START;
@@ -2105,11 +2114,12 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream
        info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
        if (atomic_read(&substream->mmap_count)) {
                snd_pcm_sframes_t n;
-               n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt;
+               delay = get_hw_ptr_period(runtime);
+               n = delay - runtime->oss.prev_hw_ptr_period;
                if (n < 0)
                        n += runtime->boundary;
                info.blocks = n / runtime->period_size;
-               runtime->oss.prev_hw_ptr_interrupt = delay;
+               runtime->oss.prev_hw_ptr_period = delay;
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        snd_pcm_oss_simulate_fill(substream, delay);
                info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
@@ -2673,18 +2683,22 @@ static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (atomic_read(&substream->mmap_count))
-               return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
+               return runtime->oss.prev_hw_ptr_period !=
+                                               get_hw_ptr_period(runtime);
        else
-               return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames;
+               return snd_pcm_playback_avail(runtime) >=
+                                               runtime->oss.period_frames;
 }
 
 static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (atomic_read(&substream->mmap_count))
-               return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
+               return runtime->oss.prev_hw_ptr_period !=
+                                               get_hw_ptr_period(runtime);
        else
-               return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames;
+               return snd_pcm_capture_avail(runtime) >=
+                                               runtime->oss.period_frames;
 }
 
 static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
index 1990afb8a73546b113826a54c6919156c8425197..70a4f7428d7810f52677d2487958dc844a1d2fd3 100644 (file)
@@ -172,6 +172,7 @@ static void xrun(struct snd_pcm_substream *substream)
 #define hw_ptr_error(substream, fmt, args...)                          \
        do {                                                            \
                if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {          \
+                       xrun_log_show(substream);                       \
                        if (printk_ratelimit()) {                       \
                                snd_printd("PCM: " fmt, ##args);        \
                        }                                               \
@@ -188,7 +189,6 @@ struct hwptr_log_entry {
        snd_pcm_uframes_t buffer_size;
        snd_pcm_uframes_t old_hw_ptr;
        snd_pcm_uframes_t hw_ptr_base;
-       snd_pcm_uframes_t hw_ptr_interrupt;
 };
 
 struct snd_pcm_hwptr_log {
@@ -220,7 +220,6 @@ static void xrun_log(struct snd_pcm_substream *substream,
        entry->buffer_size = runtime->buffer_size;;
        entry->old_hw_ptr = runtime->status->hw_ptr;
        entry->hw_ptr_base = runtime->hw_ptr_base;
-       entry->hw_ptr_interrupt = runtime->hw_ptr_interrupt;;
        log->idx = (log->idx + 1) % XRUN_LOG_CNT;
 }
 
@@ -241,14 +240,13 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
                entry = &log->entries[idx];
                if (entry->period_size == 0)
                        break;
-               snd_printd("hwptr log: %s: j=%lu, pos=0x%lx/0x%lx/0x%lx, "
-                          "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
+               snd_printd("hwptr log: %s: j=%lu, pos=%ld/%ld/%ld, "
+                          "hwptr=%ld/%ld\n",
                           name, entry->jiffies, (unsigned long)entry->pos,
                           (unsigned long)entry->period_size,
                           (unsigned long)entry->buffer_size,
                           (unsigned long)entry->old_hw_ptr,
-                          (unsigned long)entry->hw_ptr_base,
-                          (unsigned long)entry->hw_ptr_interrupt);
+                          (unsigned long)entry->hw_ptr_base);
                idx++;
                idx %= XRUN_LOG_CNT;
        }
@@ -265,33 +263,6 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
 
 #endif
 
-static snd_pcm_uframes_t
-snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
-                         struct snd_pcm_runtime *runtime)
-{
-       snd_pcm_uframes_t pos;
-
-       pos = substream->ops->pointer(substream);
-       if (pos == SNDRV_PCM_POS_XRUN)
-               return pos; /* XRUN */
-       if (pos >= runtime->buffer_size) {
-               if (printk_ratelimit()) {
-                       char name[16];
-                       pcm_debug_name(substream, name, sizeof(name));
-                       xrun_log_show(substream);
-                       snd_printd(KERN_ERR  "BUG: %s, pos = 0x%lx, "
-                                  "buffer size = 0x%lx, period size = 0x%lx\n",
-                                  name, pos, runtime->buffer_size,
-                                  runtime->period_size);
-               }
-               pos = 0;
-       }
-       pos -= pos % runtime->min_align;
-       if (xrun_debug(substream, XRUN_DEBUG_LOG))
-               xrun_log(substream, pos);
-       return pos;
-}
-
 static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
                                      struct snd_pcm_runtime *runtime)
 {
@@ -319,72 +290,88 @@ static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
+static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
+                                 unsigned int in_interrupt)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_uframes_t pos;
-       snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interrupt, hw_base;
+       snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
        snd_pcm_sframes_t hdelta, delta;
        unsigned long jdelta;
 
        old_hw_ptr = runtime->status->hw_ptr;
-       pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
+       pos = substream->ops->pointer(substream);
        if (pos == SNDRV_PCM_POS_XRUN) {
                xrun(substream);
                return -EPIPE;
        }
-       if (xrun_debug(substream, XRUN_DEBUG_PERIODUPDATE)) {
-               char name[16];
-               pcm_debug_name(substream, name, sizeof(name));
-               snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, "
-                          "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
-                          name, (unsigned int)pos,
-                          (unsigned int)runtime->period_size,
-                          (unsigned int)runtime->buffer_size,
-                          (unsigned long)old_hw_ptr,
-                          (unsigned long)runtime->hw_ptr_base,
-                          (unsigned long)runtime->hw_ptr_interrupt);
+       if (pos >= runtime->buffer_size) {
+               if (printk_ratelimit()) {
+                       char name[16];
+                       pcm_debug_name(substream, name, sizeof(name));
+                       xrun_log_show(substream);
+                       snd_printd(KERN_ERR  "BUG: %s, pos = %ld, "
+                                  "buffer size = %ld, period size = %ld\n",
+                                  name, pos, runtime->buffer_size,
+                                  runtime->period_size);
+               }
+               pos = 0;
        }
+       pos -= pos % runtime->min_align;
+       if (xrun_debug(substream, XRUN_DEBUG_LOG))
+               xrun_log(substream, pos);
        hw_base = runtime->hw_ptr_base;
        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 -= runtime->boundary;
-               if (hw_base < runtime->boundary / 2)
-                       /* hw_base was already lapped; recalc delta */
-                       delta = new_hw_ptr - hw_ptr_interrupt;
-       }
-       if (delta < 0) {
-               if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr)
-                       delta += runtime->buffer_size;
-               if (delta < 0) {
-                       xrun_log_show(substream);
-                       hw_ptr_error(substream, 
-                                    "Unexpected hw_pointer value "
-                                    "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
-                                    substream->stream, (long)pos,
-                                    (long)hw_ptr_interrupt);
-#if 1
-                       /* simply skipping the hwptr update seems more
-                        * robust in some cases, e.g. on VMware with
-                        * inaccurate timer source
-                        */
-                       return 0; /* skip this update */
-#else
-                       /* 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;
-#endif
-               } else {
+       if (in_interrupt) {
+               /* we know that one period was processed */
+               /* delta = "expected next hw_ptr" for in_interrupt != 0 */
+               delta = old_hw_ptr - (old_hw_ptr % runtime->period_size)
+                       + runtime->period_size;
+               if (delta > new_hw_ptr) {
                        hw_base += runtime->buffer_size;
                        if (hw_base >= runtime->boundary)
                                hw_base = 0;
                        new_hw_ptr = hw_base + pos;
+                       goto __delta;
                }
        }
+       /* new_hw_ptr might be lower than old_hw_ptr in case when */
+       /* pointer crosses the end of the ring buffer */
+       if (new_hw_ptr < old_hw_ptr) {
+               hw_base += runtime->buffer_size;
+               if (hw_base >= runtime->boundary)
+                       hw_base = 0;
+               new_hw_ptr = hw_base + pos;
+       }
+      __delta:
+       delta = (new_hw_ptr - old_hw_ptr) % runtime->boundary;
+       if (xrun_debug(substream, in_interrupt ?
+                       XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) {
+               char name[16];
+               pcm_debug_name(substream, name, sizeof(name));
+               snd_printd("%s_update: %s: pos=%u/%u/%u, "
+                          "hwptr=%ld/%ld/%ld/%ld\n",
+                          in_interrupt ? "period" : "hwptr",
+                          name,
+                          (unsigned int)pos,
+                          (unsigned int)runtime->period_size,
+                          (unsigned int)runtime->buffer_size,
+                          (unsigned long)delta,
+                          (unsigned long)old_hw_ptr,
+                          (unsigned long)new_hw_ptr,
+                          (unsigned long)runtime->hw_ptr_base);
+       }
+       /* something must be really wrong */
+       if (delta >= runtime->buffer_size) {
+               hw_ptr_error(substream,
+                              "Unexpected hw_pointer value %s"
+                              "(stream=%i, pos=%ld, new_hw_ptr=%ld, "
+                              "old_hw_ptr=%ld)\n",
+                                    in_interrupt ? "[Q] " : "[P]",
+                                    substream->stream, (long)pos,
+                                    (long)new_hw_ptr, (long)old_hw_ptr);
+               return 0;
+       }
 
        /* Do jiffies check only in xrun_debug mode */
        if (!xrun_debug(substream, XRUN_DEBUG_JIFFIESCHECK))
@@ -396,7 +383,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
         */
        if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
                goto no_jiffies_check;
-       hdelta = new_hw_ptr - old_hw_ptr;
+       hdelta = delta;
        if (hdelta < runtime->delay)
                goto no_jiffies_check;
        hdelta -= runtime->delay;
@@ -405,45 +392,49 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
                delta = jdelta /
                        (((runtime->period_size * HZ) / runtime->rate)
                                                                + HZ/100);
-               xrun_log_show(substream);
+               /* move new_hw_ptr according jiffies not pos variable */
+               new_hw_ptr = old_hw_ptr;
+               /* use loop to avoid checks for delta overflows */
+               /* the delta value is small or zero in most cases */
+               while (delta > 0) {
+                       new_hw_ptr += runtime->period_size;
+                       if (new_hw_ptr >= runtime->boundary)
+                               new_hw_ptr -= runtime->boundary;
+                       delta--;
+               }
+               /* align hw_base to buffer_size */
+               hw_base = new_hw_ptr - (new_hw_ptr % runtime->buffer_size);
+               delta = 0;
                hw_ptr_error(substream,
-                            "hw_ptr skipping! [Q] "
+                            "hw_ptr skipping! %s"
                             "(pos=%ld, delta=%ld, period=%ld, "
-                            "jdelta=%lu/%lu/%lu)\n",
+                            "jdelta=%lu/%lu/%lu, hw_ptr=%ld/%ld)\n",
+                            in_interrupt ? "[Q] " : "",
                             (long)pos, (long)hdelta,
                             (long)runtime->period_size, jdelta,
-                            ((hdelta * HZ) / runtime->rate), delta);
-               hw_ptr_interrupt = runtime->hw_ptr_interrupt +
-                                  runtime->period_size * delta;
-               if (hw_ptr_interrupt >= runtime->boundary)
-                       hw_ptr_interrupt -= runtime->boundary;
-               /* 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;
+                            ((hdelta * HZ) / runtime->rate), delta,
+                            (unsigned long)old_hw_ptr,
+                            (unsigned long)new_hw_ptr);
        }
  no_jiffies_check:
        if (delta > runtime->period_size + runtime->period_size / 2) {
-               xrun_log_show(substream);
                hw_ptr_error(substream,
-                            "Lost interrupts? "
-                            "(stream=%i, delta=%ld, intr_ptr=%ld)\n",
+                            "Lost interrupts? %s"
+                            "(stream=%i, delta=%ld, new_hw_ptr=%ld, "
+                            "old_hw_ptr=%ld)\n",
+                            in_interrupt ? "[Q] " : "",
                             substream->stream, (long)delta,
-                            (long)hw_ptr_interrupt);
-               /* rebase hw_ptr_interrupt */
-               hw_ptr_interrupt =
-                       new_hw_ptr - new_hw_ptr % runtime->period_size;
+                            (long)new_hw_ptr,
+                            (long)old_hw_ptr);
        }
-       runtime->hw_ptr_interrupt = hw_ptr_interrupt;
+
+       if (runtime->status->hw_ptr == new_hw_ptr)
+               return 0;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
            runtime->silence_size > 0)
                snd_pcm_playback_silence(substream, new_hw_ptr);
 
-       if (runtime->status->hw_ptr == new_hw_ptr)
-               return 0;
-
        runtime->hw_ptr_base = hw_base;
        runtime->status->hw_ptr = new_hw_ptr;
        runtime->hw_ptr_jiffies = jiffies;
@@ -456,83 +447,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
 /* CAUTION: call it with irq disabled */
 int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
 {
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       snd_pcm_uframes_t pos;
-       snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
-       snd_pcm_sframes_t delta;
-       unsigned long jdelta;
-
-       old_hw_ptr = runtime->status->hw_ptr;
-       pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
-       if (pos == SNDRV_PCM_POS_XRUN) {
-               xrun(substream);
-               return -EPIPE;
-       }
-       if (xrun_debug(substream, XRUN_DEBUG_HWPTRUPDATE)) {
-               char name[16];
-               pcm_debug_name(substream, name, sizeof(name));
-               snd_printd("hw_update: %s: pos=0x%x/0x%x/0x%x, "
-                          "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
-                          name, (unsigned int)pos,
-                          (unsigned int)runtime->period_size,
-                          (unsigned int)runtime->buffer_size,
-                          (unsigned long)old_hw_ptr,
-                          (unsigned long)runtime->hw_ptr_base,
-                          (unsigned long)runtime->hw_ptr_interrupt);
-       }
-
-       hw_base = runtime->hw_ptr_base;
-       new_hw_ptr = hw_base + pos;
-
-       delta = new_hw_ptr - old_hw_ptr;
-       jdelta = jiffies - runtime->hw_ptr_jiffies;
-       if (delta < 0) {
-               delta += runtime->buffer_size;
-               if (delta < 0) {
-                       xrun_log_show(substream);
-                       hw_ptr_error(substream, 
-                                    "Unexpected hw_pointer value [2] "
-                                    "(stream=%i, pos=%ld, old_ptr=%ld, jdelta=%li)\n",
-                                    substream->stream, (long)pos,
-                                    (long)old_hw_ptr, jdelta);
-                       return 0;
-               }
-               hw_base += runtime->buffer_size;
-               if (hw_base >= runtime->boundary)
-                       hw_base = 0;
-               new_hw_ptr = hw_base + pos;
-       }
-       /* Do jiffies check only in xrun_debug mode */
-       if (!xrun_debug(substream, XRUN_DEBUG_JIFFIESCHECK))
-               goto no_jiffies_check;
-       if (delta < runtime->delay)
-               goto no_jiffies_check;
-       delta -= runtime->delay;
-       if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
-               xrun_log_show(substream);
-               hw_ptr_error(substream,
-                            "hw_ptr skipping! "
-                            "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
-                            (long)pos, (long)delta,
-                            (long)runtime->period_size, jdelta,
-                            ((delta * HZ) / runtime->rate));
-               return 0;
-       }
- no_jiffies_check:
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
-           runtime->silence_size > 0)
-               snd_pcm_playback_silence(substream, new_hw_ptr);
-
-       if (runtime->status->hw_ptr == new_hw_ptr)
-               return 0;
-
-       runtime->hw_ptr_base = hw_base;
-       runtime->status->hw_ptr = new_hw_ptr;
-       runtime->hw_ptr_jiffies = jiffies;
-       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
-               snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
-
-       return snd_pcm_update_hw_ptr_post(substream, runtime);
+       return snd_pcm_update_hw_ptr0(substream, 0);
 }
 
 /**
@@ -1744,7 +1659,7 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
 
        snd_pcm_stream_lock_irqsave(substream, flags);
        if (!snd_pcm_running(substream) ||
-           snd_pcm_update_hw_ptr_interrupt(substream) < 0)
+           snd_pcm_update_hw_ptr0(substream, 1) < 0)
                goto _end;
 
        if (substream->timer_running)
index 29ab46a12e11cda66ff86a2865c74b9286274761..8e777f71717cc0ddb39dd276f400de67e1d5e5b5 100644 (file)
@@ -1247,8 +1247,6 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
        if (err < 0)
                return err;
        runtime->hw_ptr_base = 0;
-       runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
-               runtime->status->hw_ptr % runtime->period_size;
        runtime->silence_start = runtime->status->hw_ptr;
        runtime->silence_filled = 0;
        return 0;