Commit eee5d6f1 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: usb-audio: Switch back to non-latency mode at a later point

The recent regression report revealed that the judgment of the
low-latency playback mode based on the runtime->stop_threshold cannot
work reliably at the prepare stage, as sw_params call may happen at
any time, and PCM dmix actually sets it up after the prepare call.
This ended up with the stall of the stream as PCM ack won't be issued
at all.

For addressing this, check the free-wheeling mode again at the PCM
trigger right before starting the stream again, and allow switching to
the non-LL mode at a late stage.

Fixes: d5f871f8 ("ALSA: usb-audio: Improved lowlatency playback support")
Reported-and-tested-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Link: https://lore.kernel.org/r/20211117161855.m45mxcqszkfcetai@box.shutemov.name
Link: https://lore.kernel.org/r/20211119102459.7055-1-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 76c47183
......@@ -581,6 +581,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
return 0;
}
/* free-wheeling mode? (e.g. dmix) */
static int in_free_wheeling_mode(struct snd_pcm_runtime *runtime)
{
return runtime->stop_threshold > runtime->buffer_size;
}
/* check whether early start is needed for playback stream */
static int lowlatency_playback_available(struct snd_pcm_runtime *runtime,
struct snd_usb_substream *subs)
......@@ -592,8 +598,7 @@ static int lowlatency_playback_available(struct snd_pcm_runtime *runtime,
/* disabled via module option? */
if (!chip->lowlatency)
return false;
/* free-wheeling mode? (e.g. dmix) */
if (runtime->stop_threshold > runtime->buffer_size)
if (in_free_wheeling_mode(runtime))
return false;
/* implicit feedback mode has own operation mode */
if (snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint))
......@@ -1552,6 +1557,8 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
subs);
if (subs->lowlatency_playback &&
cmd == SNDRV_PCM_TRIGGER_START) {
if (in_free_wheeling_mode(substream->runtime))
subs->lowlatency_playback = false;
err = start_endpoints(subs);
if (err < 0) {
snd_usb_endpoint_set_callback(subs->data_endpoint,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment