ALSA: usb-audio: add support for Akai MPD16
[safe/jmp/linux-2.6] / sound / core / pcm_lib.c
index 7200195..22aff18 100644 (file)
@@ -148,6 +148,9 @@ static void pcm_debug_name(struct snd_pcm_substream *substream,
 
 #define xrun_debug(substream, mask) \
                        ((substream)->pstr->xrun_debug & (mask))
+#else
+#define xrun_debug(substream, mask)    0
+#endif
 
 #define dump_stack_on_xrun(substream) do {                     \
                if (xrun_debug(substream, XRUN_DEBUG_STACK))    \
@@ -169,6 +172,7 @@ static void xrun(struct snd_pcm_substream *substream)
        }
 }
 
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
 #define hw_ptr_error(substream, fmt, args...)                          \
        do {                                                            \
                if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {          \
@@ -255,8 +259,6 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
 
 #else /* ! CONFIG_SND_PCM_XRUN_DEBUG */
 
-#define xrun_debug(substream, mask)    0
-#define xrun(substream)                        do { } while (0)
 #define hw_ptr_error(substream, fmt, args...) do { } while (0)
 #define xrun_log(substream, pos)       do { } while (0)
 #define xrun_log_show(substream)       do { } while (0)
@@ -285,8 +287,8 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
                        return -EPIPE;
                }
        }
-       if (!runtime->nowake && avail >= runtime->control->avail_min)
-               wake_up(&runtime->sleep);
+       if (avail >= runtime->control->avail_min)
+               wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep);
        return 0;
 }
 
@@ -325,8 +327,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        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;
+               delta = runtime->hw_ptr_interrupt + runtime->period_size;
                if (delta > new_hw_ptr) {
                        hw_base += runtime->buffer_size;
                        if (hw_base >= runtime->boundary)
@@ -437,6 +438,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
            runtime->silence_size > 0)
                snd_pcm_playback_silence(substream, new_hw_ptr);
 
+       if (in_interrupt) {
+               delta = new_hw_ptr - runtime->hw_ptr_interrupt;
+               if (delta < 0)
+                       delta += runtime->boundary;
+               delta -= (snd_pcm_uframes_t)delta % runtime->period_size;
+               runtime->hw_ptr_interrupt += delta;
+               if (runtime->hw_ptr_interrupt >= runtime->boundary)
+                       runtime->hw_ptr_interrupt -= runtime->boundary;
+       }
        runtime->hw_ptr_base = hw_base;
        runtime->status->hw_ptr = new_hw_ptr;
        runtime->hw_ptr_jiffies = jiffies;
@@ -1706,7 +1716,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
        long tout;
 
        init_waitqueue_entry(&wait, current);
-       add_wait_queue(&runtime->sleep, &wait);
+       add_wait_queue(&runtime->tsleep, &wait);
        for (;;) {
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
@@ -1749,7 +1759,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
                        break;
        }
  _endloop:
-       remove_wait_queue(&runtime->sleep, &wait);
+       remove_wait_queue(&runtime->tsleep, &wait);
        *availp = avail;
        return err;
 }
@@ -1808,7 +1818,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
                goto _end_unlock;
        }
 
-       runtime->nowake = 1;
+       runtime->twake = 1;
        while (size > 0) {
                snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
                snd_pcm_uframes_t avail;
@@ -1830,7 +1840,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
                if (frames > cont)
                        frames = cont;
                if (snd_BUG_ON(!frames)) {
-                       runtime->nowake = 0;
+                       runtime->twake = 0;
                        snd_pcm_stream_unlock_irq(substream);
                        return -EINVAL;
                }
@@ -1869,7 +1879,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
                }
        }
  _end_unlock:
-       runtime->nowake = 0;
+       runtime->twake = 0;
        if (xfer > 0 && err >= 0)
                snd_pcm_update_state(substream, runtime);
        snd_pcm_stream_unlock_irq(substream);
@@ -2030,7 +2040,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
                goto _end_unlock;
        }
 
-       runtime->nowake = 1;
+       runtime->twake = 1;
        while (size > 0) {
                snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
                snd_pcm_uframes_t avail;
@@ -2059,7 +2069,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
                if (frames > cont)
                        frames = cont;
                if (snd_BUG_ON(!frames)) {
-                       runtime->nowake = 0;
+                       runtime->twake = 0;
                        snd_pcm_stream_unlock_irq(substream);
                        return -EINVAL;
                }
@@ -2092,7 +2102,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
                xfer += frames;
        }
  _end_unlock:
-       runtime->nowake = 0;
+       runtime->twake = 0;
        if (xfer > 0 && err >= 0)
                snd_pcm_update_state(substream, runtime);
        snd_pcm_stream_unlock_irq(substream);