Commit 346f59d1 authored by Alexander Tsoy's avatar Alexander Tsoy Committed by Takashi Iwai

ALSA: usb-audio: Check presence of valid altsetting control

Many devices with a single alternate setting do not have a Valid
Alternate Setting Control and validation performed by
validate_sample_rate_table_v2v3() doesn't work on them and is not
really needed. So check the presense of control before sending
altsetting validation requests.

MOTU Microbook IIc is suffering the most without this check. It
takes up to 40 seconds to bootup due to how slow it switches
sampling rates:

[ 2659.164824] usb 3-2: New USB device found, idVendor=07fd, idProduct=0004, bcdDevice= 0.60
[ 2659.164827] usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 2659.164829] usb 3-2: Product: MicroBook IIc
[ 2659.164830] usb 3-2: Manufacturer: MOTU
[ 2659.166204] usb 3-2: Found last interface = 3
[ 2679.322298] usb 3-2: No valid sample rate available for 1:1, assuming a firmware bug
[ 2679.322306] usb 3-2: 1:1: add audio endpoint 0x3
[ 2679.322321] usb 3-2: Creating new data endpoint #3
[ 2679.322552] usb 3-2: 1:1 Set sample rate 96000, clock 1
[ 2684.362250] usb 3-2: 2:1: cannot get freq (v2/v3): err -110
[ 2694.444700] usb 3-2: No valid sample rate available for 2:1, assuming a firmware bug
[ 2694.444707] usb 3-2: 2:1: add audio endpoint 0x84
[ 2694.444721] usb 3-2: Creating new data endpoint #84
[ 2699.482103] usb 3-2: 2:1 Set sample rate 96000, clock 1
Signed-off-by: default avatarAlexander Tsoy <alexander@tsoy.me>
Link: https://lore.kernel.org/r/20240129121254.3454481-1-alexander@tsoy.meSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent c0787fcf
...@@ -470,9 +470,11 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, ...@@ -470,9 +470,11 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
int clock) int clock)
{ {
struct usb_device *dev = chip->dev; struct usb_device *dev = chip->dev;
struct usb_host_interface *alts;
unsigned int *table; unsigned int *table;
unsigned int nr_rates; unsigned int nr_rates;
int i, err; int i, err;
u32 bmControls;
/* performing the rate verification may lead to unexpected USB bus /* performing the rate verification may lead to unexpected USB bus
* behavior afterwards by some unknown reason. Do this only for the * behavior afterwards by some unknown reason. Do this only for the
...@@ -481,6 +483,24 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, ...@@ -481,6 +483,24 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
if (!(chip->quirk_flags & QUIRK_FLAG_VALIDATE_RATES)) if (!(chip->quirk_flags & QUIRK_FLAG_VALIDATE_RATES))
return 0; /* don't perform the validation as default */ return 0; /* don't perform the validation as default */
alts = snd_usb_get_host_interface(chip, fp->iface, fp->altsetting);
if (!alts)
return 0;
if (fp->protocol == UAC_VERSION_3) {
struct uac3_as_header_descriptor *as = snd_usb_find_csint_desc(
alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
bmControls = le32_to_cpu(as->bmControls);
} else {
struct uac2_as_header_descriptor *as = snd_usb_find_csint_desc(
alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
bmControls = as->bmControls;
}
if (!uac_v2v3_control_is_readable(bmControls,
UAC2_AS_VAL_ALT_SETTINGS))
return 0;
table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL); table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL);
if (!table) if (!table)
return -ENOMEM; return -ENOMEM;
......
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