diff options
| author | Alexander Tsoy <alexander@tsoy.me> | 2017-08-11 02:36:14 +0300 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2019-08-06 12:48:10 +0200 | 
| commit | f7f530181461aaf6afa0b3f0be4d239dea410896 (patch) | |
| tree | 7b797fc4e4c43f715f49af94585dede1323cdaa7 /sound/usb | |
| parent | c1ae5e7f057beb1daa72831ab22ec06e71669af7 (diff) | |
| download | linux-f7f530181461aaf6afa0b3f0be4d239dea410896.tar.bz2 | |
ALSA: usb-audio: fix PCM device order
Some cards have alternate setting with non-PCM format as the first
altsetting in the interface descriptors. This confuses userspace, since
alsa-lib uses device 0 by default. So lets parse interfaces in two steps:
 1. Parse altsettings with PCM formats.
 2. Parse altsettings with non-PCM formats.
This fixes at least following cards:
 - Audinst HUD-mx2
 - Audinst HUD-mini
[ Adapted to 5.3 kernel by tiwai ]
Signed-off-by: Alexander Tsoy <alexander@tsoy.me>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
| -rw-r--r-- | sound/usb/stream.c | 34 | 
1 files changed, 33 insertions, 1 deletions
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 963d425004f8..fc3e9fcfbc38 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1077,7 +1077,9 @@ found_clock:  	return fp;  } -int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) +static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, +					   int iface_no, +					   bool *has_non_pcm, bool non_pcm)  {  	struct usb_device *dev;  	struct usb_interface *iface; @@ -1178,6 +1180,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)  		else if (IS_ERR(fp))  			return PTR_ERR(fp); +		if (fp->fmt_type != UAC_FORMAT_TYPE_I) +			*has_non_pcm = true; +		if ((fp->fmt_type == UAC_FORMAT_TYPE_I) == non_pcm) { +			audioformat_free(fp); +			kfree(pd); +			fp = NULL; +			pd = NULL; +			continue; +		} +  		dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);  		if (protocol == UAC_VERSION_3)  			err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd); @@ -1197,3 +1209,23 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)  	return 0;  } +int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) +{ +	int err; +	bool has_non_pcm = false; + +	/* parse PCM formats */ +	err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, false); +	if (err < 0) +		return err; + +	if (has_non_pcm) { +		/* parse non-PCM formats */ +		err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, true); +		if (err < 0) +			return err; +	} + +	return 0; +} +  |