xref: /openbmc/linux/sound/usb/stream.c (revision 0db00e5d86dc793aab9722ad3728d99166eb7d96)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e8e8babfSDaniel Mack /*
3e8e8babfSDaniel Mack  */
4e8e8babfSDaniel Mack 
5e8e8babfSDaniel Mack 
6e8e8babfSDaniel Mack #include <linux/init.h>
7e8e8babfSDaniel Mack #include <linux/slab.h>
8e8e8babfSDaniel Mack #include <linux/usb.h>
9e8e8babfSDaniel Mack #include <linux/usb/audio.h>
10e8e8babfSDaniel Mack #include <linux/usb/audio-v2.h>
119a2fe9b8SRuslan Bilovol #include <linux/usb/audio-v3.h>
12e8e8babfSDaniel Mack 
13e8e8babfSDaniel Mack #include <sound/core.h>
14e8e8babfSDaniel Mack #include <sound/pcm.h>
1504324cccSTakashi Iwai #include <sound/control.h>
1604324cccSTakashi Iwai #include <sound/tlv.h>
17e8e8babfSDaniel Mack 
18e8e8babfSDaniel Mack #include "usbaudio.h"
19e8e8babfSDaniel Mack #include "card.h"
20e8e8babfSDaniel Mack #include "proc.h"
21e8e8babfSDaniel Mack #include "quirks.h"
22e8e8babfSDaniel Mack #include "endpoint.h"
23e8e8babfSDaniel Mack #include "pcm.h"
24e8e8babfSDaniel Mack #include "helper.h"
25e8e8babfSDaniel Mack #include "format.h"
26e8e8babfSDaniel Mack #include "clock.h"
27e8e8babfSDaniel Mack #include "stream.h"
287edf3b5eSJorge Sanjuan #include "power.h"
2966354f18SShuah Khan #include "media.h"
30e8e8babfSDaniel Mack 
audioformat_free(struct audioformat * fp)31c1ae5e7fSTakashi Iwai static void audioformat_free(struct audioformat *fp)
32c1ae5e7fSTakashi Iwai {
33c1ae5e7fSTakashi Iwai 	list_del(&fp->list); /* unlink for avoiding double-free */
34c1ae5e7fSTakashi Iwai 	kfree(fp->rate_table);
35c1ae5e7fSTakashi Iwai 	kfree(fp->chmap);
36c1ae5e7fSTakashi Iwai 	kfree(fp);
37c1ae5e7fSTakashi Iwai }
38c1ae5e7fSTakashi Iwai 
39e8e8babfSDaniel Mack /*
40e8e8babfSDaniel Mack  * free a substream
41e8e8babfSDaniel Mack  */
free_substream(struct snd_usb_substream * subs)42e8e8babfSDaniel Mack static void free_substream(struct snd_usb_substream *subs)
43e8e8babfSDaniel Mack {
4488766f04SEldad Zack 	struct audioformat *fp, *n;
45e8e8babfSDaniel Mack 
46e8e8babfSDaniel Mack 	if (!subs->num_formats)
47e8e8babfSDaniel Mack 		return; /* not initialized */
48c1ae5e7fSTakashi Iwai 	list_for_each_entry_safe(fp, n, &subs->fmt_list, list)
49c1ae5e7fSTakashi Iwai 		audioformat_free(fp);
507edf3b5eSJorge Sanjuan 	kfree(subs->str_pd);
5166354f18SShuah Khan 	snd_media_stream_delete(subs);
52e8e8babfSDaniel Mack }
53e8e8babfSDaniel Mack 
54e8e8babfSDaniel Mack 
55e8e8babfSDaniel Mack /*
56e8e8babfSDaniel Mack  * free a usb stream instance
57e8e8babfSDaniel Mack  */
snd_usb_audio_stream_free(struct snd_usb_stream * stream)58e8e8babfSDaniel Mack static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
59e8e8babfSDaniel Mack {
60e8e8babfSDaniel Mack 	free_substream(&stream->substream[0]);
61e8e8babfSDaniel Mack 	free_substream(&stream->substream[1]);
62e8e8babfSDaniel Mack 	list_del(&stream->list);
63e8e8babfSDaniel Mack 	kfree(stream);
64e8e8babfSDaniel Mack }
65e8e8babfSDaniel Mack 
snd_usb_audio_pcm_free(struct snd_pcm * pcm)66e8e8babfSDaniel Mack static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
67e8e8babfSDaniel Mack {
68e8e8babfSDaniel Mack 	struct snd_usb_stream *stream = pcm->private_data;
69e8e8babfSDaniel Mack 	if (stream) {
70e8e8babfSDaniel Mack 		stream->pcm = NULL;
71e8e8babfSDaniel Mack 		snd_usb_audio_stream_free(stream);
72e8e8babfSDaniel Mack 	}
73e8e8babfSDaniel Mack }
74e8e8babfSDaniel Mack 
75edcd3633SDaniel Mack /*
76edcd3633SDaniel Mack  * initialize the substream instance.
77edcd3633SDaniel Mack  */
78edcd3633SDaniel Mack 
snd_usb_init_substream(struct snd_usb_stream * as,int stream,struct audioformat * fp,struct snd_usb_power_domain * pd)79edcd3633SDaniel Mack static void snd_usb_init_substream(struct snd_usb_stream *as,
80edcd3633SDaniel Mack 				   int stream,
817edf3b5eSJorge Sanjuan 				   struct audioformat *fp,
827edf3b5eSJorge Sanjuan 				   struct snd_usb_power_domain *pd)
83edcd3633SDaniel Mack {
84edcd3633SDaniel Mack 	struct snd_usb_substream *subs = &as->substream[stream];
85edcd3633SDaniel Mack 
86edcd3633SDaniel Mack 	INIT_LIST_HEAD(&subs->fmt_list);
87edcd3633SDaniel Mack 	spin_lock_init(&subs->lock);
88edcd3633SDaniel Mack 
89edcd3633SDaniel Mack 	subs->stream = as;
90edcd3633SDaniel Mack 	subs->direction = stream;
91edcd3633SDaniel Mack 	subs->dev = as->chip->dev;
92af158a7fSTakashi Iwai 	subs->txfr_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_ALIGN_TRANSFER);
93c1b034a4STakashi Iwai 	subs->tx_length_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_TX_LENGTH);
94978520b7STakashi Iwai 	subs->speed = snd_usb_get_speed(subs->dev);
951539d4f8SCalvin Owens 	subs->pkt_offset_adj = 0;
961b7ecc24SHector Martin 	subs->stream_offset_adj = 0;
97edcd3633SDaniel Mack 
98edcd3633SDaniel Mack 	snd_usb_set_pcm_ops(as->pcm, stream);
99edcd3633SDaniel Mack 
100edcd3633SDaniel Mack 	list_add_tail(&fp->list, &subs->fmt_list);
101edcd3633SDaniel Mack 	subs->formats |= fp->formats;
102edcd3633SDaniel Mack 	subs->num_formats++;
103edcd3633SDaniel Mack 	subs->fmt_type = fp->fmt_type;
1048260ef07STakashi Iwai 	subs->ep_num = fp->endpoint;
10504324cccSTakashi Iwai 	if (fp->channels > subs->channels_max)
10604324cccSTakashi Iwai 		subs->channels_max = fp->channels;
107f274baa4STakashi Iwai 
108a0a4959eSJorge Sanjuan 	if (pd) {
1097edf3b5eSJorge Sanjuan 		subs->str_pd = pd;
110a0a4959eSJorge Sanjuan 		/* Initialize Power Domain to idle status D1 */
111a0a4959eSJorge Sanjuan 		snd_usb_power_domain_set(subs->stream->chip, pd,
112a0a4959eSJorge Sanjuan 					 UAC3_PD_STATE_D1);
113a0a4959eSJorge Sanjuan 	}
1147edf3b5eSJorge Sanjuan 
115f274baa4STakashi Iwai 	snd_usb_preallocate_buffer(subs);
11604324cccSTakashi Iwai }
11704324cccSTakashi Iwai 
11804324cccSTakashi Iwai /* kctl callbacks for usb-audio channel maps */
usb_chmap_ctl_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)11904324cccSTakashi Iwai static int usb_chmap_ctl_info(struct snd_kcontrol *kcontrol,
12004324cccSTakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
12104324cccSTakashi Iwai {
12204324cccSTakashi Iwai 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
12304324cccSTakashi Iwai 	struct snd_usb_substream *subs = info->private_data;
12404324cccSTakashi Iwai 
12504324cccSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
12604324cccSTakashi Iwai 	uinfo->count = subs->channels_max;
12704324cccSTakashi Iwai 	uinfo->value.integer.min = 0;
12804324cccSTakashi Iwai 	uinfo->value.integer.max = SNDRV_CHMAP_LAST;
12904324cccSTakashi Iwai 	return 0;
13004324cccSTakashi Iwai }
13104324cccSTakashi Iwai 
13204324cccSTakashi Iwai /* check whether a duplicated entry exists in the audiofmt list */
have_dup_chmap(struct snd_usb_substream * subs,struct audioformat * fp)13304324cccSTakashi Iwai static bool have_dup_chmap(struct snd_usb_substream *subs,
13404324cccSTakashi Iwai 			   struct audioformat *fp)
13504324cccSTakashi Iwai {
136f67d71aeSGeliang Tang 	struct audioformat *prev = fp;
13704324cccSTakashi Iwai 
138f67d71aeSGeliang Tang 	list_for_each_entry_continue_reverse(prev, &subs->fmt_list, list) {
13904324cccSTakashi Iwai 		if (prev->chmap &&
14004324cccSTakashi Iwai 		    !memcmp(prev->chmap, fp->chmap, sizeof(*fp->chmap)))
14104324cccSTakashi Iwai 			return true;
14204324cccSTakashi Iwai 	}
14304324cccSTakashi Iwai 	return false;
14404324cccSTakashi Iwai }
14504324cccSTakashi Iwai 
usb_chmap_ctl_tlv(struct snd_kcontrol * kcontrol,int op_flag,unsigned int size,unsigned int __user * tlv)14604324cccSTakashi Iwai static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
14704324cccSTakashi Iwai 			     unsigned int size, unsigned int __user *tlv)
14804324cccSTakashi Iwai {
14904324cccSTakashi Iwai 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
15004324cccSTakashi Iwai 	struct snd_usb_substream *subs = info->private_data;
15104324cccSTakashi Iwai 	struct audioformat *fp;
15204324cccSTakashi Iwai 	unsigned int __user *dst;
15304324cccSTakashi Iwai 	int count = 0;
15404324cccSTakashi Iwai 
15504324cccSTakashi Iwai 	if (size < 8)
15604324cccSTakashi Iwai 		return -ENOMEM;
15704324cccSTakashi Iwai 	if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
15804324cccSTakashi Iwai 		return -EFAULT;
15904324cccSTakashi Iwai 	size -= 8;
16004324cccSTakashi Iwai 	dst = tlv + 2;
16104324cccSTakashi Iwai 	list_for_each_entry(fp, &subs->fmt_list, list) {
16204324cccSTakashi Iwai 		int i, ch_bytes;
16304324cccSTakashi Iwai 
16404324cccSTakashi Iwai 		if (!fp->chmap)
16504324cccSTakashi Iwai 			continue;
16604324cccSTakashi Iwai 		if (have_dup_chmap(subs, fp))
16704324cccSTakashi Iwai 			continue;
16804324cccSTakashi Iwai 		/* copy the entry */
16904324cccSTakashi Iwai 		ch_bytes = fp->chmap->channels * 4;
17004324cccSTakashi Iwai 		if (size < 8 + ch_bytes)
17104324cccSTakashi Iwai 			return -ENOMEM;
17204324cccSTakashi Iwai 		if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
17304324cccSTakashi Iwai 		    put_user(ch_bytes, dst + 1))
17404324cccSTakashi Iwai 			return -EFAULT;
17504324cccSTakashi Iwai 		dst += 2;
17604324cccSTakashi Iwai 		for (i = 0; i < fp->chmap->channels; i++, dst++) {
17704324cccSTakashi Iwai 			if (put_user(fp->chmap->map[i], dst))
17804324cccSTakashi Iwai 				return -EFAULT;
17904324cccSTakashi Iwai 		}
18004324cccSTakashi Iwai 
18104324cccSTakashi Iwai 		count += 8 + ch_bytes;
18204324cccSTakashi Iwai 		size -= 8 + ch_bytes;
18304324cccSTakashi Iwai 	}
18404324cccSTakashi Iwai 	if (put_user(count, tlv + 1))
18504324cccSTakashi Iwai 		return -EFAULT;
18604324cccSTakashi Iwai 	return 0;
18704324cccSTakashi Iwai }
18804324cccSTakashi Iwai 
usb_chmap_ctl_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)18904324cccSTakashi Iwai static int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol,
19004324cccSTakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
19104324cccSTakashi Iwai {
19204324cccSTakashi Iwai 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
19304324cccSTakashi Iwai 	struct snd_usb_substream *subs = info->private_data;
19404324cccSTakashi Iwai 	struct snd_pcm_chmap_elem *chmap = NULL;
195c6dde8ffSTakashi Iwai 	int i = 0;
19604324cccSTakashi Iwai 
19704324cccSTakashi Iwai 	if (subs->cur_audiofmt)
19804324cccSTakashi Iwai 		chmap = subs->cur_audiofmt->chmap;
19904324cccSTakashi Iwai 	if (chmap) {
20004324cccSTakashi Iwai 		for (i = 0; i < chmap->channels; i++)
20104324cccSTakashi Iwai 			ucontrol->value.integer.value[i] = chmap->map[i];
20204324cccSTakashi Iwai 	}
203c6dde8ffSTakashi Iwai 	for (; i < subs->channels_max; i++)
204c6dde8ffSTakashi Iwai 		ucontrol->value.integer.value[i] = 0;
20504324cccSTakashi Iwai 	return 0;
20604324cccSTakashi Iwai }
20704324cccSTakashi Iwai 
20804324cccSTakashi Iwai /* create a chmap kctl assigned to the given USB substream */
add_chmap(struct snd_pcm * pcm,int stream,struct snd_usb_substream * subs)20904324cccSTakashi Iwai static int add_chmap(struct snd_pcm *pcm, int stream,
21004324cccSTakashi Iwai 		     struct snd_usb_substream *subs)
21104324cccSTakashi Iwai {
21204324cccSTakashi Iwai 	struct audioformat *fp;
21304324cccSTakashi Iwai 	struct snd_pcm_chmap *chmap;
21404324cccSTakashi Iwai 	struct snd_kcontrol *kctl;
21504324cccSTakashi Iwai 	int err;
21604324cccSTakashi Iwai 
21704324cccSTakashi Iwai 	list_for_each_entry(fp, &subs->fmt_list, list)
21804324cccSTakashi Iwai 		if (fp->chmap)
21904324cccSTakashi Iwai 			goto ok;
22004324cccSTakashi Iwai 	/* no chmap is found */
22104324cccSTakashi Iwai 	return 0;
22204324cccSTakashi Iwai 
22304324cccSTakashi Iwai  ok:
22404324cccSTakashi Iwai 	err = snd_pcm_add_chmap_ctls(pcm, stream, NULL, 0, 0, &chmap);
22504324cccSTakashi Iwai 	if (err < 0)
22604324cccSTakashi Iwai 		return err;
22704324cccSTakashi Iwai 
22804324cccSTakashi Iwai 	/* override handlers */
22904324cccSTakashi Iwai 	chmap->private_data = subs;
23004324cccSTakashi Iwai 	kctl = chmap->kctl;
23104324cccSTakashi Iwai 	kctl->info = usb_chmap_ctl_info;
23204324cccSTakashi Iwai 	kctl->get = usb_chmap_ctl_get;
23304324cccSTakashi Iwai 	kctl->tlv.c = usb_chmap_ctl_tlv;
23404324cccSTakashi Iwai 
23504324cccSTakashi Iwai 	return 0;
23604324cccSTakashi Iwai }
23704324cccSTakashi Iwai 
23804324cccSTakashi Iwai /* convert from USB ChannelConfig bits to ALSA chmap element */
convert_chmap(int channels,unsigned int bits,int protocol)23904324cccSTakashi Iwai static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
24004324cccSTakashi Iwai 						int protocol)
24104324cccSTakashi Iwai {
242a01df925STakashi Iwai 	static const unsigned int uac1_maps[] = {
24304324cccSTakashi Iwai 		SNDRV_CHMAP_FL,		/* left front */
24404324cccSTakashi Iwai 		SNDRV_CHMAP_FR,		/* right front */
24504324cccSTakashi Iwai 		SNDRV_CHMAP_FC,		/* center front */
24604324cccSTakashi Iwai 		SNDRV_CHMAP_LFE,	/* LFE */
247*b4dd36f9STakashi Iwai 		SNDRV_CHMAP_RL,		/* left surround */
248*b4dd36f9STakashi Iwai 		SNDRV_CHMAP_RR,		/* right surround */
24904324cccSTakashi Iwai 		SNDRV_CHMAP_FLC,	/* left of center */
25004324cccSTakashi Iwai 		SNDRV_CHMAP_FRC,	/* right of center */
25104324cccSTakashi Iwai 		SNDRV_CHMAP_RC,		/* surround */
25204324cccSTakashi Iwai 		SNDRV_CHMAP_SL,		/* side left */
25304324cccSTakashi Iwai 		SNDRV_CHMAP_SR,		/* side right */
25404324cccSTakashi Iwai 		SNDRV_CHMAP_TC,		/* top */
25504324cccSTakashi Iwai 		0 /* terminator */
25604324cccSTakashi Iwai 	};
257a01df925STakashi Iwai 	static const unsigned int uac2_maps[] = {
25804324cccSTakashi Iwai 		SNDRV_CHMAP_FL,		/* front left */
25904324cccSTakashi Iwai 		SNDRV_CHMAP_FR,		/* front right */
26004324cccSTakashi Iwai 		SNDRV_CHMAP_FC,		/* front center */
26104324cccSTakashi Iwai 		SNDRV_CHMAP_LFE,	/* LFE */
26204324cccSTakashi Iwai 		SNDRV_CHMAP_RL,		/* back left */
26304324cccSTakashi Iwai 		SNDRV_CHMAP_RR,		/* back right */
26404324cccSTakashi Iwai 		SNDRV_CHMAP_FLC,	/* front left of center */
26504324cccSTakashi Iwai 		SNDRV_CHMAP_FRC,	/* front right of center */
26604324cccSTakashi Iwai 		SNDRV_CHMAP_RC,		/* back center */
26704324cccSTakashi Iwai 		SNDRV_CHMAP_SL,		/* side left */
26804324cccSTakashi Iwai 		SNDRV_CHMAP_SR,		/* side right */
26904324cccSTakashi Iwai 		SNDRV_CHMAP_TC,		/* top center */
27004324cccSTakashi Iwai 		SNDRV_CHMAP_TFL,	/* top front left */
27104324cccSTakashi Iwai 		SNDRV_CHMAP_TFC,	/* top front center */
27204324cccSTakashi Iwai 		SNDRV_CHMAP_TFR,	/* top front right */
27304324cccSTakashi Iwai 		SNDRV_CHMAP_TRL,	/* top back left */
27404324cccSTakashi Iwai 		SNDRV_CHMAP_TRC,	/* top back center */
27504324cccSTakashi Iwai 		SNDRV_CHMAP_TRR,	/* top back right */
27604324cccSTakashi Iwai 		SNDRV_CHMAP_TFLC,	/* top front left of center */
27704324cccSTakashi Iwai 		SNDRV_CHMAP_TFRC,	/* top front right of center */
27804324cccSTakashi Iwai 		SNDRV_CHMAP_LLFE,	/* left LFE */
27904324cccSTakashi Iwai 		SNDRV_CHMAP_RLFE,	/* right LFE */
28004324cccSTakashi Iwai 		SNDRV_CHMAP_TSL,	/* top side left */
28104324cccSTakashi Iwai 		SNDRV_CHMAP_TSR,	/* top side right */
28204324cccSTakashi Iwai 		SNDRV_CHMAP_BC,		/* bottom center */
28371373fddSAnssi Hannula 		SNDRV_CHMAP_RLC,	/* back left of center */
28471373fddSAnssi Hannula 		SNDRV_CHMAP_RRC,	/* back right of center */
28504324cccSTakashi Iwai 		0 /* terminator */
28604324cccSTakashi Iwai 	};
28704324cccSTakashi Iwai 	struct snd_pcm_chmap_elem *chmap;
28804324cccSTakashi Iwai 	const unsigned int *maps;
28904324cccSTakashi Iwai 	int c;
29004324cccSTakashi Iwai 
29104324cccSTakashi Iwai 	if (channels > ARRAY_SIZE(chmap->map))
29204324cccSTakashi Iwai 		return NULL;
29304324cccSTakashi Iwai 
29404324cccSTakashi Iwai 	chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
29504324cccSTakashi Iwai 	if (!chmap)
29604324cccSTakashi Iwai 		return NULL;
29704324cccSTakashi Iwai 
29804324cccSTakashi Iwai 	maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps;
29904324cccSTakashi Iwai 	chmap->channels = channels;
30004324cccSTakashi Iwai 	c = 0;
3010dca01c3SDavid Henningsson 
3020dca01c3SDavid Henningsson 	if (bits) {
30322cad1b8SJohan Carlsson 		for (; bits && *maps; maps++, bits >>= 1) {
30404324cccSTakashi Iwai 			if (bits & 1)
30504324cccSTakashi Iwai 				chmap->map[c++] = *maps;
30622cad1b8SJohan Carlsson 			if (c == chmap->channels)
30722cad1b8SJohan Carlsson 				break;
30822cad1b8SJohan Carlsson 		}
3090dca01c3SDavid Henningsson 	} else {
3100dca01c3SDavid Henningsson 		/* If we're missing wChannelConfig, then guess something
3110dca01c3SDavid Henningsson 		    to make sure the channel map is not skipped entirely */
3120dca01c3SDavid Henningsson 		if (channels == 1)
3130dca01c3SDavid Henningsson 			chmap->map[c++] = SNDRV_CHMAP_MONO;
3140dca01c3SDavid Henningsson 		else
3150dca01c3SDavid Henningsson 			for (; c < channels && *maps; maps++)
3160dca01c3SDavid Henningsson 				chmap->map[c++] = *maps;
31704324cccSTakashi Iwai 	}
31804324cccSTakashi Iwai 
31904324cccSTakashi Iwai 	for (; c < channels; c++)
32004324cccSTakashi Iwai 		chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
32104324cccSTakashi Iwai 
32204324cccSTakashi Iwai 	return chmap;
323edcd3633SDaniel Mack }
324e8e8babfSDaniel Mack 
3259a2fe9b8SRuslan Bilovol /* UAC3 device stores channels information in Cluster Descriptors */
3269a2fe9b8SRuslan Bilovol static struct
convert_chmap_v3(struct uac3_cluster_header_descriptor * cluster)3279a2fe9b8SRuslan Bilovol snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor
3289a2fe9b8SRuslan Bilovol 								*cluster)
3299a2fe9b8SRuslan Bilovol {
3309a2fe9b8SRuslan Bilovol 	unsigned int channels = cluster->bNrChannels;
3319a2fe9b8SRuslan Bilovol 	struct snd_pcm_chmap_elem *chmap;
3329a2fe9b8SRuslan Bilovol 	void *p = cluster;
3339a2fe9b8SRuslan Bilovol 	int len, c;
3349a2fe9b8SRuslan Bilovol 
3359a2fe9b8SRuslan Bilovol 	if (channels > ARRAY_SIZE(chmap->map))
3369a2fe9b8SRuslan Bilovol 		return NULL;
3379a2fe9b8SRuslan Bilovol 
3389a2fe9b8SRuslan Bilovol 	chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
3399a2fe9b8SRuslan Bilovol 	if (!chmap)
3409a2fe9b8SRuslan Bilovol 		return NULL;
3419a2fe9b8SRuslan Bilovol 
3429a2fe9b8SRuslan Bilovol 	len = le16_to_cpu(cluster->wLength);
3439a2fe9b8SRuslan Bilovol 	c = 0;
3449a2fe9b8SRuslan Bilovol 	p += sizeof(struct uac3_cluster_header_descriptor);
3459a2fe9b8SRuslan Bilovol 
3469a2fe9b8SRuslan Bilovol 	while (((p - (void *)cluster) < len) && (c < channels)) {
3479a2fe9b8SRuslan Bilovol 		struct uac3_cluster_segment_descriptor *cs_desc = p;
3489a2fe9b8SRuslan Bilovol 		u16 cs_len;
3499a2fe9b8SRuslan Bilovol 		u8 cs_type;
3509a2fe9b8SRuslan Bilovol 
3519a2fe9b8SRuslan Bilovol 		cs_len = le16_to_cpu(cs_desc->wLength);
3529a2fe9b8SRuslan Bilovol 		cs_type = cs_desc->bSegmentType;
3539a2fe9b8SRuslan Bilovol 
3549a2fe9b8SRuslan Bilovol 		if (cs_type == UAC3_CHANNEL_INFORMATION) {
3559a2fe9b8SRuslan Bilovol 			struct uac3_cluster_information_segment_descriptor *is = p;
3569a2fe9b8SRuslan Bilovol 			unsigned char map;
3579a2fe9b8SRuslan Bilovol 
3589a2fe9b8SRuslan Bilovol 			/*
3599a2fe9b8SRuslan Bilovol 			 * TODO: this conversion is not complete, update it
3609a2fe9b8SRuslan Bilovol 			 * after adding UAC3 values to asound.h
3619a2fe9b8SRuslan Bilovol 			 */
3628e0428a7SMichael Drake 			switch (is->bChRelationship) {
3639a2fe9b8SRuslan Bilovol 			case UAC3_CH_MONO:
3649a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_MONO;
3659a2fe9b8SRuslan Bilovol 				break;
3669a2fe9b8SRuslan Bilovol 			case UAC3_CH_LEFT:
3679a2fe9b8SRuslan Bilovol 			case UAC3_CH_FRONT_LEFT:
3689a2fe9b8SRuslan Bilovol 			case UAC3_CH_HEADPHONE_LEFT:
3699a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_FL;
3709a2fe9b8SRuslan Bilovol 				break;
3719a2fe9b8SRuslan Bilovol 			case UAC3_CH_RIGHT:
3729a2fe9b8SRuslan Bilovol 			case UAC3_CH_FRONT_RIGHT:
3739a2fe9b8SRuslan Bilovol 			case UAC3_CH_HEADPHONE_RIGHT:
3749a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_FR;
3759a2fe9b8SRuslan Bilovol 				break;
3769a2fe9b8SRuslan Bilovol 			case UAC3_CH_FRONT_CENTER:
3779a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_FC;
3789a2fe9b8SRuslan Bilovol 				break;
3799a2fe9b8SRuslan Bilovol 			case UAC3_CH_FRONT_LEFT_OF_CENTER:
3809a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_FLC;
3819a2fe9b8SRuslan Bilovol 				break;
3829a2fe9b8SRuslan Bilovol 			case UAC3_CH_FRONT_RIGHT_OF_CENTER:
3839a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_FRC;
3849a2fe9b8SRuslan Bilovol 				break;
3859a2fe9b8SRuslan Bilovol 			case UAC3_CH_SIDE_LEFT:
3869a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_SL;
3879a2fe9b8SRuslan Bilovol 				break;
3889a2fe9b8SRuslan Bilovol 			case UAC3_CH_SIDE_RIGHT:
3899a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_SR;
3909a2fe9b8SRuslan Bilovol 				break;
3919a2fe9b8SRuslan Bilovol 			case UAC3_CH_BACK_LEFT:
3929a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_RL;
3939a2fe9b8SRuslan Bilovol 				break;
3949a2fe9b8SRuslan Bilovol 			case UAC3_CH_BACK_RIGHT:
3959a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_RR;
3969a2fe9b8SRuslan Bilovol 				break;
3979a2fe9b8SRuslan Bilovol 			case UAC3_CH_BACK_CENTER:
3989a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_RC;
3999a2fe9b8SRuslan Bilovol 				break;
4009a2fe9b8SRuslan Bilovol 			case UAC3_CH_BACK_LEFT_OF_CENTER:
4019a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_RLC;
4029a2fe9b8SRuslan Bilovol 				break;
4039a2fe9b8SRuslan Bilovol 			case UAC3_CH_BACK_RIGHT_OF_CENTER:
4049a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_RRC;
4059a2fe9b8SRuslan Bilovol 				break;
4069a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_CENTER:
4079a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TC;
4089a2fe9b8SRuslan Bilovol 				break;
4099a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_FRONT_LEFT:
4109a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TFL;
4119a2fe9b8SRuslan Bilovol 				break;
4129a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_FRONT_RIGHT:
4139a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TFR;
4149a2fe9b8SRuslan Bilovol 				break;
4159a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_FRONT_CENTER:
4169a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TFC;
4179a2fe9b8SRuslan Bilovol 				break;
4189a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_FRONT_LOC:
4199a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TFLC;
4209a2fe9b8SRuslan Bilovol 				break;
4219a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_FRONT_ROC:
4229a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TFRC;
4239a2fe9b8SRuslan Bilovol 				break;
4249a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_SIDE_LEFT:
4259a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TSL;
4269a2fe9b8SRuslan Bilovol 				break;
4279a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_SIDE_RIGHT:
4289a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TSR;
4299a2fe9b8SRuslan Bilovol 				break;
4309a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_BACK_LEFT:
4319a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TRL;
4329a2fe9b8SRuslan Bilovol 				break;
4339a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_BACK_RIGHT:
4349a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TRR;
4359a2fe9b8SRuslan Bilovol 				break;
4369a2fe9b8SRuslan Bilovol 			case UAC3_CH_TOP_BACK_CENTER:
4379a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_TRC;
4389a2fe9b8SRuslan Bilovol 				break;
4399a2fe9b8SRuslan Bilovol 			case UAC3_CH_BOTTOM_CENTER:
4409a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_BC;
4419a2fe9b8SRuslan Bilovol 				break;
4429a2fe9b8SRuslan Bilovol 			case UAC3_CH_LOW_FREQUENCY_EFFECTS:
4439a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_LFE;
4449a2fe9b8SRuslan Bilovol 				break;
4459a2fe9b8SRuslan Bilovol 			case UAC3_CH_LFE_LEFT:
4469a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_LLFE;
4479a2fe9b8SRuslan Bilovol 				break;
4489a2fe9b8SRuslan Bilovol 			case UAC3_CH_LFE_RIGHT:
4499a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_RLFE;
4509a2fe9b8SRuslan Bilovol 				break;
4519a2fe9b8SRuslan Bilovol 			case UAC3_CH_RELATIONSHIP_UNDEFINED:
4529a2fe9b8SRuslan Bilovol 			default:
4539a2fe9b8SRuslan Bilovol 				map = SNDRV_CHMAP_UNKNOWN;
4549a2fe9b8SRuslan Bilovol 				break;
4559a2fe9b8SRuslan Bilovol 			}
4569a2fe9b8SRuslan Bilovol 			chmap->map[c++] = map;
4579a2fe9b8SRuslan Bilovol 		}
4589a2fe9b8SRuslan Bilovol 		p += cs_len;
4599a2fe9b8SRuslan Bilovol 	}
4609a2fe9b8SRuslan Bilovol 
4619a2fe9b8SRuslan Bilovol 	if (channels < c)
4629a2fe9b8SRuslan Bilovol 		pr_err("%s: channel number mismatch\n", __func__);
4639a2fe9b8SRuslan Bilovol 
4649a2fe9b8SRuslan Bilovol 	chmap->channels = channels;
4659a2fe9b8SRuslan Bilovol 
4669a2fe9b8SRuslan Bilovol 	for (; c < channels; c++)
4679a2fe9b8SRuslan Bilovol 		chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
4689a2fe9b8SRuslan Bilovol 
4699a2fe9b8SRuslan Bilovol 	return chmap;
4709a2fe9b8SRuslan Bilovol }
4719a2fe9b8SRuslan Bilovol 
472e8e8babfSDaniel Mack /*
473e8e8babfSDaniel Mack  * add this endpoint to the chip instance.
474e8e8babfSDaniel Mack  * if a stream with the same endpoint already exists, append to it.
475836b34a9SVladis Dronov  * if not, create a new pcm stream. note, fp is added to the substream
476836b34a9SVladis Dronov  * fmt_list and will be freed on the chip instance release. do not free
477836b34a9SVladis Dronov  * fp or do remove it from the substream fmt_list to avoid double-free.
478e8e8babfSDaniel Mack  */
__snd_usb_add_audio_stream(struct snd_usb_audio * chip,int stream,struct audioformat * fp,struct snd_usb_power_domain * pd)4797edf3b5eSJorge Sanjuan static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
480e8e8babfSDaniel Mack 				      int stream,
4817edf3b5eSJorge Sanjuan 				      struct audioformat *fp,
4827edf3b5eSJorge Sanjuan 				      struct snd_usb_power_domain *pd)
4837edf3b5eSJorge Sanjuan 
484e8e8babfSDaniel Mack {
485e8e8babfSDaniel Mack 	struct snd_usb_stream *as;
486e8e8babfSDaniel Mack 	struct snd_usb_substream *subs;
487e8e8babfSDaniel Mack 	struct snd_pcm *pcm;
488e8e8babfSDaniel Mack 	int err;
489e8e8babfSDaniel Mack 
49088766f04SEldad Zack 	list_for_each_entry(as, &chip->pcm_list, list) {
491e8e8babfSDaniel Mack 		if (as->fmt_type != fp->fmt_type)
492e8e8babfSDaniel Mack 			continue;
493e8e8babfSDaniel Mack 		subs = &as->substream[stream];
4948260ef07STakashi Iwai 		if (subs->ep_num == fp->endpoint) {
495e8e8babfSDaniel Mack 			list_add_tail(&fp->list, &subs->fmt_list);
496e8e8babfSDaniel Mack 			subs->num_formats++;
497e8e8babfSDaniel Mack 			subs->formats |= fp->formats;
498e8e8babfSDaniel Mack 			return 0;
499e8e8babfSDaniel Mack 		}
500e8e8babfSDaniel Mack 	}
5017e1afce5STakashi Iwai 
5027e1afce5STakashi Iwai 	if (chip->card->registered)
5037e1afce5STakashi Iwai 		chip->need_delayed_register = true;
5047e1afce5STakashi Iwai 
505e8e8babfSDaniel Mack 	/* look for an empty stream */
50688766f04SEldad Zack 	list_for_each_entry(as, &chip->pcm_list, list) {
507e8e8babfSDaniel Mack 		if (as->fmt_type != fp->fmt_type)
508e8e8babfSDaniel Mack 			continue;
509e8e8babfSDaniel Mack 		subs = &as->substream[stream];
5108260ef07STakashi Iwai 		if (subs->ep_num)
511e8e8babfSDaniel Mack 			continue;
512e8e8babfSDaniel Mack 		err = snd_pcm_new_stream(as->pcm, stream, 1);
513e8e8babfSDaniel Mack 		if (err < 0)
514e8e8babfSDaniel Mack 			return err;
5157edf3b5eSJorge Sanjuan 		snd_usb_init_substream(as, stream, fp, pd);
51604324cccSTakashi Iwai 		return add_chmap(as->pcm, stream, subs);
517e8e8babfSDaniel Mack 	}
518e8e8babfSDaniel Mack 
519e8e8babfSDaniel Mack 	/* create a new pcm */
520e8e8babfSDaniel Mack 	as = kzalloc(sizeof(*as), GFP_KERNEL);
521e8e8babfSDaniel Mack 	if (!as)
522e8e8babfSDaniel Mack 		return -ENOMEM;
523e8e8babfSDaniel Mack 	as->pcm_index = chip->pcm_devs;
524e8e8babfSDaniel Mack 	as->chip = chip;
525e8e8babfSDaniel Mack 	as->fmt_type = fp->fmt_type;
526e8e8babfSDaniel Mack 	err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
527e8e8babfSDaniel Mack 			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
528e8e8babfSDaniel Mack 			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
529e8e8babfSDaniel Mack 			  &pcm);
530e8e8babfSDaniel Mack 	if (err < 0) {
531e8e8babfSDaniel Mack 		kfree(as);
532e8e8babfSDaniel Mack 		return err;
533e8e8babfSDaniel Mack 	}
534e8e8babfSDaniel Mack 	as->pcm = pcm;
535e8e8babfSDaniel Mack 	pcm->private_data = as;
536e8e8babfSDaniel Mack 	pcm->private_free = snd_usb_audio_pcm_free;
537e8e8babfSDaniel Mack 	pcm->info_flags = 0;
538e8e8babfSDaniel Mack 	if (chip->pcm_devs > 0)
539e8e8babfSDaniel Mack 		sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
540e8e8babfSDaniel Mack 	else
541e8e8babfSDaniel Mack 		strcpy(pcm->name, "USB Audio");
542e8e8babfSDaniel Mack 
5437edf3b5eSJorge Sanjuan 	snd_usb_init_substream(as, stream, fp, pd);
544e8e8babfSDaniel Mack 
5455ee20bc7SJohan Rastén 	/*
5465ee20bc7SJohan Rastén 	 * Keep using head insertion for M-Audio Audiophile USB (tm) which has a
5475ee20bc7SJohan Rastén 	 * fix to swap capture stream order in conf/cards/USB-audio.conf
5485ee20bc7SJohan Rastén 	 */
5495ee20bc7SJohan Rastén 	if (chip->usb_id == USB_ID(0x0763, 0x2003))
550e8e8babfSDaniel Mack 		list_add(&as->list, &chip->pcm_list);
5515ee20bc7SJohan Rastén 	else
5525ee20bc7SJohan Rastén 		list_add_tail(&as->list, &chip->pcm_list);
5535ee20bc7SJohan Rastén 
554e8e8babfSDaniel Mack 	chip->pcm_devs++;
555e8e8babfSDaniel Mack 
556e8e8babfSDaniel Mack 	snd_usb_proc_pcm_format_add(as);
557e8e8babfSDaniel Mack 
55804324cccSTakashi Iwai 	return add_chmap(pcm, stream, &as->substream[stream]);
559e8e8babfSDaniel Mack }
560e8e8babfSDaniel Mack 
snd_usb_add_audio_stream(struct snd_usb_audio * chip,int stream,struct audioformat * fp)5617edf3b5eSJorge Sanjuan int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
5627edf3b5eSJorge Sanjuan 			     int stream,
5637edf3b5eSJorge Sanjuan 			     struct audioformat *fp)
5647edf3b5eSJorge Sanjuan {
5657edf3b5eSJorge Sanjuan 	return __snd_usb_add_audio_stream(chip, stream, fp, NULL);
5667edf3b5eSJorge Sanjuan }
5677edf3b5eSJorge Sanjuan 
snd_usb_add_audio_stream_v3(struct snd_usb_audio * chip,int stream,struct audioformat * fp,struct snd_usb_power_domain * pd)5687edf3b5eSJorge Sanjuan static int snd_usb_add_audio_stream_v3(struct snd_usb_audio *chip,
5697edf3b5eSJorge Sanjuan 				       int stream,
5707edf3b5eSJorge Sanjuan 				       struct audioformat *fp,
5717edf3b5eSJorge Sanjuan 				       struct snd_usb_power_domain *pd)
5727edf3b5eSJorge Sanjuan {
5737edf3b5eSJorge Sanjuan 	return __snd_usb_add_audio_stream(chip, stream, fp, pd);
5747edf3b5eSJorge Sanjuan }
5757edf3b5eSJorge Sanjuan 
parse_uac_endpoint_attributes(struct snd_usb_audio * chip,struct usb_host_interface * alts,int protocol,int iface_no)576e8e8babfSDaniel Mack static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
577e8e8babfSDaniel Mack 					 struct usb_host_interface *alts,
578e8e8babfSDaniel Mack 					 int protocol, int iface_no)
579e8e8babfSDaniel Mack {
580e8e8babfSDaniel Mack 	/* parsed with a v1 header here. that's ok as we only look at the
581e8e8babfSDaniel Mack 	 * header first which is the same for both versions */
582e8e8babfSDaniel Mack 	struct uac_iso_endpoint_descriptor *csep;
583e8e8babfSDaniel Mack 	struct usb_interface_descriptor *altsd = get_iface_desc(alts);
584e8e8babfSDaniel Mack 	int attributes = 0;
585e8e8babfSDaniel Mack 
586e8e8babfSDaniel Mack 	csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
587e8e8babfSDaniel Mack 
588e8e8babfSDaniel Mack 	/* Creamware Noah has this descriptor after the 2nd endpoint */
589e8e8babfSDaniel Mack 	if (!csep && altsd->bNumEndpoints >= 2)
590e8e8babfSDaniel Mack 		csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
591e8e8babfSDaniel Mack 
592ebfc594cSDaniel Mack 	/*
593ebfc594cSDaniel Mack 	 * If we can't locate the USB_DT_CS_ENDPOINT descriptor in the extra
594ebfc594cSDaniel Mack 	 * bytes after the first endpoint, go search the entire interface.
595ebfc594cSDaniel Mack 	 * Some devices have it directly *before* the standard endpoint.
596ebfc594cSDaniel Mack 	 */
597ebfc594cSDaniel Mack 	if (!csep)
598ebfc594cSDaniel Mack 		csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT);
599ebfc594cSDaniel Mack 
600e8e8babfSDaniel Mack 	if (!csep || csep->bLength < 7 ||
6013e96d728STakashi Iwai 	    csep->bDescriptorSubtype != UAC_EP_GENERAL)
6023e96d728STakashi Iwai 		goto error;
603e8e8babfSDaniel Mack 
604e8e8babfSDaniel Mack 	if (protocol == UAC_VERSION_1) {
605e8e8babfSDaniel Mack 		attributes = csep->bmAttributes;
606c99f0802SJorge Sanjuan 	} else if (protocol == UAC_VERSION_2) {
607e8e8babfSDaniel Mack 		struct uac2_iso_endpoint_descriptor *csep2 =
608e8e8babfSDaniel Mack 			(struct uac2_iso_endpoint_descriptor *) csep;
609e8e8babfSDaniel Mack 
6103e96d728STakashi Iwai 		if (csep2->bLength < sizeof(*csep2))
6113e96d728STakashi Iwai 			goto error;
612e8e8babfSDaniel Mack 		attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
613e8e8babfSDaniel Mack 
614e8e8babfSDaniel Mack 		/* emulate the endpoint attributes of a v1 device */
615e8e8babfSDaniel Mack 		if (csep2->bmControls & UAC2_CONTROL_PITCH)
616e8e8babfSDaniel Mack 			attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
617c99f0802SJorge Sanjuan 	} else { /* UAC_VERSION_3 */
618c99f0802SJorge Sanjuan 		struct uac3_iso_endpoint_descriptor *csep3 =
619c99f0802SJorge Sanjuan 			(struct uac3_iso_endpoint_descriptor *) csep;
620c99f0802SJorge Sanjuan 
6213e96d728STakashi Iwai 		if (csep3->bLength < sizeof(*csep3))
6223e96d728STakashi Iwai 			goto error;
623c99f0802SJorge Sanjuan 		/* emulate the endpoint attributes of a v1 device */
624c99f0802SJorge Sanjuan 		if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH)
625c99f0802SJorge Sanjuan 			attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
626e8e8babfSDaniel Mack 	}
627e8e8babfSDaniel Mack 
628e8e8babfSDaniel Mack 	return attributes;
6293e96d728STakashi Iwai 
6303e96d728STakashi Iwai  error:
6313e96d728STakashi Iwai 	usb_audio_warn(chip,
6323e96d728STakashi Iwai 		       "%u:%d : no or invalid class specific endpoint descriptor\n",
6333e96d728STakashi Iwai 		       iface_no, altsd->bAlternateSetting);
6343e96d728STakashi Iwai 	return 0;
635e8e8babfSDaniel Mack }
636e8e8babfSDaniel Mack 
63704324cccSTakashi Iwai /* find an input terminal descriptor (either UAC1 or UAC2) with the given
63804324cccSTakashi Iwai  * terminal id
63904324cccSTakashi Iwai  */
64004324cccSTakashi Iwai static void *
snd_usb_find_input_terminal_descriptor(struct usb_host_interface * ctrl_iface,int terminal_id,int protocol)641e8e8babfSDaniel Mack snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
64257f87706STakashi Iwai 				       int terminal_id, int protocol)
643e8e8babfSDaniel Mack {
644e8e8babfSDaniel Mack 	struct uac2_input_terminal_descriptor *term = NULL;
645e8e8babfSDaniel Mack 
646e8e8babfSDaniel Mack 	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
647e8e8babfSDaniel Mack 					       ctrl_iface->extralen,
648e8e8babfSDaniel Mack 					       term, UAC_INPUT_TERMINAL))) {
64957f87706STakashi Iwai 		if (!snd_usb_validate_audio_desc(term, protocol))
6503e96d728STakashi Iwai 			continue;
651e8e8babfSDaniel Mack 		if (term->bTerminalID == terminal_id)
652e8e8babfSDaniel Mack 			return term;
653e8e8babfSDaniel Mack 	}
654e8e8babfSDaniel Mack 
655e8e8babfSDaniel Mack 	return NULL;
656e8e8babfSDaniel Mack }
657e8e8babfSDaniel Mack 
6589a2fe9b8SRuslan Bilovol static void *
snd_usb_find_output_terminal_descriptor(struct usb_host_interface * ctrl_iface,int terminal_id,int protocol)659e8e8babfSDaniel Mack snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
66057f87706STakashi Iwai 					int terminal_id, int protocol)
661e8e8babfSDaniel Mack {
6629a2fe9b8SRuslan Bilovol 	/* OK to use with both UAC2 and UAC3 */
663e8e8babfSDaniel Mack 	struct uac2_output_terminal_descriptor *term = NULL;
664e8e8babfSDaniel Mack 
665e8e8babfSDaniel Mack 	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
666e8e8babfSDaniel Mack 					       ctrl_iface->extralen,
667e8e8babfSDaniel Mack 					       term, UAC_OUTPUT_TERMINAL))) {
66857f87706STakashi Iwai 		if (!snd_usb_validate_audio_desc(term, protocol))
66957f87706STakashi Iwai 			continue;
67057f87706STakashi Iwai 		if (term->bTerminalID == terminal_id)
671e8e8babfSDaniel Mack 			return term;
672e8e8babfSDaniel Mack 	}
673e8e8babfSDaniel Mack 
674e8e8babfSDaniel Mack 	return NULL;
675e8e8babfSDaniel Mack }
676e8e8babfSDaniel Mack 
6774d47fa84SRuslan Bilovol static struct audioformat *
audio_format_alloc_init(struct snd_usb_audio * chip,struct usb_host_interface * alts,int protocol,int iface_no,int altset_idx,int altno,int num_channels,int clock)6784d47fa84SRuslan Bilovol audio_format_alloc_init(struct snd_usb_audio *chip,
6794d47fa84SRuslan Bilovol 		       struct usb_host_interface *alts,
6804d47fa84SRuslan Bilovol 		       int protocol, int iface_no, int altset_idx,
6814d47fa84SRuslan Bilovol 		       int altno, int num_channels, int clock)
6824d47fa84SRuslan Bilovol {
6834d47fa84SRuslan Bilovol 	struct audioformat *fp;
6844d47fa84SRuslan Bilovol 
6854d47fa84SRuslan Bilovol 	fp = kzalloc(sizeof(*fp), GFP_KERNEL);
6864d47fa84SRuslan Bilovol 	if (!fp)
6874d47fa84SRuslan Bilovol 		return NULL;
6884d47fa84SRuslan Bilovol 
6894d47fa84SRuslan Bilovol 	fp->iface = iface_no;
6904d47fa84SRuslan Bilovol 	fp->altsetting = altno;
6914d47fa84SRuslan Bilovol 	fp->altset_idx = altset_idx;
6924d47fa84SRuslan Bilovol 	fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
6934d47fa84SRuslan Bilovol 	fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
6944d47fa84SRuslan Bilovol 	fp->datainterval = snd_usb_parse_datainterval(chip, alts);
6954d47fa84SRuslan Bilovol 	fp->protocol = protocol;
6964d47fa84SRuslan Bilovol 	fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
6974d47fa84SRuslan Bilovol 	fp->channels = num_channels;
6984d47fa84SRuslan Bilovol 	if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH)
6994d47fa84SRuslan Bilovol 		fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
7004d47fa84SRuslan Bilovol 				* (fp->maxpacksize & 0x7ff);
7014d47fa84SRuslan Bilovol 	fp->clock = clock;
7024d47fa84SRuslan Bilovol 	INIT_LIST_HEAD(&fp->list);
7034d47fa84SRuslan Bilovol 
7044d47fa84SRuslan Bilovol 	return fp;
7054d47fa84SRuslan Bilovol }
7064d47fa84SRuslan Bilovol 
70768faa863SRuslan Bilovol static struct audioformat *
snd_usb_get_audioformat_uac12(struct snd_usb_audio * chip,struct usb_host_interface * alts,int protocol,int iface_no,int altset_idx,int altno,int stream,int bm_quirk)70868faa863SRuslan Bilovol snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
70968faa863SRuslan Bilovol 			      struct usb_host_interface *alts,
71068faa863SRuslan Bilovol 			      int protocol, int iface_no, int altset_idx,
71168faa863SRuslan Bilovol 			      int altno, int stream, int bm_quirk)
71268faa863SRuslan Bilovol {
71368faa863SRuslan Bilovol 	struct usb_device *dev = chip->dev;
71468faa863SRuslan Bilovol 	struct uac_format_type_i_continuous_descriptor *fmt;
71568faa863SRuslan Bilovol 	unsigned int num_channels = 0, chconfig = 0;
71668faa863SRuslan Bilovol 	struct audioformat *fp;
71768faa863SRuslan Bilovol 	int clock = 0;
71868faa863SRuslan Bilovol 	u64 format;
71968faa863SRuslan Bilovol 
72068faa863SRuslan Bilovol 	/* get audio formats */
72168faa863SRuslan Bilovol 	if (protocol == UAC_VERSION_1) {
72268faa863SRuslan Bilovol 		struct uac1_as_header_descriptor *as =
72368faa863SRuslan Bilovol 			snd_usb_find_csint_desc(alts->extra, alts->extralen,
72468faa863SRuslan Bilovol 						NULL, UAC_AS_GENERAL);
72568faa863SRuslan Bilovol 		struct uac_input_terminal_descriptor *iterm;
72668faa863SRuslan Bilovol 
72768faa863SRuslan Bilovol 		if (!as) {
72868faa863SRuslan Bilovol 			dev_err(&dev->dev,
72968faa863SRuslan Bilovol 				"%u:%d : UAC_AS_GENERAL descriptor not found\n",
73068faa863SRuslan Bilovol 				iface_no, altno);
73168faa863SRuslan Bilovol 			return NULL;
73268faa863SRuslan Bilovol 		}
73368faa863SRuslan Bilovol 
73468faa863SRuslan Bilovol 		if (as->bLength < sizeof(*as)) {
73568faa863SRuslan Bilovol 			dev_err(&dev->dev,
73668faa863SRuslan Bilovol 				"%u:%d : invalid UAC_AS_GENERAL desc\n",
73768faa863SRuslan Bilovol 				iface_no, altno);
73868faa863SRuslan Bilovol 			return NULL;
73968faa863SRuslan Bilovol 		}
74068faa863SRuslan Bilovol 
74168faa863SRuslan Bilovol 		format = le16_to_cpu(as->wFormatTag); /* remember the format value */
74268faa863SRuslan Bilovol 
74368faa863SRuslan Bilovol 		iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
7443e96d728STakashi Iwai 							       as->bTerminalLink,
74557f87706STakashi Iwai 							       protocol);
74668faa863SRuslan Bilovol 		if (iterm) {
74768faa863SRuslan Bilovol 			num_channels = iterm->bNrChannels;
74868faa863SRuslan Bilovol 			chconfig = le16_to_cpu(iterm->wChannelConfig);
74968faa863SRuslan Bilovol 		}
75068faa863SRuslan Bilovol 	} else { /* UAC_VERSION_2 */
75168faa863SRuslan Bilovol 		struct uac2_input_terminal_descriptor *input_term;
75268faa863SRuslan Bilovol 		struct uac2_output_terminal_descriptor *output_term;
75368faa863SRuslan Bilovol 		struct uac2_as_header_descriptor *as =
75468faa863SRuslan Bilovol 			snd_usb_find_csint_desc(alts->extra, alts->extralen,
75568faa863SRuslan Bilovol 						NULL, UAC_AS_GENERAL);
75668faa863SRuslan Bilovol 
75768faa863SRuslan Bilovol 		if (!as) {
75868faa863SRuslan Bilovol 			dev_err(&dev->dev,
75968faa863SRuslan Bilovol 				"%u:%d : UAC_AS_GENERAL descriptor not found\n",
76068faa863SRuslan Bilovol 				iface_no, altno);
76168faa863SRuslan Bilovol 			return NULL;
76268faa863SRuslan Bilovol 		}
76368faa863SRuslan Bilovol 
76468faa863SRuslan Bilovol 		if (as->bLength < sizeof(*as)) {
76568faa863SRuslan Bilovol 			dev_err(&dev->dev,
76668faa863SRuslan Bilovol 				"%u:%d : invalid UAC_AS_GENERAL desc\n",
76768faa863SRuslan Bilovol 				iface_no, altno);
76868faa863SRuslan Bilovol 			return NULL;
76968faa863SRuslan Bilovol 		}
77068faa863SRuslan Bilovol 
77168faa863SRuslan Bilovol 		num_channels = as->bNrChannels;
77268faa863SRuslan Bilovol 		format = le32_to_cpu(as->bmFormats);
77368faa863SRuslan Bilovol 		chconfig = le32_to_cpu(as->bmChannelConfig);
77468faa863SRuslan Bilovol 
77568faa863SRuslan Bilovol 		/*
77668faa863SRuslan Bilovol 		 * lookup the terminal associated to this interface
77768faa863SRuslan Bilovol 		 * to extract the clock
77868faa863SRuslan Bilovol 		 */
77968faa863SRuslan Bilovol 		input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
7803e96d728STakashi Iwai 								    as->bTerminalLink,
78157f87706STakashi Iwai 								    protocol);
78268faa863SRuslan Bilovol 		if (input_term) {
78368faa863SRuslan Bilovol 			clock = input_term->bCSourceID;
78468faa863SRuslan Bilovol 			if (!chconfig && (num_channels == input_term->bNrChannels))
78568faa863SRuslan Bilovol 				chconfig = le32_to_cpu(input_term->bmChannelConfig);
78668faa863SRuslan Bilovol 			goto found_clock;
78768faa863SRuslan Bilovol 		}
78868faa863SRuslan Bilovol 
78968faa863SRuslan Bilovol 		output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
79057f87706STakashi Iwai 								      as->bTerminalLink,
79157f87706STakashi Iwai 								      protocol);
79268faa863SRuslan Bilovol 		if (output_term) {
79368faa863SRuslan Bilovol 			clock = output_term->bCSourceID;
79468faa863SRuslan Bilovol 			goto found_clock;
79568faa863SRuslan Bilovol 		}
79668faa863SRuslan Bilovol 
79768faa863SRuslan Bilovol 		dev_err(&dev->dev,
79868faa863SRuslan Bilovol 			"%u:%d : bogus bTerminalLink %d\n",
79968faa863SRuslan Bilovol 			iface_no, altno, as->bTerminalLink);
80068faa863SRuslan Bilovol 		return NULL;
80168faa863SRuslan Bilovol 	}
80268faa863SRuslan Bilovol 
80368faa863SRuslan Bilovol found_clock:
80468faa863SRuslan Bilovol 	/* get format type */
80568faa863SRuslan Bilovol 	fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen,
80668faa863SRuslan Bilovol 				      NULL, UAC_FORMAT_TYPE);
80768faa863SRuslan Bilovol 	if (!fmt) {
80868faa863SRuslan Bilovol 		dev_err(&dev->dev,
80968faa863SRuslan Bilovol 			"%u:%d : no UAC_FORMAT_TYPE desc\n",
81068faa863SRuslan Bilovol 			iface_no, altno);
81168faa863SRuslan Bilovol 		return NULL;
81268faa863SRuslan Bilovol 	}
81368faa863SRuslan Bilovol 	if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8))
81468faa863SRuslan Bilovol 			|| ((protocol == UAC_VERSION_2) &&
81568faa863SRuslan Bilovol 					(fmt->bLength < 6))) {
81668faa863SRuslan Bilovol 		dev_err(&dev->dev,
81768faa863SRuslan Bilovol 			"%u:%d : invalid UAC_FORMAT_TYPE desc\n",
81868faa863SRuslan Bilovol 			iface_no, altno);
81968faa863SRuslan Bilovol 		return NULL;
82068faa863SRuslan Bilovol 	}
82168faa863SRuslan Bilovol 
82268faa863SRuslan Bilovol 	/*
82368faa863SRuslan Bilovol 	 * Blue Microphones workaround: The last altsetting is
82468faa863SRuslan Bilovol 	 * identical with the previous one, except for a larger
82568faa863SRuslan Bilovol 	 * packet size, but is actually a mislabeled two-channel
82668faa863SRuslan Bilovol 	 * setting; ignore it.
82768faa863SRuslan Bilovol 	 *
82868faa863SRuslan Bilovol 	 * Part 2: analyze quirk flag and format
82968faa863SRuslan Bilovol 	 */
83068faa863SRuslan Bilovol 	if (bm_quirk && fmt->bNrChannels == 1 && fmt->bSubframeSize == 2)
83168faa863SRuslan Bilovol 		return NULL;
83268faa863SRuslan Bilovol 
83368faa863SRuslan Bilovol 	fp = audio_format_alloc_init(chip, alts, protocol, iface_no,
83468faa863SRuslan Bilovol 				     altset_idx, altno, num_channels, clock);
83568faa863SRuslan Bilovol 	if (!fp)
83668faa863SRuslan Bilovol 		return ERR_PTR(-ENOMEM);
83768faa863SRuslan Bilovol 
83868faa863SRuslan Bilovol 	fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol,
83968faa863SRuslan Bilovol 						       iface_no);
84068faa863SRuslan Bilovol 
84168faa863SRuslan Bilovol 	/* some quirks for attributes here */
84268faa863SRuslan Bilovol 	snd_usb_audioformat_attributes_quirk(chip, fp, stream);
84368faa863SRuslan Bilovol 
84468faa863SRuslan Bilovol 	/* ok, let's parse further... */
84568faa863SRuslan Bilovol 	if (snd_usb_parse_audio_format(chip, fp, format,
84668faa863SRuslan Bilovol 					fmt, stream) < 0) {
847c1ae5e7fSTakashi Iwai 		audioformat_free(fp);
84868faa863SRuslan Bilovol 		return NULL;
84968faa863SRuslan Bilovol 	}
85068faa863SRuslan Bilovol 
85168faa863SRuslan Bilovol 	/* Create chmap */
85268faa863SRuslan Bilovol 	if (fp->channels != num_channels)
85368faa863SRuslan Bilovol 		chconfig = 0;
85468faa863SRuslan Bilovol 
85568faa863SRuslan Bilovol 	fp->chmap = convert_chmap(fp->channels, chconfig, protocol);
85668faa863SRuslan Bilovol 
85768faa863SRuslan Bilovol 	return fp;
85868faa863SRuslan Bilovol }
8594d47fa84SRuslan Bilovol 
860eda553f4SRuslan Bilovol static struct audioformat *
snd_usb_get_audioformat_uac3(struct snd_usb_audio * chip,struct usb_host_interface * alts,struct snd_usb_power_domain ** pd_out,int iface_no,int altset_idx,int altno,int stream)861eda553f4SRuslan Bilovol snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
862eda553f4SRuslan Bilovol 			     struct usb_host_interface *alts,
8637edf3b5eSJorge Sanjuan 			     struct snd_usb_power_domain **pd_out,
864eda553f4SRuslan Bilovol 			     int iface_no, int altset_idx,
865eda553f4SRuslan Bilovol 			     int altno, int stream)
866eda553f4SRuslan Bilovol {
867eda553f4SRuslan Bilovol 	struct usb_device *dev = chip->dev;
868eda553f4SRuslan Bilovol 	struct uac3_input_terminal_descriptor *input_term;
869eda553f4SRuslan Bilovol 	struct uac3_output_terminal_descriptor *output_term;
870eda553f4SRuslan Bilovol 	struct uac3_cluster_header_descriptor *cluster;
87117156f23SRuslan Bilovol 	struct uac3_as_header_descriptor *as = NULL;
872eda553f4SRuslan Bilovol 	struct uac3_hc_descriptor_header hc_header;
873eda553f4SRuslan Bilovol 	struct snd_pcm_chmap_elem *chmap;
8747edf3b5eSJorge Sanjuan 	struct snd_usb_power_domain *pd;
87517156f23SRuslan Bilovol 	unsigned char badd_profile;
87617156f23SRuslan Bilovol 	u64 badd_formats = 0;
877eda553f4SRuslan Bilovol 	unsigned int num_channels;
878eda553f4SRuslan Bilovol 	struct audioformat *fp;
879eda553f4SRuslan Bilovol 	u16 cluster_id, wLength;
880eda553f4SRuslan Bilovol 	int clock = 0;
881eda553f4SRuslan Bilovol 	int err;
882eda553f4SRuslan Bilovol 
88317156f23SRuslan Bilovol 	badd_profile = chip->badd_profile;
88417156f23SRuslan Bilovol 
88517156f23SRuslan Bilovol 	if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
88617156f23SRuslan Bilovol 		unsigned int maxpacksize =
88717156f23SRuslan Bilovol 			le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
88817156f23SRuslan Bilovol 
88917156f23SRuslan Bilovol 		switch (maxpacksize) {
89017156f23SRuslan Bilovol 		default:
89117156f23SRuslan Bilovol 			dev_err(&dev->dev,
89217156f23SRuslan Bilovol 				"%u:%d : incorrect wMaxPacketSize for BADD profile\n",
89317156f23SRuslan Bilovol 				iface_no, altno);
89417156f23SRuslan Bilovol 			return NULL;
89517156f23SRuslan Bilovol 		case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16:
89617156f23SRuslan Bilovol 		case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16:
89717156f23SRuslan Bilovol 			badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
89817156f23SRuslan Bilovol 			num_channels = 1;
89917156f23SRuslan Bilovol 			break;
90017156f23SRuslan Bilovol 		case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24:
90117156f23SRuslan Bilovol 		case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24:
90217156f23SRuslan Bilovol 			badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
90317156f23SRuslan Bilovol 			num_channels = 1;
90417156f23SRuslan Bilovol 			break;
90517156f23SRuslan Bilovol 		case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16:
90617156f23SRuslan Bilovol 		case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16:
90717156f23SRuslan Bilovol 			badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
90817156f23SRuslan Bilovol 			num_channels = 2;
90917156f23SRuslan Bilovol 			break;
91017156f23SRuslan Bilovol 		case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24:
91117156f23SRuslan Bilovol 		case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24:
91217156f23SRuslan Bilovol 			badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
91317156f23SRuslan Bilovol 			num_channels = 2;
91417156f23SRuslan Bilovol 			break;
91517156f23SRuslan Bilovol 		}
91617156f23SRuslan Bilovol 
91717156f23SRuslan Bilovol 		chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
91817156f23SRuslan Bilovol 		if (!chmap)
91917156f23SRuslan Bilovol 			return ERR_PTR(-ENOMEM);
92017156f23SRuslan Bilovol 
92117156f23SRuslan Bilovol 		if (num_channels == 1) {
92217156f23SRuslan Bilovol 			chmap->map[0] = SNDRV_CHMAP_MONO;
92317156f23SRuslan Bilovol 		} else {
92417156f23SRuslan Bilovol 			chmap->map[0] = SNDRV_CHMAP_FL;
92517156f23SRuslan Bilovol 			chmap->map[1] = SNDRV_CHMAP_FR;
92617156f23SRuslan Bilovol 		}
92717156f23SRuslan Bilovol 
92817156f23SRuslan Bilovol 		chmap->channels = num_channels;
92917156f23SRuslan Bilovol 		clock = UAC3_BADD_CS_ID9;
93017156f23SRuslan Bilovol 		goto found_clock;
93117156f23SRuslan Bilovol 	}
93217156f23SRuslan Bilovol 
933eda553f4SRuslan Bilovol 	as = snd_usb_find_csint_desc(alts->extra, alts->extralen,
934eda553f4SRuslan Bilovol 				     NULL, UAC_AS_GENERAL);
935eda553f4SRuslan Bilovol 	if (!as) {
936eda553f4SRuslan Bilovol 		dev_err(&dev->dev,
937eda553f4SRuslan Bilovol 			"%u:%d : UAC_AS_GENERAL descriptor not found\n",
938eda553f4SRuslan Bilovol 			iface_no, altno);
939eda553f4SRuslan Bilovol 		return NULL;
940eda553f4SRuslan Bilovol 	}
941eda553f4SRuslan Bilovol 
942eda553f4SRuslan Bilovol 	if (as->bLength < sizeof(*as)) {
943eda553f4SRuslan Bilovol 		dev_err(&dev->dev,
944eda553f4SRuslan Bilovol 			"%u:%d : invalid UAC_AS_GENERAL desc\n",
945eda553f4SRuslan Bilovol 			iface_no, altno);
946eda553f4SRuslan Bilovol 		return NULL;
947eda553f4SRuslan Bilovol 	}
948eda553f4SRuslan Bilovol 
949eda553f4SRuslan Bilovol 	cluster_id = le16_to_cpu(as->wClusterDescrID);
950eda553f4SRuslan Bilovol 	if (!cluster_id) {
951eda553f4SRuslan Bilovol 		dev_err(&dev->dev,
952eda553f4SRuslan Bilovol 			"%u:%d : no cluster descriptor\n",
953eda553f4SRuslan Bilovol 			iface_no, altno);
954eda553f4SRuslan Bilovol 		return NULL;
955eda553f4SRuslan Bilovol 	}
956eda553f4SRuslan Bilovol 
957eda553f4SRuslan Bilovol 	/*
958eda553f4SRuslan Bilovol 	 * Get number of channels and channel map through
959eda553f4SRuslan Bilovol 	 * High Capability Cluster Descriptor
960eda553f4SRuslan Bilovol 	 *
961eda553f4SRuslan Bilovol 	 * First step: get High Capability header and
962eda553f4SRuslan Bilovol 	 * read size of Cluster Descriptor
963eda553f4SRuslan Bilovol 	 */
964eda553f4SRuslan Bilovol 	err = snd_usb_ctl_msg(chip->dev,
965eda553f4SRuslan Bilovol 			usb_rcvctrlpipe(chip->dev, 0),
966eda553f4SRuslan Bilovol 			UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
967eda553f4SRuslan Bilovol 			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
968eda553f4SRuslan Bilovol 			cluster_id,
969eda553f4SRuslan Bilovol 			snd_usb_ctrl_intf(chip),
970eda553f4SRuslan Bilovol 			&hc_header, sizeof(hc_header));
971eda553f4SRuslan Bilovol 	if (err < 0)
972eda553f4SRuslan Bilovol 		return ERR_PTR(err);
973eda553f4SRuslan Bilovol 	else if (err != sizeof(hc_header)) {
974eda553f4SRuslan Bilovol 		dev_err(&dev->dev,
975eda553f4SRuslan Bilovol 			"%u:%d : can't get High Capability descriptor\n",
976eda553f4SRuslan Bilovol 			iface_no, altno);
977eda553f4SRuslan Bilovol 		return ERR_PTR(-EIO);
978eda553f4SRuslan Bilovol 	}
979eda553f4SRuslan Bilovol 
980eda553f4SRuslan Bilovol 	/*
981eda553f4SRuslan Bilovol 	 * Second step: allocate needed amount of memory
982eda553f4SRuslan Bilovol 	 * and request Cluster Descriptor
983eda553f4SRuslan Bilovol 	 */
984eda553f4SRuslan Bilovol 	wLength = le16_to_cpu(hc_header.wLength);
985eda553f4SRuslan Bilovol 	cluster = kzalloc(wLength, GFP_KERNEL);
986eda553f4SRuslan Bilovol 	if (!cluster)
987eda553f4SRuslan Bilovol 		return ERR_PTR(-ENOMEM);
988eda553f4SRuslan Bilovol 	err = snd_usb_ctl_msg(chip->dev,
989eda553f4SRuslan Bilovol 			usb_rcvctrlpipe(chip->dev, 0),
990eda553f4SRuslan Bilovol 			UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
991eda553f4SRuslan Bilovol 			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
992eda553f4SRuslan Bilovol 			cluster_id,
993eda553f4SRuslan Bilovol 			snd_usb_ctrl_intf(chip),
994eda553f4SRuslan Bilovol 			cluster, wLength);
995eda553f4SRuslan Bilovol 	if (err < 0) {
996eda553f4SRuslan Bilovol 		kfree(cluster);
997eda553f4SRuslan Bilovol 		return ERR_PTR(err);
998eda553f4SRuslan Bilovol 	} else if (err != wLength) {
999eda553f4SRuslan Bilovol 		dev_err(&dev->dev,
1000eda553f4SRuslan Bilovol 			"%u:%d : can't get Cluster Descriptor\n",
1001eda553f4SRuslan Bilovol 			iface_no, altno);
1002eda553f4SRuslan Bilovol 		kfree(cluster);
1003eda553f4SRuslan Bilovol 		return ERR_PTR(-EIO);
1004eda553f4SRuslan Bilovol 	}
1005eda553f4SRuslan Bilovol 
1006eda553f4SRuslan Bilovol 	num_channels = cluster->bNrChannels;
1007eda553f4SRuslan Bilovol 	chmap = convert_chmap_v3(cluster);
1008eda553f4SRuslan Bilovol 	kfree(cluster);
1009eda553f4SRuslan Bilovol 
1010eda553f4SRuslan Bilovol 	/*
1011eda553f4SRuslan Bilovol 	 * lookup the terminal associated to this interface
1012eda553f4SRuslan Bilovol 	 * to extract the clock
1013eda553f4SRuslan Bilovol 	 */
1014eda553f4SRuslan Bilovol 	input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
10153e96d728STakashi Iwai 							    as->bTerminalLink,
101657f87706STakashi Iwai 							    UAC_VERSION_3);
1017eda553f4SRuslan Bilovol 	if (input_term) {
1018eda553f4SRuslan Bilovol 		clock = input_term->bCSourceID;
1019eda553f4SRuslan Bilovol 		goto found_clock;
1020eda553f4SRuslan Bilovol 	}
1021eda553f4SRuslan Bilovol 
1022eda553f4SRuslan Bilovol 	output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
102357f87706STakashi Iwai 							      as->bTerminalLink,
102457f87706STakashi Iwai 							      UAC_VERSION_3);
1025eda553f4SRuslan Bilovol 	if (output_term) {
1026eda553f4SRuslan Bilovol 		clock = output_term->bCSourceID;
1027eda553f4SRuslan Bilovol 		goto found_clock;
1028eda553f4SRuslan Bilovol 	}
1029eda553f4SRuslan Bilovol 
1030eda553f4SRuslan Bilovol 	dev_err(&dev->dev, "%u:%d : bogus bTerminalLink %d\n",
1031eda553f4SRuslan Bilovol 			iface_no, altno, as->bTerminalLink);
10326cd17ea7SRuslan Bilovol 	kfree(chmap);
1033eda553f4SRuslan Bilovol 	return NULL;
1034eda553f4SRuslan Bilovol 
1035eda553f4SRuslan Bilovol found_clock:
1036eda553f4SRuslan Bilovol 	fp = audio_format_alloc_init(chip, alts, UAC_VERSION_3, iface_no,
1037eda553f4SRuslan Bilovol 				     altset_idx, altno, num_channels, clock);
10386cd17ea7SRuslan Bilovol 	if (!fp) {
10396cd17ea7SRuslan Bilovol 		kfree(chmap);
1040eda553f4SRuslan Bilovol 		return ERR_PTR(-ENOMEM);
10416cd17ea7SRuslan Bilovol 	}
1042eda553f4SRuslan Bilovol 
104317156f23SRuslan Bilovol 	fp->chmap = chmap;
104417156f23SRuslan Bilovol 
104517156f23SRuslan Bilovol 	if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
104617156f23SRuslan Bilovol 		fp->attributes = 0; /* No attributes */
104717156f23SRuslan Bilovol 
104817156f23SRuslan Bilovol 		fp->fmt_type = UAC_FORMAT_TYPE_I;
104917156f23SRuslan Bilovol 		fp->formats = badd_formats;
105017156f23SRuslan Bilovol 
105117156f23SRuslan Bilovol 		fp->nr_rates = 0;	/* SNDRV_PCM_RATE_CONTINUOUS */
105217156f23SRuslan Bilovol 		fp->rate_min = UAC3_BADD_SAMPLING_RATE;
105317156f23SRuslan Bilovol 		fp->rate_max = UAC3_BADD_SAMPLING_RATE;
105417156f23SRuslan Bilovol 		fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
105517156f23SRuslan Bilovol 
105611175556SWei Yongjun 		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
10577edf3b5eSJorge Sanjuan 		if (!pd) {
1058c1ae5e7fSTakashi Iwai 			audioformat_free(fp);
10597edf3b5eSJorge Sanjuan 			return NULL;
10607edf3b5eSJorge Sanjuan 		}
10617edf3b5eSJorge Sanjuan 		pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
10627edf3b5eSJorge Sanjuan 					UAC3_BADD_PD_ID10 : UAC3_BADD_PD_ID11;
10637edf3b5eSJorge Sanjuan 		pd->pd_d1d0_rec = UAC3_BADD_PD_RECOVER_D1D0;
10647edf3b5eSJorge Sanjuan 		pd->pd_d2d0_rec = UAC3_BADD_PD_RECOVER_D2D0;
10657edf3b5eSJorge Sanjuan 
106617156f23SRuslan Bilovol 	} else {
1067eda553f4SRuslan Bilovol 		fp->attributes = parse_uac_endpoint_attributes(chip, alts,
1068eda553f4SRuslan Bilovol 							       UAC_VERSION_3,
1069eda553f4SRuslan Bilovol 							       iface_no);
10707edf3b5eSJorge Sanjuan 
10717edf3b5eSJorge Sanjuan 		pd = snd_usb_find_power_domain(chip->ctrl_intf,
10727edf3b5eSJorge Sanjuan 					       as->bTerminalLink);
10737edf3b5eSJorge Sanjuan 
1074eda553f4SRuslan Bilovol 		/* ok, let's parse further... */
1075eda553f4SRuslan Bilovol 		if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) {
10767edf3b5eSJorge Sanjuan 			kfree(pd);
1077c1ae5e7fSTakashi Iwai 			audioformat_free(fp);
1078eda553f4SRuslan Bilovol 			return NULL;
1079eda553f4SRuslan Bilovol 		}
108017156f23SRuslan Bilovol 	}
1081eda553f4SRuslan Bilovol 
10827edf3b5eSJorge Sanjuan 	if (pd)
10837edf3b5eSJorge Sanjuan 		*pd_out = pd;
10847edf3b5eSJorge Sanjuan 
1085eda553f4SRuslan Bilovol 	return fp;
1086eda553f4SRuslan Bilovol }
1087eda553f4SRuslan Bilovol 
__snd_usb_parse_audio_interface(struct snd_usb_audio * chip,int iface_no,bool * has_non_pcm,bool non_pcm)1088f7f53018SAlexander Tsoy static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
1089f7f53018SAlexander Tsoy 					   int iface_no,
1090f7f53018SAlexander Tsoy 					   bool *has_non_pcm, bool non_pcm)
1091e8e8babfSDaniel Mack {
1092e8e8babfSDaniel Mack 	struct usb_device *dev;
1093e8e8babfSDaniel Mack 	struct usb_interface *iface;
1094e8e8babfSDaniel Mack 	struct usb_host_interface *alts;
1095e8e8babfSDaniel Mack 	struct usb_interface_descriptor *altsd;
1096e8e8babfSDaniel Mack 	int i, altno, err, stream;
1097e8e8babfSDaniel Mack 	struct audioformat *fp = NULL;
10987edf3b5eSJorge Sanjuan 	struct snd_usb_power_domain *pd = NULL;
10995fadc941STakashi Iwai 	bool set_iface_first;
1100eda553f4SRuslan Bilovol 	int num, protocol;
1101e8e8babfSDaniel Mack 
1102e8e8babfSDaniel Mack 	dev = chip->dev;
1103e8e8babfSDaniel Mack 
1104e8e8babfSDaniel Mack 	/* parse the interface's altsettings */
1105e8e8babfSDaniel Mack 	iface = usb_ifnum_to_if(dev, iface_no);
1106e8e8babfSDaniel Mack 
1107e8e8babfSDaniel Mack 	num = iface->num_altsetting;
1108e8e8babfSDaniel Mack 
1109e8e8babfSDaniel Mack 	/*
1110e8e8babfSDaniel Mack 	 * Dallas DS4201 workaround: It presents 5 altsettings, but the last
1111e8e8babfSDaniel Mack 	 * one misses syncpipe, and does not produce any sound.
1112e8e8babfSDaniel Mack 	 */
1113e53f47f6SDongxiang Ke 	if (chip->usb_id == USB_ID(0x04fa, 0x4201) && num >= 4)
1114e8e8babfSDaniel Mack 		num = 4;
1115e8e8babfSDaniel Mack 
1116e8e8babfSDaniel Mack 	for (i = 0; i < num; i++) {
1117e8e8babfSDaniel Mack 		alts = &iface->altsetting[i];
1118e8e8babfSDaniel Mack 		altsd = get_iface_desc(alts);
1119e8e8babfSDaniel Mack 		protocol = altsd->bInterfaceProtocol;
1120e8e8babfSDaniel Mack 		/* skip invalid one */
1121aafe77ccSClemens Ladisch 		if (((altsd->bInterfaceClass != USB_CLASS_AUDIO ||
1122e8e8babfSDaniel Mack 		      (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
1123aafe77ccSClemens Ladisch 		       altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC)) &&
1124aafe77ccSClemens Ladisch 		     altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
1125e8e8babfSDaniel Mack 		    altsd->bNumEndpoints < 1 ||
1126e8e8babfSDaniel Mack 		    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
1127e8e8babfSDaniel Mack 			continue;
1128e8e8babfSDaniel Mack 		/* must be isochronous */
1129e8e8babfSDaniel Mack 		if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
1130e8e8babfSDaniel Mack 		    USB_ENDPOINT_XFER_ISOC)
1131e8e8babfSDaniel Mack 			continue;
1132e8e8babfSDaniel Mack 		/* check direction */
1133e8e8babfSDaniel Mack 		stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
1134e8e8babfSDaniel Mack 			SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
1135e8e8babfSDaniel Mack 		altno = altsd->bAlternateSetting;
1136e8e8babfSDaniel Mack 
1137e8e8babfSDaniel Mack 		if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
1138e8e8babfSDaniel Mack 			continue;
1139e8e8babfSDaniel Mack 
1140aafe77ccSClemens Ladisch 		/*
1141aafe77ccSClemens Ladisch 		 * Roland audio streaming interfaces are marked with protocols
1142aafe77ccSClemens Ladisch 		 * 0/1/2, but are UAC 1 compatible.
1143aafe77ccSClemens Ladisch 		 */
1144aafe77ccSClemens Ladisch 		if (USB_ID_VENDOR(chip->usb_id) == 0x0582 &&
1145aafe77ccSClemens Ladisch 		    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
1146aafe77ccSClemens Ladisch 		    protocol <= 2)
1147aafe77ccSClemens Ladisch 			protocol = UAC_VERSION_1;
1148aafe77ccSClemens Ladisch 
1149e8e8babfSDaniel Mack 		switch (protocol) {
1150e8e8babfSDaniel Mack 		default:
11510ba41d91STakashi Iwai 			dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n",
11520ba41d91STakashi Iwai 				iface_no, altno, protocol);
1153e8e8babfSDaniel Mack 			protocol = UAC_VERSION_1;
1154c0dbbdadSGustavo A. R. Silva 			fallthrough;
115568faa863SRuslan Bilovol 		case UAC_VERSION_1:
1156e8e8babfSDaniel Mack 		case UAC_VERSION_2: {
115768faa863SRuslan Bilovol 			int bm_quirk = 0;
1158e8e8babfSDaniel Mack 
115968faa863SRuslan Bilovol 			/*
116068faa863SRuslan Bilovol 			 * Blue Microphones workaround: The last altsetting is
116168faa863SRuslan Bilovol 			 * identical with the previous one, except for a larger
116268faa863SRuslan Bilovol 			 * packet size, but is actually a mislabeled two-channel
116368faa863SRuslan Bilovol 			 * setting; ignore it.
116468faa863SRuslan Bilovol 			 *
116568faa863SRuslan Bilovol 			 * Part 1: prepare quirk flag
116668faa863SRuslan Bilovol 			 */
116768faa863SRuslan Bilovol 			if (altno == 2 && num == 3 &&
116868faa863SRuslan Bilovol 			    fp && fp->altsetting == 1 && fp->channels == 1 &&
116968faa863SRuslan Bilovol 			    fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
117068faa863SRuslan Bilovol 			    protocol == UAC_VERSION_1 &&
117168faa863SRuslan Bilovol 			    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
117268faa863SRuslan Bilovol 							fp->maxpacksize * 2)
117368faa863SRuslan Bilovol 				bm_quirk = 1;
1174e8e8babfSDaniel Mack 
117568faa863SRuslan Bilovol 			fp = snd_usb_get_audioformat_uac12(chip, alts, protocol,
117668faa863SRuslan Bilovol 							   iface_no, i, altno,
117768faa863SRuslan Bilovol 							   stream, bm_quirk);
1178e8e8babfSDaniel Mack 			break;
1179e8e8babfSDaniel Mack 		}
1180eda553f4SRuslan Bilovol 		case UAC_VERSION_3:
11817edf3b5eSJorge Sanjuan 			fp = snd_usb_get_audioformat_uac3(chip, alts, &pd,
1182eda553f4SRuslan Bilovol 						iface_no, i, altno, stream);
11839a2fe9b8SRuslan Bilovol 			break;
11849a2fe9b8SRuslan Bilovol 		}
11859a2fe9b8SRuslan Bilovol 
118668faa863SRuslan Bilovol 		if (!fp)
1187e8e8babfSDaniel Mack 			continue;
118868faa863SRuslan Bilovol 		else if (IS_ERR(fp))
118968faa863SRuslan Bilovol 			return PTR_ERR(fp);
1190e8e8babfSDaniel Mack 
1191f7f53018SAlexander Tsoy 		if (fp->fmt_type != UAC_FORMAT_TYPE_I)
1192f7f53018SAlexander Tsoy 			*has_non_pcm = true;
1193f7f53018SAlexander Tsoy 		if ((fp->fmt_type == UAC_FORMAT_TYPE_I) == non_pcm) {
1194f7f53018SAlexander Tsoy 			audioformat_free(fp);
1195f7f53018SAlexander Tsoy 			kfree(pd);
1196f7f53018SAlexander Tsoy 			fp = NULL;
1197f7f53018SAlexander Tsoy 			pd = NULL;
1198f7f53018SAlexander Tsoy 			continue;
1199f7f53018SAlexander Tsoy 		}
1200f7f53018SAlexander Tsoy 
1201f6581c0eSTakashi Iwai 		snd_usb_audioformat_set_sync_ep(chip, fp);
1202f6581c0eSTakashi Iwai 
12030ba41d91STakashi Iwai 		dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
12047edf3b5eSJorge Sanjuan 		if (protocol == UAC_VERSION_3)
12057edf3b5eSJorge Sanjuan 			err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd);
12067edf3b5eSJorge Sanjuan 		else
1207e8e8babfSDaniel Mack 			err = snd_usb_add_audio_stream(chip, stream, fp);
12087edf3b5eSJorge Sanjuan 
1209e8e8babfSDaniel Mack 		if (err < 0) {
1210c1ae5e7fSTakashi Iwai 			audioformat_free(fp);
12117edf3b5eSJorge Sanjuan 			kfree(pd);
1212e8e8babfSDaniel Mack 			return err;
1213e8e8babfSDaniel Mack 		}
121454cb3190STakashi Iwai 
121554cb3190STakashi Iwai 		/* add endpoints */
121654cb3190STakashi Iwai 		err = snd_usb_add_endpoint(chip, fp->endpoint,
121754cb3190STakashi Iwai 					   SND_USB_ENDPOINT_TYPE_DATA);
121854cb3190STakashi Iwai 		if (err < 0)
121954cb3190STakashi Iwai 			return err;
122054cb3190STakashi Iwai 
122154cb3190STakashi Iwai 		if (fp->sync_ep) {
122254cb3190STakashi Iwai 			err = snd_usb_add_endpoint(chip, fp->sync_ep,
122354cb3190STakashi Iwai 						   fp->implicit_fb ?
122454cb3190STakashi Iwai 						   SND_USB_ENDPOINT_TYPE_DATA :
122554cb3190STakashi Iwai 						   SND_USB_ENDPOINT_TYPE_SYNC);
122654cb3190STakashi Iwai 			if (err < 0)
122754cb3190STakashi Iwai 				return err;
122854cb3190STakashi Iwai 		}
122916f1f838STakashi Iwai 
12305fadc941STakashi Iwai 		set_iface_first = false;
12315fadc941STakashi Iwai 		if (protocol == UAC_VERSION_1 ||
12325fadc941STakashi Iwai 		    (chip->quirk_flags & QUIRK_FLAG_SET_IFACE_FIRST))
12335fadc941STakashi Iwai 			set_iface_first = true;
12345fadc941STakashi Iwai 
123516f1f838STakashi Iwai 		/* try to set the interface... */
123616f1f838STakashi Iwai 		usb_set_interface(chip->dev, iface_no, 0);
12375fadc941STakashi Iwai 		if (set_iface_first)
12385fadc941STakashi Iwai 			usb_set_interface(chip->dev, iface_no, altno);
123916f1f838STakashi Iwai 		snd_usb_init_pitch(chip, fp);
124016f1f838STakashi Iwai 		snd_usb_init_sample_rate(chip, fp, fp->rate_max);
12415fadc941STakashi Iwai 		if (!set_iface_first)
124216f1f838STakashi Iwai 			usb_set_interface(chip->dev, iface_no, altno);
1243e8e8babfSDaniel Mack 	}
1244e8e8babfSDaniel Mack 	return 0;
1245e8e8babfSDaniel Mack }
1246e8e8babfSDaniel Mack 
snd_usb_parse_audio_interface(struct snd_usb_audio * chip,int iface_no)1247f7f53018SAlexander Tsoy int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
1248f7f53018SAlexander Tsoy {
1249f7f53018SAlexander Tsoy 	int err;
1250f7f53018SAlexander Tsoy 	bool has_non_pcm = false;
1251f7f53018SAlexander Tsoy 
1252f7f53018SAlexander Tsoy 	/* parse PCM formats */
1253f7f53018SAlexander Tsoy 	err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, false);
1254f7f53018SAlexander Tsoy 	if (err < 0)
1255f7f53018SAlexander Tsoy 		return err;
1256f7f53018SAlexander Tsoy 
1257f7f53018SAlexander Tsoy 	if (has_non_pcm) {
1258f7f53018SAlexander Tsoy 		/* parse non-PCM formats */
1259f7f53018SAlexander Tsoy 		err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, true);
1260f7f53018SAlexander Tsoy 		if (err < 0)
1261f7f53018SAlexander Tsoy 			return err;
1262f7f53018SAlexander Tsoy 	}
1263f7f53018SAlexander Tsoy 
1264f7f53018SAlexander Tsoy 	return 0;
1265f7f53018SAlexander Tsoy }
1266f7f53018SAlexander Tsoy 
1267