On Mon, 29 Aug 2022 14:16:27 +0200, Takashi Iwai wrote:
On Mon, 29 Aug 2022 10:50:58 +0200, chihhao chen wrote:
Hi Takashi,
Yes.
To issue SAMPLING_FREQ_CONTROL USB request two times is root cause of this issue.
Hm, is it a UAC1 device? Such a device should work with multiple SAMPLING_FREQ_CONTROL invocations, but some device might be not tolerant or buggy... The multiple init_sample_rate() invocations may happen with the older kernel under certain situations, so maybe we need a different fix.
How about the patch like below?
It's missing the clearance for suspend/resume. The revised patch is below.
Takashi
-- 8< -- diff --git a/sound/usb/card.h b/sound/usb/card.h index ca75f2206170..507cd62f0ff8 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -134,6 +134,7 @@ struct snd_usb_endpoint { /* for hw constraints */ const struct audioformat *cur_audiofmt; unsigned int cur_rate; + unsigned int cur_rate_setup; snd_pcm_format_t cur_format; unsigned int cur_channels; unsigned int cur_frame_bytes; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 0d7b73bf7945..58ca1f920972 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -806,6 +806,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, ep->cur_audiofmt = fp; ep->cur_channels = fp->channels; ep->cur_rate = params_rate(params); + ep->cur_rate_setup = 0; ep->cur_format = params_format(params); ep->cur_frame_bytes = snd_pcm_format_physical_width(ep->cur_format) * ep->cur_channels / 8; @@ -928,6 +929,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, ep->altsetting = 0; ep->cur_audiofmt = NULL; ep->cur_rate = 0; + ep->cur_rate_setup = 0; ep->iface_ref = NULL; ep->clock_ref = NULL; usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num); @@ -943,6 +945,7 @@ void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep) ep->iface_ref->need_setup = true; if (ep->clock_ref) ep->clock_ref->rate = 0; + ep->cur_rate_setup = 0; }
/* @@ -1356,6 +1359,9 @@ static int init_sample_rate(struct snd_usb_audio *chip, struct snd_usb_clock_ref *clock = ep->clock_ref; int err;
+ if (ep->cur_rate == ep->cur_rate_setup) + return 0; + if (clock) { if (atomic_read(&clock->locked)) return 0; @@ -1374,6 +1380,7 @@ static int init_sample_rate(struct snd_usb_audio *chip,
if (clock) clock->rate = ep->cur_rate; + ep->cur_rate_setup = ep->cur_rate; return 0; }