Draining will always playback somewhat beyond the end of the filled buffer. This would produce artifacts if the user did not set up the auto-silencing machinery. This patch makes it work out of the box.
Rather than figuring out the right threshold (which is one period plus the card-specific FIFO size plus some IRQ jitter), we use "top-up" mode.
Signed-off-by: Oswald Buddenhagen oswald.buddenhagen@gmx.de --- sound/core/pcm_lib.c | 5 +++-- sound/core/pcm_native.c | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index b074c5b926db..1dd870a2093d 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -71,7 +71,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream) }
noise_dist = hw_avail + runtime->silence_filled; - if (runtime->silence_size < runtime->boundary) { + if (runtime->silence_size < runtime->boundary && + runtime->state != SNDRV_PCM_STATE_DRAINING) { frames = runtime->silence_threshold - noise_dist; if ((snd_pcm_sframes_t) frames <= 0) return; @@ -445,7 +446,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, }
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - runtime->silence_size > 0) + (runtime->silence_size > 0 || runtime->state == SNDRV_PCM_STATE_DRAINING)) snd_pcm_playback_silence(substream);
update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0e3e7997dc58..6ecb6a733606 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1454,7 +1454,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, runtime->rate; __snd_pcm_set_state(runtime, state); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - runtime->silence_size > 0) + (runtime->silence_size > 0 || state == SNDRV_PCM_STATE_DRAINING)) snd_pcm_playback_silence(substream); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTART); } @@ -2045,6 +2045,7 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, break; case SNDRV_PCM_STATE_RUNNING: __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_DRAINING); + snd_pcm_playback_silence(substream); break; case SNDRV_PCM_STATE_XRUN: __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SETUP);