diff options
author | Jaroslav Kysela <perex@perex.cz> | 2023-05-05 17:52:39 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2023-05-05 18:23:49 +0200 |
commit | 2fbaa44a59887f9fd70c986f39c4ac9aebd0c8a1 (patch) | |
tree | 8a6603e95047bfb92bd746ec92a5aaa329bae595 /sound | |
parent | d7f5dd9790bbf9c7357672bafb1992ee7aadf45a (diff) | |
download | lwn-2fbaa44a59887f9fd70c986f39c4ac9aebd0c8a1.tar.gz lwn-2fbaa44a59887f9fd70c986f39c4ac9aebd0c8a1.zip |
ALSA: pcm: fix playback silence - use the actual new_hw_ptr for the threshold mode
The snd_pcm_playback_hw_avail() function uses runtime->status->hw_ptr.
Unfortunately, in case when we call this function from snd_pcm_update_hw_ptr0(),
this variable contains the previous hardware pointer. Use the new_hw_ptr
argument to calculate hw_avail (filled samples by the user space) to
correct the threshold comparison.
The new_hw_ptr argument may also be set to ULONG_MAX which means the
initialization phase. In this case, use runtime->status->hw_ptr.
Suggested-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Link: https://lore.kernel.org/r/20230505155244.2312199-2-oswald.buddenhagen@gmx.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/pcm_lib.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 3357ffae635f..6ad67e7e740c 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -63,7 +63,15 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram } if (runtime->silence_filled >= runtime->buffer_size) return; - noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled; + /* initialization outside pointer updates */ + if (new_hw_ptr == ULONG_MAX) + new_hw_ptr = runtime->status->hw_ptr; + /* get hw_avail with the boundary crossing */ + noise_dist = appl_ptr - new_hw_ptr; + if (noise_dist < 0) + noise_dist += runtime->boundary; + /* total noise distance */ + noise_dist += runtime->silence_filled; if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold) return; frames = runtime->silence_threshold - noise_dist; |