ALSA: pcm: simplify top-up mode init in snd_pcm_playback_silence()
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Fri, 5 May 2023 15:52:43 +0000 (17:52 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 5 May 2023 16:23:52 +0000 (18:23 +0200)
Inline the remaining call of snd_pcm_playback_hw_avail(). This makes
the top-up branch more congruent with the thresholded one, and allows
simplifying the handling of the corner cases.

Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Link: https://lore.kernel.org/r/20230505155244.2312199-6-oswald.buddenhagen@gmx.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/pcm_lib.c

index 670572c9a8cc789803d80ab506991698beea2f7a..17fc80a654bea77392f68d2264a54a7a0c936acd 100644 (file)
@@ -90,15 +90,32 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
                 * This filling mode aims at free-running mode (used for example by dmix),
                 * which doesn't update the application pointer.
                 */
-               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;
+               snd_pcm_uframes_t hw_ptr = runtime->status->hw_ptr;
+               if (new_hw_ptr == ULONG_MAX) {
+                       /*
+                        * Initialization, fill the whole unused buffer with silence.
+                        *
+                        * Usually, this is entered while stopped, before data is queued,
+                        * so both pointers are expected to be zero.
+                        */
+                       snd_pcm_sframes_t avail = runtime->control->appl_ptr - hw_ptr;
+                       if (avail < 0)
+                               avail += runtime->boundary;
+                       /*
+                        * In free-running mode, appl_ptr will be zero even while running,
+                        * so we end up with a huge number. There is no useful way to
+                        * handle this, so we just clear the whole buffer.
+                        */
+                       runtime->silence_filled = avail > runtime->buffer_size ? 0 : avail;
+                       runtime->silence_start = hw_ptr;
                } else {
-                       update_silence_vars(runtime, runtime->status->hw_ptr, new_hw_ptr);
+                       /* Silence the just played area immediately */
+                       update_silence_vars(runtime, hw_ptr, new_hw_ptr);
                }
+               /*
+                * In this mode, silence_filled actually includes the valid
+                * sample data from the user.
+                */
                frames = runtime->buffer_size - runtime->silence_filled;
        }
        if (snd_BUG_ON(frames > runtime->buffer_size))