162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci */
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/init.h>
762306a36Sopenharmony_ci#include <linux/slab.h>
862306a36Sopenharmony_ci#include <linux/usb.h>
962306a36Sopenharmony_ci#include <linux/usb/audio.h>
1062306a36Sopenharmony_ci#include <linux/usb/audio-v2.h>
1162306a36Sopenharmony_ci#include <linux/usb/audio-v3.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <sound/core.h>
1462306a36Sopenharmony_ci#include <sound/pcm.h>
1562306a36Sopenharmony_ci#include <sound/control.h>
1662306a36Sopenharmony_ci#include <sound/tlv.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include "usbaudio.h"
1962306a36Sopenharmony_ci#include "card.h"
2062306a36Sopenharmony_ci#include "proc.h"
2162306a36Sopenharmony_ci#include "quirks.h"
2262306a36Sopenharmony_ci#include "endpoint.h"
2362306a36Sopenharmony_ci#include "pcm.h"
2462306a36Sopenharmony_ci#include "helper.h"
2562306a36Sopenharmony_ci#include "format.h"
2662306a36Sopenharmony_ci#include "clock.h"
2762306a36Sopenharmony_ci#include "stream.h"
2862306a36Sopenharmony_ci#include "power.h"
2962306a36Sopenharmony_ci#include "media.h"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic void audioformat_free(struct audioformat *fp)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	list_del(&fp->list); /* unlink for avoiding double-free */
3462306a36Sopenharmony_ci	kfree(fp->rate_table);
3562306a36Sopenharmony_ci	kfree(fp->chmap);
3662306a36Sopenharmony_ci	kfree(fp);
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/*
4062306a36Sopenharmony_ci * free a substream
4162306a36Sopenharmony_ci */
4262306a36Sopenharmony_cistatic void free_substream(struct snd_usb_substream *subs)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	struct audioformat *fp, *n;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	if (!subs->num_formats)
4762306a36Sopenharmony_ci		return; /* not initialized */
4862306a36Sopenharmony_ci	list_for_each_entry_safe(fp, n, &subs->fmt_list, list)
4962306a36Sopenharmony_ci		audioformat_free(fp);
5062306a36Sopenharmony_ci	kfree(subs->str_pd);
5162306a36Sopenharmony_ci	snd_media_stream_delete(subs);
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/*
5662306a36Sopenharmony_ci * free a usb stream instance
5762306a36Sopenharmony_ci */
5862306a36Sopenharmony_cistatic void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	free_substream(&stream->substream[0]);
6162306a36Sopenharmony_ci	free_substream(&stream->substream[1]);
6262306a36Sopenharmony_ci	list_del(&stream->list);
6362306a36Sopenharmony_ci	kfree(stream);
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	struct snd_usb_stream *stream = pcm->private_data;
6962306a36Sopenharmony_ci	if (stream) {
7062306a36Sopenharmony_ci		stream->pcm = NULL;
7162306a36Sopenharmony_ci		snd_usb_audio_stream_free(stream);
7262306a36Sopenharmony_ci	}
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/*
7662306a36Sopenharmony_ci * initialize the substream instance.
7762306a36Sopenharmony_ci */
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic void snd_usb_init_substream(struct snd_usb_stream *as,
8062306a36Sopenharmony_ci				   int stream,
8162306a36Sopenharmony_ci				   struct audioformat *fp,
8262306a36Sopenharmony_ci				   struct snd_usb_power_domain *pd)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct snd_usb_substream *subs = &as->substream[stream];
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	INIT_LIST_HEAD(&subs->fmt_list);
8762306a36Sopenharmony_ci	spin_lock_init(&subs->lock);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	subs->stream = as;
9062306a36Sopenharmony_ci	subs->direction = stream;
9162306a36Sopenharmony_ci	subs->dev = as->chip->dev;
9262306a36Sopenharmony_ci	subs->txfr_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_ALIGN_TRANSFER);
9362306a36Sopenharmony_ci	subs->tx_length_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_TX_LENGTH);
9462306a36Sopenharmony_ci	subs->speed = snd_usb_get_speed(subs->dev);
9562306a36Sopenharmony_ci	subs->pkt_offset_adj = 0;
9662306a36Sopenharmony_ci	subs->stream_offset_adj = 0;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	snd_usb_set_pcm_ops(as->pcm, stream);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	list_add_tail(&fp->list, &subs->fmt_list);
10162306a36Sopenharmony_ci	subs->formats |= fp->formats;
10262306a36Sopenharmony_ci	subs->num_formats++;
10362306a36Sopenharmony_ci	subs->fmt_type = fp->fmt_type;
10462306a36Sopenharmony_ci	subs->ep_num = fp->endpoint;
10562306a36Sopenharmony_ci	if (fp->channels > subs->channels_max)
10662306a36Sopenharmony_ci		subs->channels_max = fp->channels;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	if (pd) {
10962306a36Sopenharmony_ci		subs->str_pd = pd;
11062306a36Sopenharmony_ci		/* Initialize Power Domain to idle status D1 */
11162306a36Sopenharmony_ci		snd_usb_power_domain_set(subs->stream->chip, pd,
11262306a36Sopenharmony_ci					 UAC3_PD_STATE_D1);
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	snd_usb_preallocate_buffer(subs);
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/* kctl callbacks for usb-audio channel maps */
11962306a36Sopenharmony_cistatic int usb_chmap_ctl_info(struct snd_kcontrol *kcontrol,
12062306a36Sopenharmony_ci			      struct snd_ctl_elem_info *uinfo)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
12362306a36Sopenharmony_ci	struct snd_usb_substream *subs = info->private_data;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
12662306a36Sopenharmony_ci	uinfo->count = subs->channels_max;
12762306a36Sopenharmony_ci	uinfo->value.integer.min = 0;
12862306a36Sopenharmony_ci	uinfo->value.integer.max = SNDRV_CHMAP_LAST;
12962306a36Sopenharmony_ci	return 0;
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci/* check whether a duplicated entry exists in the audiofmt list */
13362306a36Sopenharmony_cistatic bool have_dup_chmap(struct snd_usb_substream *subs,
13462306a36Sopenharmony_ci			   struct audioformat *fp)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	struct audioformat *prev = fp;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	list_for_each_entry_continue_reverse(prev, &subs->fmt_list, list) {
13962306a36Sopenharmony_ci		if (prev->chmap &&
14062306a36Sopenharmony_ci		    !memcmp(prev->chmap, fp->chmap, sizeof(*fp->chmap)))
14162306a36Sopenharmony_ci			return true;
14262306a36Sopenharmony_ci	}
14362306a36Sopenharmony_ci	return false;
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
14762306a36Sopenharmony_ci			     unsigned int size, unsigned int __user *tlv)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
15062306a36Sopenharmony_ci	struct snd_usb_substream *subs = info->private_data;
15162306a36Sopenharmony_ci	struct audioformat *fp;
15262306a36Sopenharmony_ci	unsigned int __user *dst;
15362306a36Sopenharmony_ci	int count = 0;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	if (size < 8)
15662306a36Sopenharmony_ci		return -ENOMEM;
15762306a36Sopenharmony_ci	if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
15862306a36Sopenharmony_ci		return -EFAULT;
15962306a36Sopenharmony_ci	size -= 8;
16062306a36Sopenharmony_ci	dst = tlv + 2;
16162306a36Sopenharmony_ci	list_for_each_entry(fp, &subs->fmt_list, list) {
16262306a36Sopenharmony_ci		int i, ch_bytes;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci		if (!fp->chmap)
16562306a36Sopenharmony_ci			continue;
16662306a36Sopenharmony_ci		if (have_dup_chmap(subs, fp))
16762306a36Sopenharmony_ci			continue;
16862306a36Sopenharmony_ci		/* copy the entry */
16962306a36Sopenharmony_ci		ch_bytes = fp->chmap->channels * 4;
17062306a36Sopenharmony_ci		if (size < 8 + ch_bytes)
17162306a36Sopenharmony_ci			return -ENOMEM;
17262306a36Sopenharmony_ci		if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
17362306a36Sopenharmony_ci		    put_user(ch_bytes, dst + 1))
17462306a36Sopenharmony_ci			return -EFAULT;
17562306a36Sopenharmony_ci		dst += 2;
17662306a36Sopenharmony_ci		for (i = 0; i < fp->chmap->channels; i++, dst++) {
17762306a36Sopenharmony_ci			if (put_user(fp->chmap->map[i], dst))
17862306a36Sopenharmony_ci				return -EFAULT;
17962306a36Sopenharmony_ci		}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci		count += 8 + ch_bytes;
18262306a36Sopenharmony_ci		size -= 8 + ch_bytes;
18362306a36Sopenharmony_ci	}
18462306a36Sopenharmony_ci	if (put_user(count, tlv + 1))
18562306a36Sopenharmony_ci		return -EFAULT;
18662306a36Sopenharmony_ci	return 0;
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistatic int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol,
19062306a36Sopenharmony_ci			     struct snd_ctl_elem_value *ucontrol)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
19362306a36Sopenharmony_ci	struct snd_usb_substream *subs = info->private_data;
19462306a36Sopenharmony_ci	struct snd_pcm_chmap_elem *chmap = NULL;
19562306a36Sopenharmony_ci	int i = 0;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	if (subs->cur_audiofmt)
19862306a36Sopenharmony_ci		chmap = subs->cur_audiofmt->chmap;
19962306a36Sopenharmony_ci	if (chmap) {
20062306a36Sopenharmony_ci		for (i = 0; i < chmap->channels; i++)
20162306a36Sopenharmony_ci			ucontrol->value.integer.value[i] = chmap->map[i];
20262306a36Sopenharmony_ci	}
20362306a36Sopenharmony_ci	for (; i < subs->channels_max; i++)
20462306a36Sopenharmony_ci		ucontrol->value.integer.value[i] = 0;
20562306a36Sopenharmony_ci	return 0;
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci/* create a chmap kctl assigned to the given USB substream */
20962306a36Sopenharmony_cistatic int add_chmap(struct snd_pcm *pcm, int stream,
21062306a36Sopenharmony_ci		     struct snd_usb_substream *subs)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	struct audioformat *fp;
21362306a36Sopenharmony_ci	struct snd_pcm_chmap *chmap;
21462306a36Sopenharmony_ci	struct snd_kcontrol *kctl;
21562306a36Sopenharmony_ci	int err;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	list_for_each_entry(fp, &subs->fmt_list, list)
21862306a36Sopenharmony_ci		if (fp->chmap)
21962306a36Sopenharmony_ci			goto ok;
22062306a36Sopenharmony_ci	/* no chmap is found */
22162306a36Sopenharmony_ci	return 0;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci ok:
22462306a36Sopenharmony_ci	err = snd_pcm_add_chmap_ctls(pcm, stream, NULL, 0, 0, &chmap);
22562306a36Sopenharmony_ci	if (err < 0)
22662306a36Sopenharmony_ci		return err;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	/* override handlers */
22962306a36Sopenharmony_ci	chmap->private_data = subs;
23062306a36Sopenharmony_ci	kctl = chmap->kctl;
23162306a36Sopenharmony_ci	kctl->info = usb_chmap_ctl_info;
23262306a36Sopenharmony_ci	kctl->get = usb_chmap_ctl_get;
23362306a36Sopenharmony_ci	kctl->tlv.c = usb_chmap_ctl_tlv;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	return 0;
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci/* convert from USB ChannelConfig bits to ALSA chmap element */
23962306a36Sopenharmony_cistatic struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
24062306a36Sopenharmony_ci						int protocol)
24162306a36Sopenharmony_ci{
24262306a36Sopenharmony_ci	static const unsigned int uac1_maps[] = {
24362306a36Sopenharmony_ci		SNDRV_CHMAP_FL,		/* left front */
24462306a36Sopenharmony_ci		SNDRV_CHMAP_FR,		/* right front */
24562306a36Sopenharmony_ci		SNDRV_CHMAP_FC,		/* center front */
24662306a36Sopenharmony_ci		SNDRV_CHMAP_LFE,	/* LFE */
24762306a36Sopenharmony_ci		SNDRV_CHMAP_SL,		/* left surround */
24862306a36Sopenharmony_ci		SNDRV_CHMAP_SR,		/* right surround */
24962306a36Sopenharmony_ci		SNDRV_CHMAP_FLC,	/* left of center */
25062306a36Sopenharmony_ci		SNDRV_CHMAP_FRC,	/* right of center */
25162306a36Sopenharmony_ci		SNDRV_CHMAP_RC,		/* surround */
25262306a36Sopenharmony_ci		SNDRV_CHMAP_SL,		/* side left */
25362306a36Sopenharmony_ci		SNDRV_CHMAP_SR,		/* side right */
25462306a36Sopenharmony_ci		SNDRV_CHMAP_TC,		/* top */
25562306a36Sopenharmony_ci		0 /* terminator */
25662306a36Sopenharmony_ci	};
25762306a36Sopenharmony_ci	static const unsigned int uac2_maps[] = {
25862306a36Sopenharmony_ci		SNDRV_CHMAP_FL,		/* front left */
25962306a36Sopenharmony_ci		SNDRV_CHMAP_FR,		/* front right */
26062306a36Sopenharmony_ci		SNDRV_CHMAP_FC,		/* front center */
26162306a36Sopenharmony_ci		SNDRV_CHMAP_LFE,	/* LFE */
26262306a36Sopenharmony_ci		SNDRV_CHMAP_RL,		/* back left */
26362306a36Sopenharmony_ci		SNDRV_CHMAP_RR,		/* back right */
26462306a36Sopenharmony_ci		SNDRV_CHMAP_FLC,	/* front left of center */
26562306a36Sopenharmony_ci		SNDRV_CHMAP_FRC,	/* front right of center */
26662306a36Sopenharmony_ci		SNDRV_CHMAP_RC,		/* back center */
26762306a36Sopenharmony_ci		SNDRV_CHMAP_SL,		/* side left */
26862306a36Sopenharmony_ci		SNDRV_CHMAP_SR,		/* side right */
26962306a36Sopenharmony_ci		SNDRV_CHMAP_TC,		/* top center */
27062306a36Sopenharmony_ci		SNDRV_CHMAP_TFL,	/* top front left */
27162306a36Sopenharmony_ci		SNDRV_CHMAP_TFC,	/* top front center */
27262306a36Sopenharmony_ci		SNDRV_CHMAP_TFR,	/* top front right */
27362306a36Sopenharmony_ci		SNDRV_CHMAP_TRL,	/* top back left */
27462306a36Sopenharmony_ci		SNDRV_CHMAP_TRC,	/* top back center */
27562306a36Sopenharmony_ci		SNDRV_CHMAP_TRR,	/* top back right */
27662306a36Sopenharmony_ci		SNDRV_CHMAP_TFLC,	/* top front left of center */
27762306a36Sopenharmony_ci		SNDRV_CHMAP_TFRC,	/* top front right of center */
27862306a36Sopenharmony_ci		SNDRV_CHMAP_LLFE,	/* left LFE */
27962306a36Sopenharmony_ci		SNDRV_CHMAP_RLFE,	/* right LFE */
28062306a36Sopenharmony_ci		SNDRV_CHMAP_TSL,	/* top side left */
28162306a36Sopenharmony_ci		SNDRV_CHMAP_TSR,	/* top side right */
28262306a36Sopenharmony_ci		SNDRV_CHMAP_BC,		/* bottom center */
28362306a36Sopenharmony_ci		SNDRV_CHMAP_RLC,	/* back left of center */
28462306a36Sopenharmony_ci		SNDRV_CHMAP_RRC,	/* back right of center */
28562306a36Sopenharmony_ci		0 /* terminator */
28662306a36Sopenharmony_ci	};
28762306a36Sopenharmony_ci	struct snd_pcm_chmap_elem *chmap;
28862306a36Sopenharmony_ci	const unsigned int *maps;
28962306a36Sopenharmony_ci	int c;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	if (channels > ARRAY_SIZE(chmap->map))
29262306a36Sopenharmony_ci		return NULL;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
29562306a36Sopenharmony_ci	if (!chmap)
29662306a36Sopenharmony_ci		return NULL;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps;
29962306a36Sopenharmony_ci	chmap->channels = channels;
30062306a36Sopenharmony_ci	c = 0;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	if (bits) {
30362306a36Sopenharmony_ci		for (; bits && *maps; maps++, bits >>= 1) {
30462306a36Sopenharmony_ci			if (bits & 1)
30562306a36Sopenharmony_ci				chmap->map[c++] = *maps;
30662306a36Sopenharmony_ci			if (c == chmap->channels)
30762306a36Sopenharmony_ci				break;
30862306a36Sopenharmony_ci		}
30962306a36Sopenharmony_ci	} else {
31062306a36Sopenharmony_ci		/* If we're missing wChannelConfig, then guess something
31162306a36Sopenharmony_ci		    to make sure the channel map is not skipped entirely */
31262306a36Sopenharmony_ci		if (channels == 1)
31362306a36Sopenharmony_ci			chmap->map[c++] = SNDRV_CHMAP_MONO;
31462306a36Sopenharmony_ci		else
31562306a36Sopenharmony_ci			for (; c < channels && *maps; maps++)
31662306a36Sopenharmony_ci				chmap->map[c++] = *maps;
31762306a36Sopenharmony_ci	}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	for (; c < channels; c++)
32062306a36Sopenharmony_ci		chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	return chmap;
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci/* UAC3 device stores channels information in Cluster Descriptors */
32662306a36Sopenharmony_cistatic struct
32762306a36Sopenharmony_cisnd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor
32862306a36Sopenharmony_ci								*cluster)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	unsigned int channels = cluster->bNrChannels;
33162306a36Sopenharmony_ci	struct snd_pcm_chmap_elem *chmap;
33262306a36Sopenharmony_ci	void *p = cluster;
33362306a36Sopenharmony_ci	int len, c;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	if (channels > ARRAY_SIZE(chmap->map))
33662306a36Sopenharmony_ci		return NULL;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
33962306a36Sopenharmony_ci	if (!chmap)
34062306a36Sopenharmony_ci		return NULL;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	len = le16_to_cpu(cluster->wLength);
34362306a36Sopenharmony_ci	c = 0;
34462306a36Sopenharmony_ci	p += sizeof(struct uac3_cluster_header_descriptor);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	while (((p - (void *)cluster) < len) && (c < channels)) {
34762306a36Sopenharmony_ci		struct uac3_cluster_segment_descriptor *cs_desc = p;
34862306a36Sopenharmony_ci		u16 cs_len;
34962306a36Sopenharmony_ci		u8 cs_type;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci		cs_len = le16_to_cpu(cs_desc->wLength);
35262306a36Sopenharmony_ci		cs_type = cs_desc->bSegmentType;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		if (cs_type == UAC3_CHANNEL_INFORMATION) {
35562306a36Sopenharmony_ci			struct uac3_cluster_information_segment_descriptor *is = p;
35662306a36Sopenharmony_ci			unsigned char map;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci			/*
35962306a36Sopenharmony_ci			 * TODO: this conversion is not complete, update it
36062306a36Sopenharmony_ci			 * after adding UAC3 values to asound.h
36162306a36Sopenharmony_ci			 */
36262306a36Sopenharmony_ci			switch (is->bChRelationship) {
36362306a36Sopenharmony_ci			case UAC3_CH_MONO:
36462306a36Sopenharmony_ci				map = SNDRV_CHMAP_MONO;
36562306a36Sopenharmony_ci				break;
36662306a36Sopenharmony_ci			case UAC3_CH_LEFT:
36762306a36Sopenharmony_ci			case UAC3_CH_FRONT_LEFT:
36862306a36Sopenharmony_ci			case UAC3_CH_HEADPHONE_LEFT:
36962306a36Sopenharmony_ci				map = SNDRV_CHMAP_FL;
37062306a36Sopenharmony_ci				break;
37162306a36Sopenharmony_ci			case UAC3_CH_RIGHT:
37262306a36Sopenharmony_ci			case UAC3_CH_FRONT_RIGHT:
37362306a36Sopenharmony_ci			case UAC3_CH_HEADPHONE_RIGHT:
37462306a36Sopenharmony_ci				map = SNDRV_CHMAP_FR;
37562306a36Sopenharmony_ci				break;
37662306a36Sopenharmony_ci			case UAC3_CH_FRONT_CENTER:
37762306a36Sopenharmony_ci				map = SNDRV_CHMAP_FC;
37862306a36Sopenharmony_ci				break;
37962306a36Sopenharmony_ci			case UAC3_CH_FRONT_LEFT_OF_CENTER:
38062306a36Sopenharmony_ci				map = SNDRV_CHMAP_FLC;
38162306a36Sopenharmony_ci				break;
38262306a36Sopenharmony_ci			case UAC3_CH_FRONT_RIGHT_OF_CENTER:
38362306a36Sopenharmony_ci				map = SNDRV_CHMAP_FRC;
38462306a36Sopenharmony_ci				break;
38562306a36Sopenharmony_ci			case UAC3_CH_SIDE_LEFT:
38662306a36Sopenharmony_ci				map = SNDRV_CHMAP_SL;
38762306a36Sopenharmony_ci				break;
38862306a36Sopenharmony_ci			case UAC3_CH_SIDE_RIGHT:
38962306a36Sopenharmony_ci				map = SNDRV_CHMAP_SR;
39062306a36Sopenharmony_ci				break;
39162306a36Sopenharmony_ci			case UAC3_CH_BACK_LEFT:
39262306a36Sopenharmony_ci				map = SNDRV_CHMAP_RL;
39362306a36Sopenharmony_ci				break;
39462306a36Sopenharmony_ci			case UAC3_CH_BACK_RIGHT:
39562306a36Sopenharmony_ci				map = SNDRV_CHMAP_RR;
39662306a36Sopenharmony_ci				break;
39762306a36Sopenharmony_ci			case UAC3_CH_BACK_CENTER:
39862306a36Sopenharmony_ci				map = SNDRV_CHMAP_RC;
39962306a36Sopenharmony_ci				break;
40062306a36Sopenharmony_ci			case UAC3_CH_BACK_LEFT_OF_CENTER:
40162306a36Sopenharmony_ci				map = SNDRV_CHMAP_RLC;
40262306a36Sopenharmony_ci				break;
40362306a36Sopenharmony_ci			case UAC3_CH_BACK_RIGHT_OF_CENTER:
40462306a36Sopenharmony_ci				map = SNDRV_CHMAP_RRC;
40562306a36Sopenharmony_ci				break;
40662306a36Sopenharmony_ci			case UAC3_CH_TOP_CENTER:
40762306a36Sopenharmony_ci				map = SNDRV_CHMAP_TC;
40862306a36Sopenharmony_ci				break;
40962306a36Sopenharmony_ci			case UAC3_CH_TOP_FRONT_LEFT:
41062306a36Sopenharmony_ci				map = SNDRV_CHMAP_TFL;
41162306a36Sopenharmony_ci				break;
41262306a36Sopenharmony_ci			case UAC3_CH_TOP_FRONT_RIGHT:
41362306a36Sopenharmony_ci				map = SNDRV_CHMAP_TFR;
41462306a36Sopenharmony_ci				break;
41562306a36Sopenharmony_ci			case UAC3_CH_TOP_FRONT_CENTER:
41662306a36Sopenharmony_ci				map = SNDRV_CHMAP_TFC;
41762306a36Sopenharmony_ci				break;
41862306a36Sopenharmony_ci			case UAC3_CH_TOP_FRONT_LOC:
41962306a36Sopenharmony_ci				map = SNDRV_CHMAP_TFLC;
42062306a36Sopenharmony_ci				break;
42162306a36Sopenharmony_ci			case UAC3_CH_TOP_FRONT_ROC:
42262306a36Sopenharmony_ci				map = SNDRV_CHMAP_TFRC;
42362306a36Sopenharmony_ci				break;
42462306a36Sopenharmony_ci			case UAC3_CH_TOP_SIDE_LEFT:
42562306a36Sopenharmony_ci				map = SNDRV_CHMAP_TSL;
42662306a36Sopenharmony_ci				break;
42762306a36Sopenharmony_ci			case UAC3_CH_TOP_SIDE_RIGHT:
42862306a36Sopenharmony_ci				map = SNDRV_CHMAP_TSR;
42962306a36Sopenharmony_ci				break;
43062306a36Sopenharmony_ci			case UAC3_CH_TOP_BACK_LEFT:
43162306a36Sopenharmony_ci				map = SNDRV_CHMAP_TRL;
43262306a36Sopenharmony_ci				break;
43362306a36Sopenharmony_ci			case UAC3_CH_TOP_BACK_RIGHT:
43462306a36Sopenharmony_ci				map = SNDRV_CHMAP_TRR;
43562306a36Sopenharmony_ci				break;
43662306a36Sopenharmony_ci			case UAC3_CH_TOP_BACK_CENTER:
43762306a36Sopenharmony_ci				map = SNDRV_CHMAP_TRC;
43862306a36Sopenharmony_ci				break;
43962306a36Sopenharmony_ci			case UAC3_CH_BOTTOM_CENTER:
44062306a36Sopenharmony_ci				map = SNDRV_CHMAP_BC;
44162306a36Sopenharmony_ci				break;
44262306a36Sopenharmony_ci			case UAC3_CH_LOW_FREQUENCY_EFFECTS:
44362306a36Sopenharmony_ci				map = SNDRV_CHMAP_LFE;
44462306a36Sopenharmony_ci				break;
44562306a36Sopenharmony_ci			case UAC3_CH_LFE_LEFT:
44662306a36Sopenharmony_ci				map = SNDRV_CHMAP_LLFE;
44762306a36Sopenharmony_ci				break;
44862306a36Sopenharmony_ci			case UAC3_CH_LFE_RIGHT:
44962306a36Sopenharmony_ci				map = SNDRV_CHMAP_RLFE;
45062306a36Sopenharmony_ci				break;
45162306a36Sopenharmony_ci			case UAC3_CH_RELATIONSHIP_UNDEFINED:
45262306a36Sopenharmony_ci			default:
45362306a36Sopenharmony_ci				map = SNDRV_CHMAP_UNKNOWN;
45462306a36Sopenharmony_ci				break;
45562306a36Sopenharmony_ci			}
45662306a36Sopenharmony_ci			chmap->map[c++] = map;
45762306a36Sopenharmony_ci		}
45862306a36Sopenharmony_ci		p += cs_len;
45962306a36Sopenharmony_ci	}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	if (channels < c)
46262306a36Sopenharmony_ci		pr_err("%s: channel number mismatch\n", __func__);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	chmap->channels = channels;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	for (; c < channels; c++)
46762306a36Sopenharmony_ci		chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	return chmap;
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci/*
47362306a36Sopenharmony_ci * add this endpoint to the chip instance.
47462306a36Sopenharmony_ci * if a stream with the same endpoint already exists, append to it.
47562306a36Sopenharmony_ci * if not, create a new pcm stream. note, fp is added to the substream
47662306a36Sopenharmony_ci * fmt_list and will be freed on the chip instance release. do not free
47762306a36Sopenharmony_ci * fp or do remove it from the substream fmt_list to avoid double-free.
47862306a36Sopenharmony_ci */
47962306a36Sopenharmony_cistatic int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
48062306a36Sopenharmony_ci				      int stream,
48162306a36Sopenharmony_ci				      struct audioformat *fp,
48262306a36Sopenharmony_ci				      struct snd_usb_power_domain *pd)
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	struct snd_usb_stream *as;
48662306a36Sopenharmony_ci	struct snd_usb_substream *subs;
48762306a36Sopenharmony_ci	struct snd_pcm *pcm;
48862306a36Sopenharmony_ci	int err;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	list_for_each_entry(as, &chip->pcm_list, list) {
49162306a36Sopenharmony_ci		if (as->fmt_type != fp->fmt_type)
49262306a36Sopenharmony_ci			continue;
49362306a36Sopenharmony_ci		subs = &as->substream[stream];
49462306a36Sopenharmony_ci		if (subs->ep_num == fp->endpoint) {
49562306a36Sopenharmony_ci			list_add_tail(&fp->list, &subs->fmt_list);
49662306a36Sopenharmony_ci			subs->num_formats++;
49762306a36Sopenharmony_ci			subs->formats |= fp->formats;
49862306a36Sopenharmony_ci			return 0;
49962306a36Sopenharmony_ci		}
50062306a36Sopenharmony_ci	}
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	if (chip->card->registered)
50362306a36Sopenharmony_ci		chip->need_delayed_register = true;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	/* look for an empty stream */
50662306a36Sopenharmony_ci	list_for_each_entry(as, &chip->pcm_list, list) {
50762306a36Sopenharmony_ci		if (as->fmt_type != fp->fmt_type)
50862306a36Sopenharmony_ci			continue;
50962306a36Sopenharmony_ci		subs = &as->substream[stream];
51062306a36Sopenharmony_ci		if (subs->ep_num)
51162306a36Sopenharmony_ci			continue;
51262306a36Sopenharmony_ci		err = snd_pcm_new_stream(as->pcm, stream, 1);
51362306a36Sopenharmony_ci		if (err < 0)
51462306a36Sopenharmony_ci			return err;
51562306a36Sopenharmony_ci		snd_usb_init_substream(as, stream, fp, pd);
51662306a36Sopenharmony_ci		return add_chmap(as->pcm, stream, subs);
51762306a36Sopenharmony_ci	}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	/* create a new pcm */
52062306a36Sopenharmony_ci	as = kzalloc(sizeof(*as), GFP_KERNEL);
52162306a36Sopenharmony_ci	if (!as)
52262306a36Sopenharmony_ci		return -ENOMEM;
52362306a36Sopenharmony_ci	as->pcm_index = chip->pcm_devs;
52462306a36Sopenharmony_ci	as->chip = chip;
52562306a36Sopenharmony_ci	as->fmt_type = fp->fmt_type;
52662306a36Sopenharmony_ci	err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
52762306a36Sopenharmony_ci			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
52862306a36Sopenharmony_ci			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
52962306a36Sopenharmony_ci			  &pcm);
53062306a36Sopenharmony_ci	if (err < 0) {
53162306a36Sopenharmony_ci		kfree(as);
53262306a36Sopenharmony_ci		return err;
53362306a36Sopenharmony_ci	}
53462306a36Sopenharmony_ci	as->pcm = pcm;
53562306a36Sopenharmony_ci	pcm->private_data = as;
53662306a36Sopenharmony_ci	pcm->private_free = snd_usb_audio_pcm_free;
53762306a36Sopenharmony_ci	pcm->info_flags = 0;
53862306a36Sopenharmony_ci	if (chip->pcm_devs > 0)
53962306a36Sopenharmony_ci		sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
54062306a36Sopenharmony_ci	else
54162306a36Sopenharmony_ci		strcpy(pcm->name, "USB Audio");
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	snd_usb_init_substream(as, stream, fp, pd);
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	/*
54662306a36Sopenharmony_ci	 * Keep using head insertion for M-Audio Audiophile USB (tm) which has a
54762306a36Sopenharmony_ci	 * fix to swap capture stream order in conf/cards/USB-audio.conf
54862306a36Sopenharmony_ci	 */
54962306a36Sopenharmony_ci	if (chip->usb_id == USB_ID(0x0763, 0x2003))
55062306a36Sopenharmony_ci		list_add(&as->list, &chip->pcm_list);
55162306a36Sopenharmony_ci	else
55262306a36Sopenharmony_ci		list_add_tail(&as->list, &chip->pcm_list);
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	chip->pcm_devs++;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	snd_usb_proc_pcm_format_add(as);
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	return add_chmap(pcm, stream, &as->substream[stream]);
55962306a36Sopenharmony_ci}
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ciint snd_usb_add_audio_stream(struct snd_usb_audio *chip,
56262306a36Sopenharmony_ci			     int stream,
56362306a36Sopenharmony_ci			     struct audioformat *fp)
56462306a36Sopenharmony_ci{
56562306a36Sopenharmony_ci	return __snd_usb_add_audio_stream(chip, stream, fp, NULL);
56662306a36Sopenharmony_ci}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_cistatic int snd_usb_add_audio_stream_v3(struct snd_usb_audio *chip,
56962306a36Sopenharmony_ci				       int stream,
57062306a36Sopenharmony_ci				       struct audioformat *fp,
57162306a36Sopenharmony_ci				       struct snd_usb_power_domain *pd)
57262306a36Sopenharmony_ci{
57362306a36Sopenharmony_ci	return __snd_usb_add_audio_stream(chip, stream, fp, pd);
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_cistatic int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
57762306a36Sopenharmony_ci					 struct usb_host_interface *alts,
57862306a36Sopenharmony_ci					 int protocol, int iface_no)
57962306a36Sopenharmony_ci{
58062306a36Sopenharmony_ci	/* parsed with a v1 header here. that's ok as we only look at the
58162306a36Sopenharmony_ci	 * header first which is the same for both versions */
58262306a36Sopenharmony_ci	struct uac_iso_endpoint_descriptor *csep;
58362306a36Sopenharmony_ci	struct usb_interface_descriptor *altsd = get_iface_desc(alts);
58462306a36Sopenharmony_ci	int attributes = 0;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	/* Creamware Noah has this descriptor after the 2nd endpoint */
58962306a36Sopenharmony_ci	if (!csep && altsd->bNumEndpoints >= 2)
59062306a36Sopenharmony_ci		csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	/*
59362306a36Sopenharmony_ci	 * If we can't locate the USB_DT_CS_ENDPOINT descriptor in the extra
59462306a36Sopenharmony_ci	 * bytes after the first endpoint, go search the entire interface.
59562306a36Sopenharmony_ci	 * Some devices have it directly *before* the standard endpoint.
59662306a36Sopenharmony_ci	 */
59762306a36Sopenharmony_ci	if (!csep)
59862306a36Sopenharmony_ci		csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (!csep || csep->bLength < 7 ||
60162306a36Sopenharmony_ci	    csep->bDescriptorSubtype != UAC_EP_GENERAL)
60262306a36Sopenharmony_ci		goto error;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	if (protocol == UAC_VERSION_1) {
60562306a36Sopenharmony_ci		attributes = csep->bmAttributes;
60662306a36Sopenharmony_ci	} else if (protocol == UAC_VERSION_2) {
60762306a36Sopenharmony_ci		struct uac2_iso_endpoint_descriptor *csep2 =
60862306a36Sopenharmony_ci			(struct uac2_iso_endpoint_descriptor *) csep;
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci		if (csep2->bLength < sizeof(*csep2))
61162306a36Sopenharmony_ci			goto error;
61262306a36Sopenharmony_ci		attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci		/* emulate the endpoint attributes of a v1 device */
61562306a36Sopenharmony_ci		if (csep2->bmControls & UAC2_CONTROL_PITCH)
61662306a36Sopenharmony_ci			attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
61762306a36Sopenharmony_ci	} else { /* UAC_VERSION_3 */
61862306a36Sopenharmony_ci		struct uac3_iso_endpoint_descriptor *csep3 =
61962306a36Sopenharmony_ci			(struct uac3_iso_endpoint_descriptor *) csep;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci		if (csep3->bLength < sizeof(*csep3))
62262306a36Sopenharmony_ci			goto error;
62362306a36Sopenharmony_ci		/* emulate the endpoint attributes of a v1 device */
62462306a36Sopenharmony_ci		if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH)
62562306a36Sopenharmony_ci			attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
62662306a36Sopenharmony_ci	}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	return attributes;
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci error:
63162306a36Sopenharmony_ci	usb_audio_warn(chip,
63262306a36Sopenharmony_ci		       "%u:%d : no or invalid class specific endpoint descriptor\n",
63362306a36Sopenharmony_ci		       iface_no, altsd->bAlternateSetting);
63462306a36Sopenharmony_ci	return 0;
63562306a36Sopenharmony_ci}
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci/* find an input terminal descriptor (either UAC1 or UAC2) with the given
63862306a36Sopenharmony_ci * terminal id
63962306a36Sopenharmony_ci */
64062306a36Sopenharmony_cistatic void *
64162306a36Sopenharmony_cisnd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
64262306a36Sopenharmony_ci				       int terminal_id, int protocol)
64362306a36Sopenharmony_ci{
64462306a36Sopenharmony_ci	struct uac2_input_terminal_descriptor *term = NULL;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
64762306a36Sopenharmony_ci					       ctrl_iface->extralen,
64862306a36Sopenharmony_ci					       term, UAC_INPUT_TERMINAL))) {
64962306a36Sopenharmony_ci		if (!snd_usb_validate_audio_desc(term, protocol))
65062306a36Sopenharmony_ci			continue;
65162306a36Sopenharmony_ci		if (term->bTerminalID == terminal_id)
65262306a36Sopenharmony_ci			return term;
65362306a36Sopenharmony_ci	}
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	return NULL;
65662306a36Sopenharmony_ci}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_cistatic void *
65962306a36Sopenharmony_cisnd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
66062306a36Sopenharmony_ci					int terminal_id, int protocol)
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	/* OK to use with both UAC2 and UAC3 */
66362306a36Sopenharmony_ci	struct uac2_output_terminal_descriptor *term = NULL;
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
66662306a36Sopenharmony_ci					       ctrl_iface->extralen,
66762306a36Sopenharmony_ci					       term, UAC_OUTPUT_TERMINAL))) {
66862306a36Sopenharmony_ci		if (!snd_usb_validate_audio_desc(term, protocol))
66962306a36Sopenharmony_ci			continue;
67062306a36Sopenharmony_ci		if (term->bTerminalID == terminal_id)
67162306a36Sopenharmony_ci			return term;
67262306a36Sopenharmony_ci	}
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	return NULL;
67562306a36Sopenharmony_ci}
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_cistatic struct audioformat *
67862306a36Sopenharmony_ciaudio_format_alloc_init(struct snd_usb_audio *chip,
67962306a36Sopenharmony_ci		       struct usb_host_interface *alts,
68062306a36Sopenharmony_ci		       int protocol, int iface_no, int altset_idx,
68162306a36Sopenharmony_ci		       int altno, int num_channels, int clock)
68262306a36Sopenharmony_ci{
68362306a36Sopenharmony_ci	struct audioformat *fp;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	fp = kzalloc(sizeof(*fp), GFP_KERNEL);
68662306a36Sopenharmony_ci	if (!fp)
68762306a36Sopenharmony_ci		return NULL;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	fp->iface = iface_no;
69062306a36Sopenharmony_ci	fp->altsetting = altno;
69162306a36Sopenharmony_ci	fp->altset_idx = altset_idx;
69262306a36Sopenharmony_ci	fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
69362306a36Sopenharmony_ci	fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
69462306a36Sopenharmony_ci	fp->datainterval = snd_usb_parse_datainterval(chip, alts);
69562306a36Sopenharmony_ci	fp->protocol = protocol;
69662306a36Sopenharmony_ci	fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
69762306a36Sopenharmony_ci	fp->channels = num_channels;
69862306a36Sopenharmony_ci	if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH)
69962306a36Sopenharmony_ci		fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
70062306a36Sopenharmony_ci				* (fp->maxpacksize & 0x7ff);
70162306a36Sopenharmony_ci	fp->clock = clock;
70262306a36Sopenharmony_ci	INIT_LIST_HEAD(&fp->list);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	return fp;
70562306a36Sopenharmony_ci}
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_cistatic struct audioformat *
70862306a36Sopenharmony_cisnd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
70962306a36Sopenharmony_ci			      struct usb_host_interface *alts,
71062306a36Sopenharmony_ci			      int protocol, int iface_no, int altset_idx,
71162306a36Sopenharmony_ci			      int altno, int stream, int bm_quirk)
71262306a36Sopenharmony_ci{
71362306a36Sopenharmony_ci	struct usb_device *dev = chip->dev;
71462306a36Sopenharmony_ci	struct uac_format_type_i_continuous_descriptor *fmt;
71562306a36Sopenharmony_ci	unsigned int num_channels = 0, chconfig = 0;
71662306a36Sopenharmony_ci	struct audioformat *fp;
71762306a36Sopenharmony_ci	int clock = 0;
71862306a36Sopenharmony_ci	u64 format;
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	/* get audio formats */
72162306a36Sopenharmony_ci	if (protocol == UAC_VERSION_1) {
72262306a36Sopenharmony_ci		struct uac1_as_header_descriptor *as =
72362306a36Sopenharmony_ci			snd_usb_find_csint_desc(alts->extra, alts->extralen,
72462306a36Sopenharmony_ci						NULL, UAC_AS_GENERAL);
72562306a36Sopenharmony_ci		struct uac_input_terminal_descriptor *iterm;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci		if (!as) {
72862306a36Sopenharmony_ci			dev_err(&dev->dev,
72962306a36Sopenharmony_ci				"%u:%d : UAC_AS_GENERAL descriptor not found\n",
73062306a36Sopenharmony_ci				iface_no, altno);
73162306a36Sopenharmony_ci			return NULL;
73262306a36Sopenharmony_ci		}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci		if (as->bLength < sizeof(*as)) {
73562306a36Sopenharmony_ci			dev_err(&dev->dev,
73662306a36Sopenharmony_ci				"%u:%d : invalid UAC_AS_GENERAL desc\n",
73762306a36Sopenharmony_ci				iface_no, altno);
73862306a36Sopenharmony_ci			return NULL;
73962306a36Sopenharmony_ci		}
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci		format = le16_to_cpu(as->wFormatTag); /* remember the format value */
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci		iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
74462306a36Sopenharmony_ci							       as->bTerminalLink,
74562306a36Sopenharmony_ci							       protocol);
74662306a36Sopenharmony_ci		if (iterm) {
74762306a36Sopenharmony_ci			num_channels = iterm->bNrChannels;
74862306a36Sopenharmony_ci			chconfig = le16_to_cpu(iterm->wChannelConfig);
74962306a36Sopenharmony_ci		}
75062306a36Sopenharmony_ci	} else { /* UAC_VERSION_2 */
75162306a36Sopenharmony_ci		struct uac2_input_terminal_descriptor *input_term;
75262306a36Sopenharmony_ci		struct uac2_output_terminal_descriptor *output_term;
75362306a36Sopenharmony_ci		struct uac2_as_header_descriptor *as =
75462306a36Sopenharmony_ci			snd_usb_find_csint_desc(alts->extra, alts->extralen,
75562306a36Sopenharmony_ci						NULL, UAC_AS_GENERAL);
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci		if (!as) {
75862306a36Sopenharmony_ci			dev_err(&dev->dev,
75962306a36Sopenharmony_ci				"%u:%d : UAC_AS_GENERAL descriptor not found\n",
76062306a36Sopenharmony_ci				iface_no, altno);
76162306a36Sopenharmony_ci			return NULL;
76262306a36Sopenharmony_ci		}
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci		if (as->bLength < sizeof(*as)) {
76562306a36Sopenharmony_ci			dev_err(&dev->dev,
76662306a36Sopenharmony_ci				"%u:%d : invalid UAC_AS_GENERAL desc\n",
76762306a36Sopenharmony_ci				iface_no, altno);
76862306a36Sopenharmony_ci			return NULL;
76962306a36Sopenharmony_ci		}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci		num_channels = as->bNrChannels;
77262306a36Sopenharmony_ci		format = le32_to_cpu(as->bmFormats);
77362306a36Sopenharmony_ci		chconfig = le32_to_cpu(as->bmChannelConfig);
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci		/*
77662306a36Sopenharmony_ci		 * lookup the terminal associated to this interface
77762306a36Sopenharmony_ci		 * to extract the clock
77862306a36Sopenharmony_ci		 */
77962306a36Sopenharmony_ci		input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
78062306a36Sopenharmony_ci								    as->bTerminalLink,
78162306a36Sopenharmony_ci								    protocol);
78262306a36Sopenharmony_ci		if (input_term) {
78362306a36Sopenharmony_ci			clock = input_term->bCSourceID;
78462306a36Sopenharmony_ci			if (!chconfig && (num_channels == input_term->bNrChannels))
78562306a36Sopenharmony_ci				chconfig = le32_to_cpu(input_term->bmChannelConfig);
78662306a36Sopenharmony_ci			goto found_clock;
78762306a36Sopenharmony_ci		}
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci		output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
79062306a36Sopenharmony_ci								      as->bTerminalLink,
79162306a36Sopenharmony_ci								      protocol);
79262306a36Sopenharmony_ci		if (output_term) {
79362306a36Sopenharmony_ci			clock = output_term->bCSourceID;
79462306a36Sopenharmony_ci			goto found_clock;
79562306a36Sopenharmony_ci		}
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci		dev_err(&dev->dev,
79862306a36Sopenharmony_ci			"%u:%d : bogus bTerminalLink %d\n",
79962306a36Sopenharmony_ci			iface_no, altno, as->bTerminalLink);
80062306a36Sopenharmony_ci		return NULL;
80162306a36Sopenharmony_ci	}
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_cifound_clock:
80462306a36Sopenharmony_ci	/* get format type */
80562306a36Sopenharmony_ci	fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen,
80662306a36Sopenharmony_ci				      NULL, UAC_FORMAT_TYPE);
80762306a36Sopenharmony_ci	if (!fmt) {
80862306a36Sopenharmony_ci		dev_err(&dev->dev,
80962306a36Sopenharmony_ci			"%u:%d : no UAC_FORMAT_TYPE desc\n",
81062306a36Sopenharmony_ci			iface_no, altno);
81162306a36Sopenharmony_ci		return NULL;
81262306a36Sopenharmony_ci	}
81362306a36Sopenharmony_ci	if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8))
81462306a36Sopenharmony_ci			|| ((protocol == UAC_VERSION_2) &&
81562306a36Sopenharmony_ci					(fmt->bLength < 6))) {
81662306a36Sopenharmony_ci		dev_err(&dev->dev,
81762306a36Sopenharmony_ci			"%u:%d : invalid UAC_FORMAT_TYPE desc\n",
81862306a36Sopenharmony_ci			iface_no, altno);
81962306a36Sopenharmony_ci		return NULL;
82062306a36Sopenharmony_ci	}
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	/*
82362306a36Sopenharmony_ci	 * Blue Microphones workaround: The last altsetting is
82462306a36Sopenharmony_ci	 * identical with the previous one, except for a larger
82562306a36Sopenharmony_ci	 * packet size, but is actually a mislabeled two-channel
82662306a36Sopenharmony_ci	 * setting; ignore it.
82762306a36Sopenharmony_ci	 *
82862306a36Sopenharmony_ci	 * Part 2: analyze quirk flag and format
82962306a36Sopenharmony_ci	 */
83062306a36Sopenharmony_ci	if (bm_quirk && fmt->bNrChannels == 1 && fmt->bSubframeSize == 2)
83162306a36Sopenharmony_ci		return NULL;
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	fp = audio_format_alloc_init(chip, alts, protocol, iface_no,
83462306a36Sopenharmony_ci				     altset_idx, altno, num_channels, clock);
83562306a36Sopenharmony_ci	if (!fp)
83662306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol,
83962306a36Sopenharmony_ci						       iface_no);
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	/* some quirks for attributes here */
84262306a36Sopenharmony_ci	snd_usb_audioformat_attributes_quirk(chip, fp, stream);
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	/* ok, let's parse further... */
84562306a36Sopenharmony_ci	if (snd_usb_parse_audio_format(chip, fp, format,
84662306a36Sopenharmony_ci					fmt, stream) < 0) {
84762306a36Sopenharmony_ci		audioformat_free(fp);
84862306a36Sopenharmony_ci		return NULL;
84962306a36Sopenharmony_ci	}
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	/* Create chmap */
85262306a36Sopenharmony_ci	if (fp->channels != num_channels)
85362306a36Sopenharmony_ci		chconfig = 0;
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	fp->chmap = convert_chmap(fp->channels, chconfig, protocol);
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	return fp;
85862306a36Sopenharmony_ci}
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_cistatic struct audioformat *
86162306a36Sopenharmony_cisnd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
86262306a36Sopenharmony_ci			     struct usb_host_interface *alts,
86362306a36Sopenharmony_ci			     struct snd_usb_power_domain **pd_out,
86462306a36Sopenharmony_ci			     int iface_no, int altset_idx,
86562306a36Sopenharmony_ci			     int altno, int stream)
86662306a36Sopenharmony_ci{
86762306a36Sopenharmony_ci	struct usb_device *dev = chip->dev;
86862306a36Sopenharmony_ci	struct uac3_input_terminal_descriptor *input_term;
86962306a36Sopenharmony_ci	struct uac3_output_terminal_descriptor *output_term;
87062306a36Sopenharmony_ci	struct uac3_cluster_header_descriptor *cluster;
87162306a36Sopenharmony_ci	struct uac3_as_header_descriptor *as = NULL;
87262306a36Sopenharmony_ci	struct uac3_hc_descriptor_header hc_header;
87362306a36Sopenharmony_ci	struct snd_pcm_chmap_elem *chmap;
87462306a36Sopenharmony_ci	struct snd_usb_power_domain *pd;
87562306a36Sopenharmony_ci	unsigned char badd_profile;
87662306a36Sopenharmony_ci	u64 badd_formats = 0;
87762306a36Sopenharmony_ci	unsigned int num_channels;
87862306a36Sopenharmony_ci	struct audioformat *fp;
87962306a36Sopenharmony_ci	u16 cluster_id, wLength;
88062306a36Sopenharmony_ci	int clock = 0;
88162306a36Sopenharmony_ci	int err;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	badd_profile = chip->badd_profile;
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
88662306a36Sopenharmony_ci		unsigned int maxpacksize =
88762306a36Sopenharmony_ci			le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci		switch (maxpacksize) {
89062306a36Sopenharmony_ci		default:
89162306a36Sopenharmony_ci			dev_err(&dev->dev,
89262306a36Sopenharmony_ci				"%u:%d : incorrect wMaxPacketSize for BADD profile\n",
89362306a36Sopenharmony_ci				iface_no, altno);
89462306a36Sopenharmony_ci			return NULL;
89562306a36Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16:
89662306a36Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16:
89762306a36Sopenharmony_ci			badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
89862306a36Sopenharmony_ci			num_channels = 1;
89962306a36Sopenharmony_ci			break;
90062306a36Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24:
90162306a36Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24:
90262306a36Sopenharmony_ci			badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
90362306a36Sopenharmony_ci			num_channels = 1;
90462306a36Sopenharmony_ci			break;
90562306a36Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16:
90662306a36Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16:
90762306a36Sopenharmony_ci			badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
90862306a36Sopenharmony_ci			num_channels = 2;
90962306a36Sopenharmony_ci			break;
91062306a36Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24:
91162306a36Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24:
91262306a36Sopenharmony_ci			badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
91362306a36Sopenharmony_ci			num_channels = 2;
91462306a36Sopenharmony_ci			break;
91562306a36Sopenharmony_ci		}
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci		chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
91862306a36Sopenharmony_ci		if (!chmap)
91962306a36Sopenharmony_ci			return ERR_PTR(-ENOMEM);
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci		if (num_channels == 1) {
92262306a36Sopenharmony_ci			chmap->map[0] = SNDRV_CHMAP_MONO;
92362306a36Sopenharmony_ci		} else {
92462306a36Sopenharmony_ci			chmap->map[0] = SNDRV_CHMAP_FL;
92562306a36Sopenharmony_ci			chmap->map[1] = SNDRV_CHMAP_FR;
92662306a36Sopenharmony_ci		}
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci		chmap->channels = num_channels;
92962306a36Sopenharmony_ci		clock = UAC3_BADD_CS_ID9;
93062306a36Sopenharmony_ci		goto found_clock;
93162306a36Sopenharmony_ci	}
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	as = snd_usb_find_csint_desc(alts->extra, alts->extralen,
93462306a36Sopenharmony_ci				     NULL, UAC_AS_GENERAL);
93562306a36Sopenharmony_ci	if (!as) {
93662306a36Sopenharmony_ci		dev_err(&dev->dev,
93762306a36Sopenharmony_ci			"%u:%d : UAC_AS_GENERAL descriptor not found\n",
93862306a36Sopenharmony_ci			iface_no, altno);
93962306a36Sopenharmony_ci		return NULL;
94062306a36Sopenharmony_ci	}
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	if (as->bLength < sizeof(*as)) {
94362306a36Sopenharmony_ci		dev_err(&dev->dev,
94462306a36Sopenharmony_ci			"%u:%d : invalid UAC_AS_GENERAL desc\n",
94562306a36Sopenharmony_ci			iface_no, altno);
94662306a36Sopenharmony_ci		return NULL;
94762306a36Sopenharmony_ci	}
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	cluster_id = le16_to_cpu(as->wClusterDescrID);
95062306a36Sopenharmony_ci	if (!cluster_id) {
95162306a36Sopenharmony_ci		dev_err(&dev->dev,
95262306a36Sopenharmony_ci			"%u:%d : no cluster descriptor\n",
95362306a36Sopenharmony_ci			iface_no, altno);
95462306a36Sopenharmony_ci		return NULL;
95562306a36Sopenharmony_ci	}
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	/*
95862306a36Sopenharmony_ci	 * Get number of channels and channel map through
95962306a36Sopenharmony_ci	 * High Capability Cluster Descriptor
96062306a36Sopenharmony_ci	 *
96162306a36Sopenharmony_ci	 * First step: get High Capability header and
96262306a36Sopenharmony_ci	 * read size of Cluster Descriptor
96362306a36Sopenharmony_ci	 */
96462306a36Sopenharmony_ci	err = snd_usb_ctl_msg(chip->dev,
96562306a36Sopenharmony_ci			usb_rcvctrlpipe(chip->dev, 0),
96662306a36Sopenharmony_ci			UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
96762306a36Sopenharmony_ci			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
96862306a36Sopenharmony_ci			cluster_id,
96962306a36Sopenharmony_ci			snd_usb_ctrl_intf(chip),
97062306a36Sopenharmony_ci			&hc_header, sizeof(hc_header));
97162306a36Sopenharmony_ci	if (err < 0)
97262306a36Sopenharmony_ci		return ERR_PTR(err);
97362306a36Sopenharmony_ci	else if (err != sizeof(hc_header)) {
97462306a36Sopenharmony_ci		dev_err(&dev->dev,
97562306a36Sopenharmony_ci			"%u:%d : can't get High Capability descriptor\n",
97662306a36Sopenharmony_ci			iface_no, altno);
97762306a36Sopenharmony_ci		return ERR_PTR(-EIO);
97862306a36Sopenharmony_ci	}
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	/*
98162306a36Sopenharmony_ci	 * Second step: allocate needed amount of memory
98262306a36Sopenharmony_ci	 * and request Cluster Descriptor
98362306a36Sopenharmony_ci	 */
98462306a36Sopenharmony_ci	wLength = le16_to_cpu(hc_header.wLength);
98562306a36Sopenharmony_ci	cluster = kzalloc(wLength, GFP_KERNEL);
98662306a36Sopenharmony_ci	if (!cluster)
98762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
98862306a36Sopenharmony_ci	err = snd_usb_ctl_msg(chip->dev,
98962306a36Sopenharmony_ci			usb_rcvctrlpipe(chip->dev, 0),
99062306a36Sopenharmony_ci			UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
99162306a36Sopenharmony_ci			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
99262306a36Sopenharmony_ci			cluster_id,
99362306a36Sopenharmony_ci			snd_usb_ctrl_intf(chip),
99462306a36Sopenharmony_ci			cluster, wLength);
99562306a36Sopenharmony_ci	if (err < 0) {
99662306a36Sopenharmony_ci		kfree(cluster);
99762306a36Sopenharmony_ci		return ERR_PTR(err);
99862306a36Sopenharmony_ci	} else if (err != wLength) {
99962306a36Sopenharmony_ci		dev_err(&dev->dev,
100062306a36Sopenharmony_ci			"%u:%d : can't get Cluster Descriptor\n",
100162306a36Sopenharmony_ci			iface_no, altno);
100262306a36Sopenharmony_ci		kfree(cluster);
100362306a36Sopenharmony_ci		return ERR_PTR(-EIO);
100462306a36Sopenharmony_ci	}
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	num_channels = cluster->bNrChannels;
100762306a36Sopenharmony_ci	chmap = convert_chmap_v3(cluster);
100862306a36Sopenharmony_ci	kfree(cluster);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	/*
101162306a36Sopenharmony_ci	 * lookup the terminal associated to this interface
101262306a36Sopenharmony_ci	 * to extract the clock
101362306a36Sopenharmony_ci	 */
101462306a36Sopenharmony_ci	input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
101562306a36Sopenharmony_ci							    as->bTerminalLink,
101662306a36Sopenharmony_ci							    UAC_VERSION_3);
101762306a36Sopenharmony_ci	if (input_term) {
101862306a36Sopenharmony_ci		clock = input_term->bCSourceID;
101962306a36Sopenharmony_ci		goto found_clock;
102062306a36Sopenharmony_ci	}
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
102362306a36Sopenharmony_ci							      as->bTerminalLink,
102462306a36Sopenharmony_ci							      UAC_VERSION_3);
102562306a36Sopenharmony_ci	if (output_term) {
102662306a36Sopenharmony_ci		clock = output_term->bCSourceID;
102762306a36Sopenharmony_ci		goto found_clock;
102862306a36Sopenharmony_ci	}
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	dev_err(&dev->dev, "%u:%d : bogus bTerminalLink %d\n",
103162306a36Sopenharmony_ci			iface_no, altno, as->bTerminalLink);
103262306a36Sopenharmony_ci	kfree(chmap);
103362306a36Sopenharmony_ci	return NULL;
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_cifound_clock:
103662306a36Sopenharmony_ci	fp = audio_format_alloc_init(chip, alts, UAC_VERSION_3, iface_no,
103762306a36Sopenharmony_ci				     altset_idx, altno, num_channels, clock);
103862306a36Sopenharmony_ci	if (!fp) {
103962306a36Sopenharmony_ci		kfree(chmap);
104062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
104162306a36Sopenharmony_ci	}
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	fp->chmap = chmap;
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
104662306a36Sopenharmony_ci		fp->attributes = 0; /* No attributes */
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci		fp->fmt_type = UAC_FORMAT_TYPE_I;
104962306a36Sopenharmony_ci		fp->formats = badd_formats;
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci		fp->nr_rates = 0;	/* SNDRV_PCM_RATE_CONTINUOUS */
105262306a36Sopenharmony_ci		fp->rate_min = UAC3_BADD_SAMPLING_RATE;
105362306a36Sopenharmony_ci		fp->rate_max = UAC3_BADD_SAMPLING_RATE;
105462306a36Sopenharmony_ci		fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
105762306a36Sopenharmony_ci		if (!pd) {
105862306a36Sopenharmony_ci			audioformat_free(fp);
105962306a36Sopenharmony_ci			return NULL;
106062306a36Sopenharmony_ci		}
106162306a36Sopenharmony_ci		pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
106262306a36Sopenharmony_ci					UAC3_BADD_PD_ID10 : UAC3_BADD_PD_ID11;
106362306a36Sopenharmony_ci		pd->pd_d1d0_rec = UAC3_BADD_PD_RECOVER_D1D0;
106462306a36Sopenharmony_ci		pd->pd_d2d0_rec = UAC3_BADD_PD_RECOVER_D2D0;
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	} else {
106762306a36Sopenharmony_ci		fp->attributes = parse_uac_endpoint_attributes(chip, alts,
106862306a36Sopenharmony_ci							       UAC_VERSION_3,
106962306a36Sopenharmony_ci							       iface_no);
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci		pd = snd_usb_find_power_domain(chip->ctrl_intf,
107262306a36Sopenharmony_ci					       as->bTerminalLink);
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci		/* ok, let's parse further... */
107562306a36Sopenharmony_ci		if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) {
107662306a36Sopenharmony_ci			kfree(pd);
107762306a36Sopenharmony_ci			audioformat_free(fp);
107862306a36Sopenharmony_ci			return NULL;
107962306a36Sopenharmony_ci		}
108062306a36Sopenharmony_ci	}
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	if (pd)
108362306a36Sopenharmony_ci		*pd_out = pd;
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	return fp;
108662306a36Sopenharmony_ci}
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_cistatic int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
108962306a36Sopenharmony_ci					   int iface_no,
109062306a36Sopenharmony_ci					   bool *has_non_pcm, bool non_pcm)
109162306a36Sopenharmony_ci{
109262306a36Sopenharmony_ci	struct usb_device *dev;
109362306a36Sopenharmony_ci	struct usb_interface *iface;
109462306a36Sopenharmony_ci	struct usb_host_interface *alts;
109562306a36Sopenharmony_ci	struct usb_interface_descriptor *altsd;
109662306a36Sopenharmony_ci	int i, altno, err, stream;
109762306a36Sopenharmony_ci	struct audioformat *fp = NULL;
109862306a36Sopenharmony_ci	struct snd_usb_power_domain *pd = NULL;
109962306a36Sopenharmony_ci	bool set_iface_first;
110062306a36Sopenharmony_ci	int num, protocol;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	dev = chip->dev;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	/* parse the interface's altsettings */
110562306a36Sopenharmony_ci	iface = usb_ifnum_to_if(dev, iface_no);
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	num = iface->num_altsetting;
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	/*
111062306a36Sopenharmony_ci	 * Dallas DS4201 workaround: It presents 5 altsettings, but the last
111162306a36Sopenharmony_ci	 * one misses syncpipe, and does not produce any sound.
111262306a36Sopenharmony_ci	 */
111362306a36Sopenharmony_ci	if (chip->usb_id == USB_ID(0x04fa, 0x4201) && num >= 4)
111462306a36Sopenharmony_ci		num = 4;
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
111762306a36Sopenharmony_ci		alts = &iface->altsetting[i];
111862306a36Sopenharmony_ci		altsd = get_iface_desc(alts);
111962306a36Sopenharmony_ci		protocol = altsd->bInterfaceProtocol;
112062306a36Sopenharmony_ci		/* skip invalid one */
112162306a36Sopenharmony_ci		if (((altsd->bInterfaceClass != USB_CLASS_AUDIO ||
112262306a36Sopenharmony_ci		      (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
112362306a36Sopenharmony_ci		       altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC)) &&
112462306a36Sopenharmony_ci		     altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
112562306a36Sopenharmony_ci		    altsd->bNumEndpoints < 1 ||
112662306a36Sopenharmony_ci		    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
112762306a36Sopenharmony_ci			continue;
112862306a36Sopenharmony_ci		/* must be isochronous */
112962306a36Sopenharmony_ci		if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
113062306a36Sopenharmony_ci		    USB_ENDPOINT_XFER_ISOC)
113162306a36Sopenharmony_ci			continue;
113262306a36Sopenharmony_ci		/* check direction */
113362306a36Sopenharmony_ci		stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
113462306a36Sopenharmony_ci			SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
113562306a36Sopenharmony_ci		altno = altsd->bAlternateSetting;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci		if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
113862306a36Sopenharmony_ci			continue;
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci		/*
114162306a36Sopenharmony_ci		 * Roland audio streaming interfaces are marked with protocols
114262306a36Sopenharmony_ci		 * 0/1/2, but are UAC 1 compatible.
114362306a36Sopenharmony_ci		 */
114462306a36Sopenharmony_ci		if (USB_ID_VENDOR(chip->usb_id) == 0x0582 &&
114562306a36Sopenharmony_ci		    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
114662306a36Sopenharmony_ci		    protocol <= 2)
114762306a36Sopenharmony_ci			protocol = UAC_VERSION_1;
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci		switch (protocol) {
115062306a36Sopenharmony_ci		default:
115162306a36Sopenharmony_ci			dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n",
115262306a36Sopenharmony_ci				iface_no, altno, protocol);
115362306a36Sopenharmony_ci			protocol = UAC_VERSION_1;
115462306a36Sopenharmony_ci			fallthrough;
115562306a36Sopenharmony_ci		case UAC_VERSION_1:
115662306a36Sopenharmony_ci		case UAC_VERSION_2: {
115762306a36Sopenharmony_ci			int bm_quirk = 0;
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci			/*
116062306a36Sopenharmony_ci			 * Blue Microphones workaround: The last altsetting is
116162306a36Sopenharmony_ci			 * identical with the previous one, except for a larger
116262306a36Sopenharmony_ci			 * packet size, but is actually a mislabeled two-channel
116362306a36Sopenharmony_ci			 * setting; ignore it.
116462306a36Sopenharmony_ci			 *
116562306a36Sopenharmony_ci			 * Part 1: prepare quirk flag
116662306a36Sopenharmony_ci			 */
116762306a36Sopenharmony_ci			if (altno == 2 && num == 3 &&
116862306a36Sopenharmony_ci			    fp && fp->altsetting == 1 && fp->channels == 1 &&
116962306a36Sopenharmony_ci			    fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
117062306a36Sopenharmony_ci			    protocol == UAC_VERSION_1 &&
117162306a36Sopenharmony_ci			    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
117262306a36Sopenharmony_ci							fp->maxpacksize * 2)
117362306a36Sopenharmony_ci				bm_quirk = 1;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci			fp = snd_usb_get_audioformat_uac12(chip, alts, protocol,
117662306a36Sopenharmony_ci							   iface_no, i, altno,
117762306a36Sopenharmony_ci							   stream, bm_quirk);
117862306a36Sopenharmony_ci			break;
117962306a36Sopenharmony_ci		}
118062306a36Sopenharmony_ci		case UAC_VERSION_3:
118162306a36Sopenharmony_ci			fp = snd_usb_get_audioformat_uac3(chip, alts, &pd,
118262306a36Sopenharmony_ci						iface_no, i, altno, stream);
118362306a36Sopenharmony_ci			break;
118462306a36Sopenharmony_ci		}
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci		if (!fp)
118762306a36Sopenharmony_ci			continue;
118862306a36Sopenharmony_ci		else if (IS_ERR(fp))
118962306a36Sopenharmony_ci			return PTR_ERR(fp);
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci		if (fp->fmt_type != UAC_FORMAT_TYPE_I)
119262306a36Sopenharmony_ci			*has_non_pcm = true;
119362306a36Sopenharmony_ci		if ((fp->fmt_type == UAC_FORMAT_TYPE_I) == non_pcm) {
119462306a36Sopenharmony_ci			audioformat_free(fp);
119562306a36Sopenharmony_ci			kfree(pd);
119662306a36Sopenharmony_ci			fp = NULL;
119762306a36Sopenharmony_ci			pd = NULL;
119862306a36Sopenharmony_ci			continue;
119962306a36Sopenharmony_ci		}
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci		snd_usb_audioformat_set_sync_ep(chip, fp);
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci		dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
120462306a36Sopenharmony_ci		if (protocol == UAC_VERSION_3)
120562306a36Sopenharmony_ci			err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd);
120662306a36Sopenharmony_ci		else
120762306a36Sopenharmony_ci			err = snd_usb_add_audio_stream(chip, stream, fp);
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci		if (err < 0) {
121062306a36Sopenharmony_ci			audioformat_free(fp);
121162306a36Sopenharmony_ci			kfree(pd);
121262306a36Sopenharmony_ci			return err;
121362306a36Sopenharmony_ci		}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci		/* add endpoints */
121662306a36Sopenharmony_ci		err = snd_usb_add_endpoint(chip, fp->endpoint,
121762306a36Sopenharmony_ci					   SND_USB_ENDPOINT_TYPE_DATA);
121862306a36Sopenharmony_ci		if (err < 0)
121962306a36Sopenharmony_ci			return err;
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci		if (fp->sync_ep) {
122262306a36Sopenharmony_ci			err = snd_usb_add_endpoint(chip, fp->sync_ep,
122362306a36Sopenharmony_ci						   fp->implicit_fb ?
122462306a36Sopenharmony_ci						   SND_USB_ENDPOINT_TYPE_DATA :
122562306a36Sopenharmony_ci						   SND_USB_ENDPOINT_TYPE_SYNC);
122662306a36Sopenharmony_ci			if (err < 0)
122762306a36Sopenharmony_ci				return err;
122862306a36Sopenharmony_ci		}
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci		set_iface_first = false;
123162306a36Sopenharmony_ci		if (protocol == UAC_VERSION_1 ||
123262306a36Sopenharmony_ci		    (chip->quirk_flags & QUIRK_FLAG_SET_IFACE_FIRST))
123362306a36Sopenharmony_ci			set_iface_first = true;
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci		/* try to set the interface... */
123662306a36Sopenharmony_ci		usb_set_interface(chip->dev, iface_no, 0);
123762306a36Sopenharmony_ci		if (set_iface_first)
123862306a36Sopenharmony_ci			usb_set_interface(chip->dev, iface_no, altno);
123962306a36Sopenharmony_ci		snd_usb_init_pitch(chip, fp);
124062306a36Sopenharmony_ci		snd_usb_init_sample_rate(chip, fp, fp->rate_max);
124162306a36Sopenharmony_ci		if (!set_iface_first)
124262306a36Sopenharmony_ci			usb_set_interface(chip->dev, iface_no, altno);
124362306a36Sopenharmony_ci	}
124462306a36Sopenharmony_ci	return 0;
124562306a36Sopenharmony_ci}
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ciint snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
124862306a36Sopenharmony_ci{
124962306a36Sopenharmony_ci	int err;
125062306a36Sopenharmony_ci	bool has_non_pcm = false;
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	/* parse PCM formats */
125362306a36Sopenharmony_ci	err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, false);
125462306a36Sopenharmony_ci	if (err < 0)
125562306a36Sopenharmony_ci		return err;
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	if (has_non_pcm) {
125862306a36Sopenharmony_ci		/* parse non-PCM formats */
125962306a36Sopenharmony_ci		err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, true);
126062306a36Sopenharmony_ci		if (err < 0)
126162306a36Sopenharmony_ci			return err;
126262306a36Sopenharmony_ci	}
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	return 0;
126562306a36Sopenharmony_ci}
126662306a36Sopenharmony_ci
1267