Merge branch 'drm-intel-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ickle...
[pandora-kernel.git] / sound / core / pcm_lib.c
index e9d98be..e23e0e7 100644 (file)
@@ -67,6 +67,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
        } else {
                if (new_hw_ptr == ULONG_MAX) {  /* initialization */
                        snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime);
+                       if (avail > runtime->buffer_size)
+                               avail = runtime->buffer_size;
                        runtime->silence_filled = avail > 0 ? avail : 0;
                        runtime->silence_start = (runtime->status->hw_ptr +
                                                  runtime->silence_filled) %
@@ -287,8 +289,11 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
                        return -EPIPE;
                }
        }
-       if (avail >= runtime->control->avail_min)
-               wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep);
+       if (runtime->twake) {
+               if (avail >= runtime->twake)
+                       wake_up(&runtime->tsleep);
+       } else if (avail >= runtime->control->avail_min)
+               wake_up(&runtime->sleep);
        return 0;
 }
 
@@ -1707,7 +1712,7 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed);
  * The available space is stored on availp.  When err = 0 and avail = 0
  * on the capture stream, it indicates the stream is in DRAINING state.
  */
-static int wait_for_avail_min(struct snd_pcm_substream *substream,
+static int wait_for_avail(struct snd_pcm_substream *substream,
                              snd_pcm_uframes_t *availp)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1757,7 +1762,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
                        avail = snd_pcm_playback_avail(runtime);
                else
                        avail = snd_pcm_capture_avail(runtime);
-               if (avail >= runtime->control->avail_min)
+               if (avail >= runtime->twake)
                        break;
        }
  _endloop:
@@ -1820,7 +1825,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
                goto _end_unlock;
        }
 
-       runtime->twake = 1;
+       runtime->twake = runtime->control->avail_min ? : 1;
        while (size > 0) {
                snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
                snd_pcm_uframes_t avail;
@@ -1833,7 +1838,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
                                err = -EAGAIN;
                                goto _end_unlock;
                        }
-                       err = wait_for_avail_min(substream, &avail);
+                       runtime->twake = min_t(snd_pcm_uframes_t, size,
+                                       runtime->control->avail_min ? : 1);
+                       err = wait_for_avail(substream, &avail);
                        if (err < 0)
                                goto _end_unlock;
                }
@@ -2042,7 +2049,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
                goto _end_unlock;
        }
 
-       runtime->twake = 1;
+       runtime->twake = runtime->control->avail_min ? : 1;
        while (size > 0) {
                snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
                snd_pcm_uframes_t avail;
@@ -2060,7 +2067,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
                                err = -EAGAIN;
                                goto _end_unlock;
                        }
-                       err = wait_for_avail_min(substream, &avail);
+                       runtime->twake = min_t(snd_pcm_uframes_t, size,
+                                       runtime->control->avail_min ? : 1);
+                       err = wait_for_avail(substream, &avail);
                        if (err < 0)
                                goto _end_unlock;
                        if (!avail)