xref: /kernel/linux/linux-5.10/sound/usb/stream.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci */
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/init.h>
78c2ecf20Sopenharmony_ci#include <linux/slab.h>
88c2ecf20Sopenharmony_ci#include <linux/usb.h>
98c2ecf20Sopenharmony_ci#include <linux/usb/audio.h>
108c2ecf20Sopenharmony_ci#include <linux/usb/audio-v2.h>
118c2ecf20Sopenharmony_ci#include <linux/usb/audio-v3.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <sound/core.h>
148c2ecf20Sopenharmony_ci#include <sound/pcm.h>
158c2ecf20Sopenharmony_ci#include <sound/control.h>
168c2ecf20Sopenharmony_ci#include <sound/tlv.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "usbaudio.h"
198c2ecf20Sopenharmony_ci#include "card.h"
208c2ecf20Sopenharmony_ci#include "proc.h"
218c2ecf20Sopenharmony_ci#include "quirks.h"
228c2ecf20Sopenharmony_ci#include "endpoint.h"
238c2ecf20Sopenharmony_ci#include "pcm.h"
248c2ecf20Sopenharmony_ci#include "helper.h"
258c2ecf20Sopenharmony_ci#include "format.h"
268c2ecf20Sopenharmony_ci#include "clock.h"
278c2ecf20Sopenharmony_ci#include "stream.h"
288c2ecf20Sopenharmony_ci#include "power.h"
298c2ecf20Sopenharmony_ci#include "media.h"
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic void audioformat_free(struct audioformat *fp)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	list_del(&fp->list); /* unlink for avoiding double-free */
348c2ecf20Sopenharmony_ci	kfree(fp->rate_table);
358c2ecf20Sopenharmony_ci	kfree(fp->chmap);
368c2ecf20Sopenharmony_ci	kfree(fp);
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/*
408c2ecf20Sopenharmony_ci * free a substream
418c2ecf20Sopenharmony_ci */
428c2ecf20Sopenharmony_cistatic void free_substream(struct snd_usb_substream *subs)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	struct audioformat *fp, *n;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	if (!subs->num_formats)
478c2ecf20Sopenharmony_ci		return; /* not initialized */
488c2ecf20Sopenharmony_ci	list_for_each_entry_safe(fp, n, &subs->fmt_list, list)
498c2ecf20Sopenharmony_ci		audioformat_free(fp);
508c2ecf20Sopenharmony_ci	kfree(subs->rate_list.list);
518c2ecf20Sopenharmony_ci	kfree(subs->str_pd);
528c2ecf20Sopenharmony_ci	snd_media_stream_delete(subs);
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/*
578c2ecf20Sopenharmony_ci * free a usb stream instance
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_cistatic void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	free_substream(&stream->substream[0]);
628c2ecf20Sopenharmony_ci	free_substream(&stream->substream[1]);
638c2ecf20Sopenharmony_ci	list_del(&stream->list);
648c2ecf20Sopenharmony_ci	kfree(stream);
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	struct snd_usb_stream *stream = pcm->private_data;
708c2ecf20Sopenharmony_ci	if (stream) {
718c2ecf20Sopenharmony_ci		stream->pcm = NULL;
728c2ecf20Sopenharmony_ci		snd_usb_audio_stream_free(stream);
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci/*
778c2ecf20Sopenharmony_ci * initialize the substream instance.
788c2ecf20Sopenharmony_ci */
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic void snd_usb_init_substream(struct snd_usb_stream *as,
818c2ecf20Sopenharmony_ci				   int stream,
828c2ecf20Sopenharmony_ci				   struct audioformat *fp,
838c2ecf20Sopenharmony_ci				   struct snd_usb_power_domain *pd)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	struct snd_usb_substream *subs = &as->substream[stream];
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&subs->fmt_list);
888c2ecf20Sopenharmony_ci	spin_lock_init(&subs->lock);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	subs->stream = as;
918c2ecf20Sopenharmony_ci	subs->direction = stream;
928c2ecf20Sopenharmony_ci	subs->dev = as->chip->dev;
938c2ecf20Sopenharmony_ci	subs->txfr_quirk = as->chip->txfr_quirk;
948c2ecf20Sopenharmony_ci	subs->tx_length_quirk = as->chip->tx_length_quirk;
958c2ecf20Sopenharmony_ci	subs->speed = snd_usb_get_speed(subs->dev);
968c2ecf20Sopenharmony_ci	subs->pkt_offset_adj = 0;
978c2ecf20Sopenharmony_ci	subs->stream_offset_adj = 0;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	snd_usb_set_pcm_ops(as->pcm, stream);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	list_add_tail(&fp->list, &subs->fmt_list);
1028c2ecf20Sopenharmony_ci	subs->formats |= fp->formats;
1038c2ecf20Sopenharmony_ci	subs->num_formats++;
1048c2ecf20Sopenharmony_ci	subs->fmt_type = fp->fmt_type;
1058c2ecf20Sopenharmony_ci	subs->ep_num = fp->endpoint;
1068c2ecf20Sopenharmony_ci	if (fp->channels > subs->channels_max)
1078c2ecf20Sopenharmony_ci		subs->channels_max = fp->channels;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	if (pd) {
1108c2ecf20Sopenharmony_ci		subs->str_pd = pd;
1118c2ecf20Sopenharmony_ci		/* Initialize Power Domain to idle status D1 */
1128c2ecf20Sopenharmony_ci		snd_usb_power_domain_set(subs->stream->chip, pd,
1138c2ecf20Sopenharmony_ci					 UAC3_PD_STATE_D1);
1148c2ecf20Sopenharmony_ci	}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	snd_usb_preallocate_buffer(subs);
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci/* kctl callbacks for usb-audio channel maps */
1208c2ecf20Sopenharmony_cistatic int usb_chmap_ctl_info(struct snd_kcontrol *kcontrol,
1218c2ecf20Sopenharmony_ci			      struct snd_ctl_elem_info *uinfo)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
1248c2ecf20Sopenharmony_ci	struct snd_usb_substream *subs = info->private_data;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1278c2ecf20Sopenharmony_ci	uinfo->count = subs->channels_max;
1288c2ecf20Sopenharmony_ci	uinfo->value.integer.min = 0;
1298c2ecf20Sopenharmony_ci	uinfo->value.integer.max = SNDRV_CHMAP_LAST;
1308c2ecf20Sopenharmony_ci	return 0;
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci/* check whether a duplicated entry exists in the audiofmt list */
1348c2ecf20Sopenharmony_cistatic bool have_dup_chmap(struct snd_usb_substream *subs,
1358c2ecf20Sopenharmony_ci			   struct audioformat *fp)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	struct audioformat *prev = fp;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	list_for_each_entry_continue_reverse(prev, &subs->fmt_list, list) {
1408c2ecf20Sopenharmony_ci		if (prev->chmap &&
1418c2ecf20Sopenharmony_ci		    !memcmp(prev->chmap, fp->chmap, sizeof(*fp->chmap)))
1428c2ecf20Sopenharmony_ci			return true;
1438c2ecf20Sopenharmony_ci	}
1448c2ecf20Sopenharmony_ci	return false;
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1488c2ecf20Sopenharmony_ci			     unsigned int size, unsigned int __user *tlv)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
1518c2ecf20Sopenharmony_ci	struct snd_usb_substream *subs = info->private_data;
1528c2ecf20Sopenharmony_ci	struct audioformat *fp;
1538c2ecf20Sopenharmony_ci	unsigned int __user *dst;
1548c2ecf20Sopenharmony_ci	int count = 0;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	if (size < 8)
1578c2ecf20Sopenharmony_ci		return -ENOMEM;
1588c2ecf20Sopenharmony_ci	if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
1598c2ecf20Sopenharmony_ci		return -EFAULT;
1608c2ecf20Sopenharmony_ci	size -= 8;
1618c2ecf20Sopenharmony_ci	dst = tlv + 2;
1628c2ecf20Sopenharmony_ci	list_for_each_entry(fp, &subs->fmt_list, list) {
1638c2ecf20Sopenharmony_ci		int i, ch_bytes;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci		if (!fp->chmap)
1668c2ecf20Sopenharmony_ci			continue;
1678c2ecf20Sopenharmony_ci		if (have_dup_chmap(subs, fp))
1688c2ecf20Sopenharmony_ci			continue;
1698c2ecf20Sopenharmony_ci		/* copy the entry */
1708c2ecf20Sopenharmony_ci		ch_bytes = fp->chmap->channels * 4;
1718c2ecf20Sopenharmony_ci		if (size < 8 + ch_bytes)
1728c2ecf20Sopenharmony_ci			return -ENOMEM;
1738c2ecf20Sopenharmony_ci		if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
1748c2ecf20Sopenharmony_ci		    put_user(ch_bytes, dst + 1))
1758c2ecf20Sopenharmony_ci			return -EFAULT;
1768c2ecf20Sopenharmony_ci		dst += 2;
1778c2ecf20Sopenharmony_ci		for (i = 0; i < fp->chmap->channels; i++, dst++) {
1788c2ecf20Sopenharmony_ci			if (put_user(fp->chmap->map[i], dst))
1798c2ecf20Sopenharmony_ci				return -EFAULT;
1808c2ecf20Sopenharmony_ci		}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci		count += 8 + ch_bytes;
1838c2ecf20Sopenharmony_ci		size -= 8 + ch_bytes;
1848c2ecf20Sopenharmony_ci	}
1858c2ecf20Sopenharmony_ci	if (put_user(count, tlv + 1))
1868c2ecf20Sopenharmony_ci		return -EFAULT;
1878c2ecf20Sopenharmony_ci	return 0;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol,
1918c2ecf20Sopenharmony_ci			     struct snd_ctl_elem_value *ucontrol)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
1948c2ecf20Sopenharmony_ci	struct snd_usb_substream *subs = info->private_data;
1958c2ecf20Sopenharmony_ci	struct snd_pcm_chmap_elem *chmap = NULL;
1968c2ecf20Sopenharmony_ci	int i = 0;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	if (subs->cur_audiofmt)
1998c2ecf20Sopenharmony_ci		chmap = subs->cur_audiofmt->chmap;
2008c2ecf20Sopenharmony_ci	if (chmap) {
2018c2ecf20Sopenharmony_ci		for (i = 0; i < chmap->channels; i++)
2028c2ecf20Sopenharmony_ci			ucontrol->value.integer.value[i] = chmap->map[i];
2038c2ecf20Sopenharmony_ci	}
2048c2ecf20Sopenharmony_ci	for (; i < subs->channels_max; i++)
2058c2ecf20Sopenharmony_ci		ucontrol->value.integer.value[i] = 0;
2068c2ecf20Sopenharmony_ci	return 0;
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci/* create a chmap kctl assigned to the given USB substream */
2108c2ecf20Sopenharmony_cistatic int add_chmap(struct snd_pcm *pcm, int stream,
2118c2ecf20Sopenharmony_ci		     struct snd_usb_substream *subs)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	struct audioformat *fp;
2148c2ecf20Sopenharmony_ci	struct snd_pcm_chmap *chmap;
2158c2ecf20Sopenharmony_ci	struct snd_kcontrol *kctl;
2168c2ecf20Sopenharmony_ci	int err;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	list_for_each_entry(fp, &subs->fmt_list, list)
2198c2ecf20Sopenharmony_ci		if (fp->chmap)
2208c2ecf20Sopenharmony_ci			goto ok;
2218c2ecf20Sopenharmony_ci	/* no chmap is found */
2228c2ecf20Sopenharmony_ci	return 0;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci ok:
2258c2ecf20Sopenharmony_ci	err = snd_pcm_add_chmap_ctls(pcm, stream, NULL, 0, 0, &chmap);
2268c2ecf20Sopenharmony_ci	if (err < 0)
2278c2ecf20Sopenharmony_ci		return err;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	/* override handlers */
2308c2ecf20Sopenharmony_ci	chmap->private_data = subs;
2318c2ecf20Sopenharmony_ci	kctl = chmap->kctl;
2328c2ecf20Sopenharmony_ci	kctl->info = usb_chmap_ctl_info;
2338c2ecf20Sopenharmony_ci	kctl->get = usb_chmap_ctl_get;
2348c2ecf20Sopenharmony_ci	kctl->tlv.c = usb_chmap_ctl_tlv;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	return 0;
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci/* convert from USB ChannelConfig bits to ALSA chmap element */
2408c2ecf20Sopenharmony_cistatic struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
2418c2ecf20Sopenharmony_ci						int protocol)
2428c2ecf20Sopenharmony_ci{
2438c2ecf20Sopenharmony_ci	static const unsigned int uac1_maps[] = {
2448c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FL,		/* left front */
2458c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FR,		/* right front */
2468c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FC,		/* center front */
2478c2ecf20Sopenharmony_ci		SNDRV_CHMAP_LFE,	/* LFE */
2488c2ecf20Sopenharmony_ci		SNDRV_CHMAP_SL,		/* left surround */
2498c2ecf20Sopenharmony_ci		SNDRV_CHMAP_SR,		/* right surround */
2508c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FLC,	/* left of center */
2518c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FRC,	/* right of center */
2528c2ecf20Sopenharmony_ci		SNDRV_CHMAP_RC,		/* surround */
2538c2ecf20Sopenharmony_ci		SNDRV_CHMAP_SL,		/* side left */
2548c2ecf20Sopenharmony_ci		SNDRV_CHMAP_SR,		/* side right */
2558c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TC,		/* top */
2568c2ecf20Sopenharmony_ci		0 /* terminator */
2578c2ecf20Sopenharmony_ci	};
2588c2ecf20Sopenharmony_ci	static const unsigned int uac2_maps[] = {
2598c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FL,		/* front left */
2608c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FR,		/* front right */
2618c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FC,		/* front center */
2628c2ecf20Sopenharmony_ci		SNDRV_CHMAP_LFE,	/* LFE */
2638c2ecf20Sopenharmony_ci		SNDRV_CHMAP_RL,		/* back left */
2648c2ecf20Sopenharmony_ci		SNDRV_CHMAP_RR,		/* back right */
2658c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FLC,	/* front left of center */
2668c2ecf20Sopenharmony_ci		SNDRV_CHMAP_FRC,	/* front right of center */
2678c2ecf20Sopenharmony_ci		SNDRV_CHMAP_RC,		/* back center */
2688c2ecf20Sopenharmony_ci		SNDRV_CHMAP_SL,		/* side left */
2698c2ecf20Sopenharmony_ci		SNDRV_CHMAP_SR,		/* side right */
2708c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TC,		/* top center */
2718c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TFL,	/* top front left */
2728c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TFC,	/* top front center */
2738c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TFR,	/* top front right */
2748c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TRL,	/* top back left */
2758c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TRC,	/* top back center */
2768c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TRR,	/* top back right */
2778c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TFLC,	/* top front left of center */
2788c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TFRC,	/* top front right of center */
2798c2ecf20Sopenharmony_ci		SNDRV_CHMAP_LLFE,	/* left LFE */
2808c2ecf20Sopenharmony_ci		SNDRV_CHMAP_RLFE,	/* right LFE */
2818c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TSL,	/* top side left */
2828c2ecf20Sopenharmony_ci		SNDRV_CHMAP_TSR,	/* top side right */
2838c2ecf20Sopenharmony_ci		SNDRV_CHMAP_BC,		/* bottom center */
2848c2ecf20Sopenharmony_ci		SNDRV_CHMAP_RLC,	/* back left of center */
2858c2ecf20Sopenharmony_ci		SNDRV_CHMAP_RRC,	/* back right of center */
2868c2ecf20Sopenharmony_ci		0 /* terminator */
2878c2ecf20Sopenharmony_ci	};
2888c2ecf20Sopenharmony_ci	struct snd_pcm_chmap_elem *chmap;
2898c2ecf20Sopenharmony_ci	const unsigned int *maps;
2908c2ecf20Sopenharmony_ci	int c;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (channels > ARRAY_SIZE(chmap->map))
2938c2ecf20Sopenharmony_ci		return NULL;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
2968c2ecf20Sopenharmony_ci	if (!chmap)
2978c2ecf20Sopenharmony_ci		return NULL;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps;
3008c2ecf20Sopenharmony_ci	chmap->channels = channels;
3018c2ecf20Sopenharmony_ci	c = 0;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	if (bits) {
3048c2ecf20Sopenharmony_ci		for (; bits && *maps; maps++, bits >>= 1)
3058c2ecf20Sopenharmony_ci			if (bits & 1)
3068c2ecf20Sopenharmony_ci				chmap->map[c++] = *maps;
3078c2ecf20Sopenharmony_ci	} else {
3088c2ecf20Sopenharmony_ci		/* If we're missing wChannelConfig, then guess something
3098c2ecf20Sopenharmony_ci		    to make sure the channel map is not skipped entirely */
3108c2ecf20Sopenharmony_ci		if (channels == 1)
3118c2ecf20Sopenharmony_ci			chmap->map[c++] = SNDRV_CHMAP_MONO;
3128c2ecf20Sopenharmony_ci		else
3138c2ecf20Sopenharmony_ci			for (; c < channels && *maps; maps++)
3148c2ecf20Sopenharmony_ci				chmap->map[c++] = *maps;
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	for (; c < channels; c++)
3188c2ecf20Sopenharmony_ci		chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	return chmap;
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci/* UAC3 device stores channels information in Cluster Descriptors */
3248c2ecf20Sopenharmony_cistatic struct
3258c2ecf20Sopenharmony_cisnd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor
3268c2ecf20Sopenharmony_ci								*cluster)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	unsigned int channels = cluster->bNrChannels;
3298c2ecf20Sopenharmony_ci	struct snd_pcm_chmap_elem *chmap;
3308c2ecf20Sopenharmony_ci	void *p = cluster;
3318c2ecf20Sopenharmony_ci	int len, c;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	if (channels > ARRAY_SIZE(chmap->map))
3348c2ecf20Sopenharmony_ci		return NULL;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
3378c2ecf20Sopenharmony_ci	if (!chmap)
3388c2ecf20Sopenharmony_ci		return NULL;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	len = le16_to_cpu(cluster->wLength);
3418c2ecf20Sopenharmony_ci	c = 0;
3428c2ecf20Sopenharmony_ci	p += sizeof(struct uac3_cluster_header_descriptor);
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	while (((p - (void *)cluster) < len) && (c < channels)) {
3458c2ecf20Sopenharmony_ci		struct uac3_cluster_segment_descriptor *cs_desc = p;
3468c2ecf20Sopenharmony_ci		u16 cs_len;
3478c2ecf20Sopenharmony_ci		u8 cs_type;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci		cs_len = le16_to_cpu(cs_desc->wLength);
3508c2ecf20Sopenharmony_ci		cs_type = cs_desc->bSegmentType;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci		if (cs_type == UAC3_CHANNEL_INFORMATION) {
3538c2ecf20Sopenharmony_ci			struct uac3_cluster_information_segment_descriptor *is = p;
3548c2ecf20Sopenharmony_ci			unsigned char map;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci			/*
3578c2ecf20Sopenharmony_ci			 * TODO: this conversion is not complete, update it
3588c2ecf20Sopenharmony_ci			 * after adding UAC3 values to asound.h
3598c2ecf20Sopenharmony_ci			 */
3608c2ecf20Sopenharmony_ci			switch (is->bChRelationship) {
3618c2ecf20Sopenharmony_ci			case UAC3_CH_MONO:
3628c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_MONO;
3638c2ecf20Sopenharmony_ci				break;
3648c2ecf20Sopenharmony_ci			case UAC3_CH_LEFT:
3658c2ecf20Sopenharmony_ci			case UAC3_CH_FRONT_LEFT:
3668c2ecf20Sopenharmony_ci			case UAC3_CH_HEADPHONE_LEFT:
3678c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_FL;
3688c2ecf20Sopenharmony_ci				break;
3698c2ecf20Sopenharmony_ci			case UAC3_CH_RIGHT:
3708c2ecf20Sopenharmony_ci			case UAC3_CH_FRONT_RIGHT:
3718c2ecf20Sopenharmony_ci			case UAC3_CH_HEADPHONE_RIGHT:
3728c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_FR;
3738c2ecf20Sopenharmony_ci				break;
3748c2ecf20Sopenharmony_ci			case UAC3_CH_FRONT_CENTER:
3758c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_FC;
3768c2ecf20Sopenharmony_ci				break;
3778c2ecf20Sopenharmony_ci			case UAC3_CH_FRONT_LEFT_OF_CENTER:
3788c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_FLC;
3798c2ecf20Sopenharmony_ci				break;
3808c2ecf20Sopenharmony_ci			case UAC3_CH_FRONT_RIGHT_OF_CENTER:
3818c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_FRC;
3828c2ecf20Sopenharmony_ci				break;
3838c2ecf20Sopenharmony_ci			case UAC3_CH_SIDE_LEFT:
3848c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_SL;
3858c2ecf20Sopenharmony_ci				break;
3868c2ecf20Sopenharmony_ci			case UAC3_CH_SIDE_RIGHT:
3878c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_SR;
3888c2ecf20Sopenharmony_ci				break;
3898c2ecf20Sopenharmony_ci			case UAC3_CH_BACK_LEFT:
3908c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_RL;
3918c2ecf20Sopenharmony_ci				break;
3928c2ecf20Sopenharmony_ci			case UAC3_CH_BACK_RIGHT:
3938c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_RR;
3948c2ecf20Sopenharmony_ci				break;
3958c2ecf20Sopenharmony_ci			case UAC3_CH_BACK_CENTER:
3968c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_RC;
3978c2ecf20Sopenharmony_ci				break;
3988c2ecf20Sopenharmony_ci			case UAC3_CH_BACK_LEFT_OF_CENTER:
3998c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_RLC;
4008c2ecf20Sopenharmony_ci				break;
4018c2ecf20Sopenharmony_ci			case UAC3_CH_BACK_RIGHT_OF_CENTER:
4028c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_RRC;
4038c2ecf20Sopenharmony_ci				break;
4048c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_CENTER:
4058c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TC;
4068c2ecf20Sopenharmony_ci				break;
4078c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_FRONT_LEFT:
4088c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TFL;
4098c2ecf20Sopenharmony_ci				break;
4108c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_FRONT_RIGHT:
4118c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TFR;
4128c2ecf20Sopenharmony_ci				break;
4138c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_FRONT_CENTER:
4148c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TFC;
4158c2ecf20Sopenharmony_ci				break;
4168c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_FRONT_LOC:
4178c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TFLC;
4188c2ecf20Sopenharmony_ci				break;
4198c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_FRONT_ROC:
4208c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TFRC;
4218c2ecf20Sopenharmony_ci				break;
4228c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_SIDE_LEFT:
4238c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TSL;
4248c2ecf20Sopenharmony_ci				break;
4258c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_SIDE_RIGHT:
4268c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TSR;
4278c2ecf20Sopenharmony_ci				break;
4288c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_BACK_LEFT:
4298c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TRL;
4308c2ecf20Sopenharmony_ci				break;
4318c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_BACK_RIGHT:
4328c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TRR;
4338c2ecf20Sopenharmony_ci				break;
4348c2ecf20Sopenharmony_ci			case UAC3_CH_TOP_BACK_CENTER:
4358c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_TRC;
4368c2ecf20Sopenharmony_ci				break;
4378c2ecf20Sopenharmony_ci			case UAC3_CH_BOTTOM_CENTER:
4388c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_BC;
4398c2ecf20Sopenharmony_ci				break;
4408c2ecf20Sopenharmony_ci			case UAC3_CH_LOW_FREQUENCY_EFFECTS:
4418c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_LFE;
4428c2ecf20Sopenharmony_ci				break;
4438c2ecf20Sopenharmony_ci			case UAC3_CH_LFE_LEFT:
4448c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_LLFE;
4458c2ecf20Sopenharmony_ci				break;
4468c2ecf20Sopenharmony_ci			case UAC3_CH_LFE_RIGHT:
4478c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_RLFE;
4488c2ecf20Sopenharmony_ci				break;
4498c2ecf20Sopenharmony_ci			case UAC3_CH_RELATIONSHIP_UNDEFINED:
4508c2ecf20Sopenharmony_ci			default:
4518c2ecf20Sopenharmony_ci				map = SNDRV_CHMAP_UNKNOWN;
4528c2ecf20Sopenharmony_ci				break;
4538c2ecf20Sopenharmony_ci			}
4548c2ecf20Sopenharmony_ci			chmap->map[c++] = map;
4558c2ecf20Sopenharmony_ci		}
4568c2ecf20Sopenharmony_ci		p += cs_len;
4578c2ecf20Sopenharmony_ci	}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	if (channels < c)
4608c2ecf20Sopenharmony_ci		pr_err("%s: channel number mismatch\n", __func__);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	chmap->channels = channels;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	for (; c < channels; c++)
4658c2ecf20Sopenharmony_ci		chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	return chmap;
4688c2ecf20Sopenharmony_ci}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci/*
4718c2ecf20Sopenharmony_ci * add this endpoint to the chip instance.
4728c2ecf20Sopenharmony_ci * if a stream with the same endpoint already exists, append to it.
4738c2ecf20Sopenharmony_ci * if not, create a new pcm stream. note, fp is added to the substream
4748c2ecf20Sopenharmony_ci * fmt_list and will be freed on the chip instance release. do not free
4758c2ecf20Sopenharmony_ci * fp or do remove it from the substream fmt_list to avoid double-free.
4768c2ecf20Sopenharmony_ci */
4778c2ecf20Sopenharmony_cistatic int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
4788c2ecf20Sopenharmony_ci				      int stream,
4798c2ecf20Sopenharmony_ci				      struct audioformat *fp,
4808c2ecf20Sopenharmony_ci				      struct snd_usb_power_domain *pd)
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	struct snd_usb_stream *as;
4848c2ecf20Sopenharmony_ci	struct snd_usb_substream *subs;
4858c2ecf20Sopenharmony_ci	struct snd_pcm *pcm;
4868c2ecf20Sopenharmony_ci	int err;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	list_for_each_entry(as, &chip->pcm_list, list) {
4898c2ecf20Sopenharmony_ci		if (as->fmt_type != fp->fmt_type)
4908c2ecf20Sopenharmony_ci			continue;
4918c2ecf20Sopenharmony_ci		subs = &as->substream[stream];
4928c2ecf20Sopenharmony_ci		if (subs->ep_num == fp->endpoint) {
4938c2ecf20Sopenharmony_ci			list_add_tail(&fp->list, &subs->fmt_list);
4948c2ecf20Sopenharmony_ci			subs->num_formats++;
4958c2ecf20Sopenharmony_ci			subs->formats |= fp->formats;
4968c2ecf20Sopenharmony_ci			return 0;
4978c2ecf20Sopenharmony_ci		}
4988c2ecf20Sopenharmony_ci	}
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	if (chip->card->registered)
5018c2ecf20Sopenharmony_ci		chip->need_delayed_register = true;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	/* look for an empty stream */
5048c2ecf20Sopenharmony_ci	list_for_each_entry(as, &chip->pcm_list, list) {
5058c2ecf20Sopenharmony_ci		if (as->fmt_type != fp->fmt_type)
5068c2ecf20Sopenharmony_ci			continue;
5078c2ecf20Sopenharmony_ci		subs = &as->substream[stream];
5088c2ecf20Sopenharmony_ci		if (subs->ep_num)
5098c2ecf20Sopenharmony_ci			continue;
5108c2ecf20Sopenharmony_ci		err = snd_pcm_new_stream(as->pcm, stream, 1);
5118c2ecf20Sopenharmony_ci		if (err < 0)
5128c2ecf20Sopenharmony_ci			return err;
5138c2ecf20Sopenharmony_ci		snd_usb_init_substream(as, stream, fp, pd);
5148c2ecf20Sopenharmony_ci		return add_chmap(as->pcm, stream, subs);
5158c2ecf20Sopenharmony_ci	}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	/* create a new pcm */
5188c2ecf20Sopenharmony_ci	as = kzalloc(sizeof(*as), GFP_KERNEL);
5198c2ecf20Sopenharmony_ci	if (!as)
5208c2ecf20Sopenharmony_ci		return -ENOMEM;
5218c2ecf20Sopenharmony_ci	as->pcm_index = chip->pcm_devs;
5228c2ecf20Sopenharmony_ci	as->chip = chip;
5238c2ecf20Sopenharmony_ci	as->fmt_type = fp->fmt_type;
5248c2ecf20Sopenharmony_ci	err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
5258c2ecf20Sopenharmony_ci			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
5268c2ecf20Sopenharmony_ci			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
5278c2ecf20Sopenharmony_ci			  &pcm);
5288c2ecf20Sopenharmony_ci	if (err < 0) {
5298c2ecf20Sopenharmony_ci		kfree(as);
5308c2ecf20Sopenharmony_ci		return err;
5318c2ecf20Sopenharmony_ci	}
5328c2ecf20Sopenharmony_ci	as->pcm = pcm;
5338c2ecf20Sopenharmony_ci	pcm->private_data = as;
5348c2ecf20Sopenharmony_ci	pcm->private_free = snd_usb_audio_pcm_free;
5358c2ecf20Sopenharmony_ci	pcm->info_flags = 0;
5368c2ecf20Sopenharmony_ci	if (chip->pcm_devs > 0)
5378c2ecf20Sopenharmony_ci		sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
5388c2ecf20Sopenharmony_ci	else
5398c2ecf20Sopenharmony_ci		strcpy(pcm->name, "USB Audio");
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	snd_usb_init_substream(as, stream, fp, pd);
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	/*
5448c2ecf20Sopenharmony_ci	 * Keep using head insertion for M-Audio Audiophile USB (tm) which has a
5458c2ecf20Sopenharmony_ci	 * fix to swap capture stream order in conf/cards/USB-audio.conf
5468c2ecf20Sopenharmony_ci	 */
5478c2ecf20Sopenharmony_ci	if (chip->usb_id == USB_ID(0x0763, 0x2003))
5488c2ecf20Sopenharmony_ci		list_add(&as->list, &chip->pcm_list);
5498c2ecf20Sopenharmony_ci	else
5508c2ecf20Sopenharmony_ci		list_add_tail(&as->list, &chip->pcm_list);
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	chip->pcm_devs++;
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	snd_usb_proc_pcm_format_add(as);
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	return add_chmap(pcm, stream, &as->substream[stream]);
5578c2ecf20Sopenharmony_ci}
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ciint snd_usb_add_audio_stream(struct snd_usb_audio *chip,
5608c2ecf20Sopenharmony_ci			     int stream,
5618c2ecf20Sopenharmony_ci			     struct audioformat *fp)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	return __snd_usb_add_audio_stream(chip, stream, fp, NULL);
5648c2ecf20Sopenharmony_ci}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_cistatic int snd_usb_add_audio_stream_v3(struct snd_usb_audio *chip,
5678c2ecf20Sopenharmony_ci				       int stream,
5688c2ecf20Sopenharmony_ci				       struct audioformat *fp,
5698c2ecf20Sopenharmony_ci				       struct snd_usb_power_domain *pd)
5708c2ecf20Sopenharmony_ci{
5718c2ecf20Sopenharmony_ci	return __snd_usb_add_audio_stream(chip, stream, fp, pd);
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cistatic int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
5758c2ecf20Sopenharmony_ci					 struct usb_host_interface *alts,
5768c2ecf20Sopenharmony_ci					 int protocol, int iface_no)
5778c2ecf20Sopenharmony_ci{
5788c2ecf20Sopenharmony_ci	/* parsed with a v1 header here. that's ok as we only look at the
5798c2ecf20Sopenharmony_ci	 * header first which is the same for both versions */
5808c2ecf20Sopenharmony_ci	struct uac_iso_endpoint_descriptor *csep;
5818c2ecf20Sopenharmony_ci	struct usb_interface_descriptor *altsd = get_iface_desc(alts);
5828c2ecf20Sopenharmony_ci	int attributes = 0;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	/* Creamware Noah has this descriptor after the 2nd endpoint */
5878c2ecf20Sopenharmony_ci	if (!csep && altsd->bNumEndpoints >= 2)
5888c2ecf20Sopenharmony_ci		csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	/*
5918c2ecf20Sopenharmony_ci	 * If we can't locate the USB_DT_CS_ENDPOINT descriptor in the extra
5928c2ecf20Sopenharmony_ci	 * bytes after the first endpoint, go search the entire interface.
5938c2ecf20Sopenharmony_ci	 * Some devices have it directly *before* the standard endpoint.
5948c2ecf20Sopenharmony_ci	 */
5958c2ecf20Sopenharmony_ci	if (!csep)
5968c2ecf20Sopenharmony_ci		csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT);
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	if (!csep || csep->bLength < 7 ||
5998c2ecf20Sopenharmony_ci	    csep->bDescriptorSubtype != UAC_EP_GENERAL)
6008c2ecf20Sopenharmony_ci		goto error;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	if (protocol == UAC_VERSION_1) {
6038c2ecf20Sopenharmony_ci		attributes = csep->bmAttributes;
6048c2ecf20Sopenharmony_ci	} else if (protocol == UAC_VERSION_2) {
6058c2ecf20Sopenharmony_ci		struct uac2_iso_endpoint_descriptor *csep2 =
6068c2ecf20Sopenharmony_ci			(struct uac2_iso_endpoint_descriptor *) csep;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci		if (csep2->bLength < sizeof(*csep2))
6098c2ecf20Sopenharmony_ci			goto error;
6108c2ecf20Sopenharmony_ci		attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci		/* emulate the endpoint attributes of a v1 device */
6138c2ecf20Sopenharmony_ci		if (csep2->bmControls & UAC2_CONTROL_PITCH)
6148c2ecf20Sopenharmony_ci			attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
6158c2ecf20Sopenharmony_ci	} else { /* UAC_VERSION_3 */
6168c2ecf20Sopenharmony_ci		struct uac3_iso_endpoint_descriptor *csep3 =
6178c2ecf20Sopenharmony_ci			(struct uac3_iso_endpoint_descriptor *) csep;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci		if (csep3->bLength < sizeof(*csep3))
6208c2ecf20Sopenharmony_ci			goto error;
6218c2ecf20Sopenharmony_ci		/* emulate the endpoint attributes of a v1 device */
6228c2ecf20Sopenharmony_ci		if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH)
6238c2ecf20Sopenharmony_ci			attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
6248c2ecf20Sopenharmony_ci	}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	return attributes;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci error:
6298c2ecf20Sopenharmony_ci	usb_audio_warn(chip,
6308c2ecf20Sopenharmony_ci		       "%u:%d : no or invalid class specific endpoint descriptor\n",
6318c2ecf20Sopenharmony_ci		       iface_no, altsd->bAlternateSetting);
6328c2ecf20Sopenharmony_ci	return 0;
6338c2ecf20Sopenharmony_ci}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci/* find an input terminal descriptor (either UAC1 or UAC2) with the given
6368c2ecf20Sopenharmony_ci * terminal id
6378c2ecf20Sopenharmony_ci */
6388c2ecf20Sopenharmony_cistatic void *
6398c2ecf20Sopenharmony_cisnd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
6408c2ecf20Sopenharmony_ci				       int terminal_id, int protocol)
6418c2ecf20Sopenharmony_ci{
6428c2ecf20Sopenharmony_ci	struct uac2_input_terminal_descriptor *term = NULL;
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
6458c2ecf20Sopenharmony_ci					       ctrl_iface->extralen,
6468c2ecf20Sopenharmony_ci					       term, UAC_INPUT_TERMINAL))) {
6478c2ecf20Sopenharmony_ci		if (!snd_usb_validate_audio_desc(term, protocol))
6488c2ecf20Sopenharmony_ci			continue;
6498c2ecf20Sopenharmony_ci		if (term->bTerminalID == terminal_id)
6508c2ecf20Sopenharmony_ci			return term;
6518c2ecf20Sopenharmony_ci	}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	return NULL;
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_cistatic void *
6578c2ecf20Sopenharmony_cisnd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
6588c2ecf20Sopenharmony_ci					int terminal_id, int protocol)
6598c2ecf20Sopenharmony_ci{
6608c2ecf20Sopenharmony_ci	/* OK to use with both UAC2 and UAC3 */
6618c2ecf20Sopenharmony_ci	struct uac2_output_terminal_descriptor *term = NULL;
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
6648c2ecf20Sopenharmony_ci					       ctrl_iface->extralen,
6658c2ecf20Sopenharmony_ci					       term, UAC_OUTPUT_TERMINAL))) {
6668c2ecf20Sopenharmony_ci		if (!snd_usb_validate_audio_desc(term, protocol))
6678c2ecf20Sopenharmony_ci			continue;
6688c2ecf20Sopenharmony_ci		if (term->bTerminalID == terminal_id)
6698c2ecf20Sopenharmony_ci			return term;
6708c2ecf20Sopenharmony_ci	}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	return NULL;
6738c2ecf20Sopenharmony_ci}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_cistatic struct audioformat *
6768c2ecf20Sopenharmony_ciaudio_format_alloc_init(struct snd_usb_audio *chip,
6778c2ecf20Sopenharmony_ci		       struct usb_host_interface *alts,
6788c2ecf20Sopenharmony_ci		       int protocol, int iface_no, int altset_idx,
6798c2ecf20Sopenharmony_ci		       int altno, int num_channels, int clock)
6808c2ecf20Sopenharmony_ci{
6818c2ecf20Sopenharmony_ci	struct audioformat *fp;
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	fp = kzalloc(sizeof(*fp), GFP_KERNEL);
6848c2ecf20Sopenharmony_ci	if (!fp)
6858c2ecf20Sopenharmony_ci		return NULL;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	fp->iface = iface_no;
6888c2ecf20Sopenharmony_ci	fp->altsetting = altno;
6898c2ecf20Sopenharmony_ci	fp->altset_idx = altset_idx;
6908c2ecf20Sopenharmony_ci	fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
6918c2ecf20Sopenharmony_ci	fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
6928c2ecf20Sopenharmony_ci	fp->datainterval = snd_usb_parse_datainterval(chip, alts);
6938c2ecf20Sopenharmony_ci	fp->protocol = protocol;
6948c2ecf20Sopenharmony_ci	fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
6958c2ecf20Sopenharmony_ci	fp->channels = num_channels;
6968c2ecf20Sopenharmony_ci	if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH)
6978c2ecf20Sopenharmony_ci		fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
6988c2ecf20Sopenharmony_ci				* (fp->maxpacksize & 0x7ff);
6998c2ecf20Sopenharmony_ci	fp->clock = clock;
7008c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&fp->list);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	return fp;
7038c2ecf20Sopenharmony_ci}
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_cistatic struct audioformat *
7068c2ecf20Sopenharmony_cisnd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
7078c2ecf20Sopenharmony_ci			      struct usb_host_interface *alts,
7088c2ecf20Sopenharmony_ci			      int protocol, int iface_no, int altset_idx,
7098c2ecf20Sopenharmony_ci			      int altno, int stream, int bm_quirk)
7108c2ecf20Sopenharmony_ci{
7118c2ecf20Sopenharmony_ci	struct usb_device *dev = chip->dev;
7128c2ecf20Sopenharmony_ci	struct uac_format_type_i_continuous_descriptor *fmt;
7138c2ecf20Sopenharmony_ci	unsigned int num_channels = 0, chconfig = 0;
7148c2ecf20Sopenharmony_ci	struct audioformat *fp;
7158c2ecf20Sopenharmony_ci	int clock = 0;
7168c2ecf20Sopenharmony_ci	u64 format;
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	/* get audio formats */
7198c2ecf20Sopenharmony_ci	if (protocol == UAC_VERSION_1) {
7208c2ecf20Sopenharmony_ci		struct uac1_as_header_descriptor *as =
7218c2ecf20Sopenharmony_ci			snd_usb_find_csint_desc(alts->extra, alts->extralen,
7228c2ecf20Sopenharmony_ci						NULL, UAC_AS_GENERAL);
7238c2ecf20Sopenharmony_ci		struct uac_input_terminal_descriptor *iterm;
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci		if (!as) {
7268c2ecf20Sopenharmony_ci			dev_err(&dev->dev,
7278c2ecf20Sopenharmony_ci				"%u:%d : UAC_AS_GENERAL descriptor not found\n",
7288c2ecf20Sopenharmony_ci				iface_no, altno);
7298c2ecf20Sopenharmony_ci			return NULL;
7308c2ecf20Sopenharmony_ci		}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci		if (as->bLength < sizeof(*as)) {
7338c2ecf20Sopenharmony_ci			dev_err(&dev->dev,
7348c2ecf20Sopenharmony_ci				"%u:%d : invalid UAC_AS_GENERAL desc\n",
7358c2ecf20Sopenharmony_ci				iface_no, altno);
7368c2ecf20Sopenharmony_ci			return NULL;
7378c2ecf20Sopenharmony_ci		}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci		format = le16_to_cpu(as->wFormatTag); /* remember the format value */
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci		iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
7428c2ecf20Sopenharmony_ci							       as->bTerminalLink,
7438c2ecf20Sopenharmony_ci							       protocol);
7448c2ecf20Sopenharmony_ci		if (iterm) {
7458c2ecf20Sopenharmony_ci			num_channels = iterm->bNrChannels;
7468c2ecf20Sopenharmony_ci			chconfig = le16_to_cpu(iterm->wChannelConfig);
7478c2ecf20Sopenharmony_ci		}
7488c2ecf20Sopenharmony_ci	} else { /* UAC_VERSION_2 */
7498c2ecf20Sopenharmony_ci		struct uac2_input_terminal_descriptor *input_term;
7508c2ecf20Sopenharmony_ci		struct uac2_output_terminal_descriptor *output_term;
7518c2ecf20Sopenharmony_ci		struct uac2_as_header_descriptor *as =
7528c2ecf20Sopenharmony_ci			snd_usb_find_csint_desc(alts->extra, alts->extralen,
7538c2ecf20Sopenharmony_ci						NULL, UAC_AS_GENERAL);
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci		if (!as) {
7568c2ecf20Sopenharmony_ci			dev_err(&dev->dev,
7578c2ecf20Sopenharmony_ci				"%u:%d : UAC_AS_GENERAL descriptor not found\n",
7588c2ecf20Sopenharmony_ci				iface_no, altno);
7598c2ecf20Sopenharmony_ci			return NULL;
7608c2ecf20Sopenharmony_ci		}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci		if (as->bLength < sizeof(*as)) {
7638c2ecf20Sopenharmony_ci			dev_err(&dev->dev,
7648c2ecf20Sopenharmony_ci				"%u:%d : invalid UAC_AS_GENERAL desc\n",
7658c2ecf20Sopenharmony_ci				iface_no, altno);
7668c2ecf20Sopenharmony_ci			return NULL;
7678c2ecf20Sopenharmony_ci		}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci		num_channels = as->bNrChannels;
7708c2ecf20Sopenharmony_ci		format = le32_to_cpu(as->bmFormats);
7718c2ecf20Sopenharmony_ci		chconfig = le32_to_cpu(as->bmChannelConfig);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci		/*
7748c2ecf20Sopenharmony_ci		 * lookup the terminal associated to this interface
7758c2ecf20Sopenharmony_ci		 * to extract the clock
7768c2ecf20Sopenharmony_ci		 */
7778c2ecf20Sopenharmony_ci		input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
7788c2ecf20Sopenharmony_ci								    as->bTerminalLink,
7798c2ecf20Sopenharmony_ci								    protocol);
7808c2ecf20Sopenharmony_ci		if (input_term) {
7818c2ecf20Sopenharmony_ci			clock = input_term->bCSourceID;
7828c2ecf20Sopenharmony_ci			if (!chconfig && (num_channels == input_term->bNrChannels))
7838c2ecf20Sopenharmony_ci				chconfig = le32_to_cpu(input_term->bmChannelConfig);
7848c2ecf20Sopenharmony_ci			goto found_clock;
7858c2ecf20Sopenharmony_ci		}
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci		output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
7888c2ecf20Sopenharmony_ci								      as->bTerminalLink,
7898c2ecf20Sopenharmony_ci								      protocol);
7908c2ecf20Sopenharmony_ci		if (output_term) {
7918c2ecf20Sopenharmony_ci			clock = output_term->bCSourceID;
7928c2ecf20Sopenharmony_ci			goto found_clock;
7938c2ecf20Sopenharmony_ci		}
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci		dev_err(&dev->dev,
7968c2ecf20Sopenharmony_ci			"%u:%d : bogus bTerminalLink %d\n",
7978c2ecf20Sopenharmony_ci			iface_no, altno, as->bTerminalLink);
7988c2ecf20Sopenharmony_ci		return NULL;
7998c2ecf20Sopenharmony_ci	}
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_cifound_clock:
8028c2ecf20Sopenharmony_ci	/* get format type */
8038c2ecf20Sopenharmony_ci	fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen,
8048c2ecf20Sopenharmony_ci				      NULL, UAC_FORMAT_TYPE);
8058c2ecf20Sopenharmony_ci	if (!fmt) {
8068c2ecf20Sopenharmony_ci		dev_err(&dev->dev,
8078c2ecf20Sopenharmony_ci			"%u:%d : no UAC_FORMAT_TYPE desc\n",
8088c2ecf20Sopenharmony_ci			iface_no, altno);
8098c2ecf20Sopenharmony_ci		return NULL;
8108c2ecf20Sopenharmony_ci	}
8118c2ecf20Sopenharmony_ci	if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8))
8128c2ecf20Sopenharmony_ci			|| ((protocol == UAC_VERSION_2) &&
8138c2ecf20Sopenharmony_ci					(fmt->bLength < 6))) {
8148c2ecf20Sopenharmony_ci		dev_err(&dev->dev,
8158c2ecf20Sopenharmony_ci			"%u:%d : invalid UAC_FORMAT_TYPE desc\n",
8168c2ecf20Sopenharmony_ci			iface_no, altno);
8178c2ecf20Sopenharmony_ci		return NULL;
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	/*
8218c2ecf20Sopenharmony_ci	 * Blue Microphones workaround: The last altsetting is
8228c2ecf20Sopenharmony_ci	 * identical with the previous one, except for a larger
8238c2ecf20Sopenharmony_ci	 * packet size, but is actually a mislabeled two-channel
8248c2ecf20Sopenharmony_ci	 * setting; ignore it.
8258c2ecf20Sopenharmony_ci	 *
8268c2ecf20Sopenharmony_ci	 * Part 2: analyze quirk flag and format
8278c2ecf20Sopenharmony_ci	 */
8288c2ecf20Sopenharmony_ci	if (bm_quirk && fmt->bNrChannels == 1 && fmt->bSubframeSize == 2)
8298c2ecf20Sopenharmony_ci		return NULL;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	fp = audio_format_alloc_init(chip, alts, protocol, iface_no,
8328c2ecf20Sopenharmony_ci				     altset_idx, altno, num_channels, clock);
8338c2ecf20Sopenharmony_ci	if (!fp)
8348c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol,
8378c2ecf20Sopenharmony_ci						       iface_no);
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	/* some quirks for attributes here */
8408c2ecf20Sopenharmony_ci	snd_usb_audioformat_attributes_quirk(chip, fp, stream);
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	/* ok, let's parse further... */
8438c2ecf20Sopenharmony_ci	if (snd_usb_parse_audio_format(chip, fp, format,
8448c2ecf20Sopenharmony_ci					fmt, stream) < 0) {
8458c2ecf20Sopenharmony_ci		audioformat_free(fp);
8468c2ecf20Sopenharmony_ci		return NULL;
8478c2ecf20Sopenharmony_ci	}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	/* Create chmap */
8508c2ecf20Sopenharmony_ci	if (fp->channels != num_channels)
8518c2ecf20Sopenharmony_ci		chconfig = 0;
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	fp->chmap = convert_chmap(fp->channels, chconfig, protocol);
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	return fp;
8568c2ecf20Sopenharmony_ci}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_cistatic struct audioformat *
8598c2ecf20Sopenharmony_cisnd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
8608c2ecf20Sopenharmony_ci			     struct usb_host_interface *alts,
8618c2ecf20Sopenharmony_ci			     struct snd_usb_power_domain **pd_out,
8628c2ecf20Sopenharmony_ci			     int iface_no, int altset_idx,
8638c2ecf20Sopenharmony_ci			     int altno, int stream)
8648c2ecf20Sopenharmony_ci{
8658c2ecf20Sopenharmony_ci	struct usb_device *dev = chip->dev;
8668c2ecf20Sopenharmony_ci	struct uac3_input_terminal_descriptor *input_term;
8678c2ecf20Sopenharmony_ci	struct uac3_output_terminal_descriptor *output_term;
8688c2ecf20Sopenharmony_ci	struct uac3_cluster_header_descriptor *cluster;
8698c2ecf20Sopenharmony_ci	struct uac3_as_header_descriptor *as = NULL;
8708c2ecf20Sopenharmony_ci	struct uac3_hc_descriptor_header hc_header;
8718c2ecf20Sopenharmony_ci	struct snd_pcm_chmap_elem *chmap;
8728c2ecf20Sopenharmony_ci	struct snd_usb_power_domain *pd;
8738c2ecf20Sopenharmony_ci	unsigned char badd_profile;
8748c2ecf20Sopenharmony_ci	u64 badd_formats = 0;
8758c2ecf20Sopenharmony_ci	unsigned int num_channels;
8768c2ecf20Sopenharmony_ci	struct audioformat *fp;
8778c2ecf20Sopenharmony_ci	u16 cluster_id, wLength;
8788c2ecf20Sopenharmony_ci	int clock = 0;
8798c2ecf20Sopenharmony_ci	int err;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	badd_profile = chip->badd_profile;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
8848c2ecf20Sopenharmony_ci		unsigned int maxpacksize =
8858c2ecf20Sopenharmony_ci			le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci		switch (maxpacksize) {
8888c2ecf20Sopenharmony_ci		default:
8898c2ecf20Sopenharmony_ci			dev_err(&dev->dev,
8908c2ecf20Sopenharmony_ci				"%u:%d : incorrect wMaxPacketSize for BADD profile\n",
8918c2ecf20Sopenharmony_ci				iface_no, altno);
8928c2ecf20Sopenharmony_ci			return NULL;
8938c2ecf20Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16:
8948c2ecf20Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16:
8958c2ecf20Sopenharmony_ci			badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
8968c2ecf20Sopenharmony_ci			num_channels = 1;
8978c2ecf20Sopenharmony_ci			break;
8988c2ecf20Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24:
8998c2ecf20Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24:
9008c2ecf20Sopenharmony_ci			badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
9018c2ecf20Sopenharmony_ci			num_channels = 1;
9028c2ecf20Sopenharmony_ci			break;
9038c2ecf20Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16:
9048c2ecf20Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16:
9058c2ecf20Sopenharmony_ci			badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
9068c2ecf20Sopenharmony_ci			num_channels = 2;
9078c2ecf20Sopenharmony_ci			break;
9088c2ecf20Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24:
9098c2ecf20Sopenharmony_ci		case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24:
9108c2ecf20Sopenharmony_ci			badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
9118c2ecf20Sopenharmony_ci			num_channels = 2;
9128c2ecf20Sopenharmony_ci			break;
9138c2ecf20Sopenharmony_ci		}
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci		chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
9168c2ecf20Sopenharmony_ci		if (!chmap)
9178c2ecf20Sopenharmony_ci			return ERR_PTR(-ENOMEM);
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci		if (num_channels == 1) {
9208c2ecf20Sopenharmony_ci			chmap->map[0] = SNDRV_CHMAP_MONO;
9218c2ecf20Sopenharmony_ci		} else {
9228c2ecf20Sopenharmony_ci			chmap->map[0] = SNDRV_CHMAP_FL;
9238c2ecf20Sopenharmony_ci			chmap->map[1] = SNDRV_CHMAP_FR;
9248c2ecf20Sopenharmony_ci		}
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci		chmap->channels = num_channels;
9278c2ecf20Sopenharmony_ci		clock = UAC3_BADD_CS_ID9;
9288c2ecf20Sopenharmony_ci		goto found_clock;
9298c2ecf20Sopenharmony_ci	}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	as = snd_usb_find_csint_desc(alts->extra, alts->extralen,
9328c2ecf20Sopenharmony_ci				     NULL, UAC_AS_GENERAL);
9338c2ecf20Sopenharmony_ci	if (!as) {
9348c2ecf20Sopenharmony_ci		dev_err(&dev->dev,
9358c2ecf20Sopenharmony_ci			"%u:%d : UAC_AS_GENERAL descriptor not found\n",
9368c2ecf20Sopenharmony_ci			iface_no, altno);
9378c2ecf20Sopenharmony_ci		return NULL;
9388c2ecf20Sopenharmony_ci	}
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	if (as->bLength < sizeof(*as)) {
9418c2ecf20Sopenharmony_ci		dev_err(&dev->dev,
9428c2ecf20Sopenharmony_ci			"%u:%d : invalid UAC_AS_GENERAL desc\n",
9438c2ecf20Sopenharmony_ci			iface_no, altno);
9448c2ecf20Sopenharmony_ci		return NULL;
9458c2ecf20Sopenharmony_ci	}
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	cluster_id = le16_to_cpu(as->wClusterDescrID);
9488c2ecf20Sopenharmony_ci	if (!cluster_id) {
9498c2ecf20Sopenharmony_ci		dev_err(&dev->dev,
9508c2ecf20Sopenharmony_ci			"%u:%d : no cluster descriptor\n",
9518c2ecf20Sopenharmony_ci			iface_no, altno);
9528c2ecf20Sopenharmony_ci		return NULL;
9538c2ecf20Sopenharmony_ci	}
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	/*
9568c2ecf20Sopenharmony_ci	 * Get number of channels and channel map through
9578c2ecf20Sopenharmony_ci	 * High Capability Cluster Descriptor
9588c2ecf20Sopenharmony_ci	 *
9598c2ecf20Sopenharmony_ci	 * First step: get High Capability header and
9608c2ecf20Sopenharmony_ci	 * read size of Cluster Descriptor
9618c2ecf20Sopenharmony_ci	 */
9628c2ecf20Sopenharmony_ci	err = snd_usb_ctl_msg(chip->dev,
9638c2ecf20Sopenharmony_ci			usb_rcvctrlpipe(chip->dev, 0),
9648c2ecf20Sopenharmony_ci			UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
9658c2ecf20Sopenharmony_ci			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
9668c2ecf20Sopenharmony_ci			cluster_id,
9678c2ecf20Sopenharmony_ci			snd_usb_ctrl_intf(chip),
9688c2ecf20Sopenharmony_ci			&hc_header, sizeof(hc_header));
9698c2ecf20Sopenharmony_ci	if (err < 0)
9708c2ecf20Sopenharmony_ci		return ERR_PTR(err);
9718c2ecf20Sopenharmony_ci	else if (err != sizeof(hc_header)) {
9728c2ecf20Sopenharmony_ci		dev_err(&dev->dev,
9738c2ecf20Sopenharmony_ci			"%u:%d : can't get High Capability descriptor\n",
9748c2ecf20Sopenharmony_ci			iface_no, altno);
9758c2ecf20Sopenharmony_ci		return ERR_PTR(-EIO);
9768c2ecf20Sopenharmony_ci	}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	/*
9798c2ecf20Sopenharmony_ci	 * Second step: allocate needed amount of memory
9808c2ecf20Sopenharmony_ci	 * and request Cluster Descriptor
9818c2ecf20Sopenharmony_ci	 */
9828c2ecf20Sopenharmony_ci	wLength = le16_to_cpu(hc_header.wLength);
9838c2ecf20Sopenharmony_ci	cluster = kzalloc(wLength, GFP_KERNEL);
9848c2ecf20Sopenharmony_ci	if (!cluster)
9858c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
9868c2ecf20Sopenharmony_ci	err = snd_usb_ctl_msg(chip->dev,
9878c2ecf20Sopenharmony_ci			usb_rcvctrlpipe(chip->dev, 0),
9888c2ecf20Sopenharmony_ci			UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
9898c2ecf20Sopenharmony_ci			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
9908c2ecf20Sopenharmony_ci			cluster_id,
9918c2ecf20Sopenharmony_ci			snd_usb_ctrl_intf(chip),
9928c2ecf20Sopenharmony_ci			cluster, wLength);
9938c2ecf20Sopenharmony_ci	if (err < 0) {
9948c2ecf20Sopenharmony_ci		kfree(cluster);
9958c2ecf20Sopenharmony_ci		return ERR_PTR(err);
9968c2ecf20Sopenharmony_ci	} else if (err != wLength) {
9978c2ecf20Sopenharmony_ci		dev_err(&dev->dev,
9988c2ecf20Sopenharmony_ci			"%u:%d : can't get Cluster Descriptor\n",
9998c2ecf20Sopenharmony_ci			iface_no, altno);
10008c2ecf20Sopenharmony_ci		kfree(cluster);
10018c2ecf20Sopenharmony_ci		return ERR_PTR(-EIO);
10028c2ecf20Sopenharmony_ci	}
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	num_channels = cluster->bNrChannels;
10058c2ecf20Sopenharmony_ci	chmap = convert_chmap_v3(cluster);
10068c2ecf20Sopenharmony_ci	kfree(cluster);
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	/*
10098c2ecf20Sopenharmony_ci	 * lookup the terminal associated to this interface
10108c2ecf20Sopenharmony_ci	 * to extract the clock
10118c2ecf20Sopenharmony_ci	 */
10128c2ecf20Sopenharmony_ci	input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
10138c2ecf20Sopenharmony_ci							    as->bTerminalLink,
10148c2ecf20Sopenharmony_ci							    UAC_VERSION_3);
10158c2ecf20Sopenharmony_ci	if (input_term) {
10168c2ecf20Sopenharmony_ci		clock = input_term->bCSourceID;
10178c2ecf20Sopenharmony_ci		goto found_clock;
10188c2ecf20Sopenharmony_ci	}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
10218c2ecf20Sopenharmony_ci							      as->bTerminalLink,
10228c2ecf20Sopenharmony_ci							      UAC_VERSION_3);
10238c2ecf20Sopenharmony_ci	if (output_term) {
10248c2ecf20Sopenharmony_ci		clock = output_term->bCSourceID;
10258c2ecf20Sopenharmony_ci		goto found_clock;
10268c2ecf20Sopenharmony_ci	}
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	dev_err(&dev->dev, "%u:%d : bogus bTerminalLink %d\n",
10298c2ecf20Sopenharmony_ci			iface_no, altno, as->bTerminalLink);
10308c2ecf20Sopenharmony_ci	kfree(chmap);
10318c2ecf20Sopenharmony_ci	return NULL;
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_cifound_clock:
10348c2ecf20Sopenharmony_ci	fp = audio_format_alloc_init(chip, alts, UAC_VERSION_3, iface_no,
10358c2ecf20Sopenharmony_ci				     altset_idx, altno, num_channels, clock);
10368c2ecf20Sopenharmony_ci	if (!fp) {
10378c2ecf20Sopenharmony_ci		kfree(chmap);
10388c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
10398c2ecf20Sopenharmony_ci	}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	fp->chmap = chmap;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
10448c2ecf20Sopenharmony_ci		fp->attributes = 0; /* No attributes */
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci		fp->fmt_type = UAC_FORMAT_TYPE_I;
10478c2ecf20Sopenharmony_ci		fp->formats = badd_formats;
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci		fp->nr_rates = 0;	/* SNDRV_PCM_RATE_CONTINUOUS */
10508c2ecf20Sopenharmony_ci		fp->rate_min = UAC3_BADD_SAMPLING_RATE;
10518c2ecf20Sopenharmony_ci		fp->rate_max = UAC3_BADD_SAMPLING_RATE;
10528c2ecf20Sopenharmony_ci		fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
10558c2ecf20Sopenharmony_ci		if (!pd) {
10568c2ecf20Sopenharmony_ci			audioformat_free(fp);
10578c2ecf20Sopenharmony_ci			return NULL;
10588c2ecf20Sopenharmony_ci		}
10598c2ecf20Sopenharmony_ci		pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
10608c2ecf20Sopenharmony_ci					UAC3_BADD_PD_ID10 : UAC3_BADD_PD_ID11;
10618c2ecf20Sopenharmony_ci		pd->pd_d1d0_rec = UAC3_BADD_PD_RECOVER_D1D0;
10628c2ecf20Sopenharmony_ci		pd->pd_d2d0_rec = UAC3_BADD_PD_RECOVER_D2D0;
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	} else {
10658c2ecf20Sopenharmony_ci		fp->attributes = parse_uac_endpoint_attributes(chip, alts,
10668c2ecf20Sopenharmony_ci							       UAC_VERSION_3,
10678c2ecf20Sopenharmony_ci							       iface_no);
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci		pd = snd_usb_find_power_domain(chip->ctrl_intf,
10708c2ecf20Sopenharmony_ci					       as->bTerminalLink);
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci		/* ok, let's parse further... */
10738c2ecf20Sopenharmony_ci		if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) {
10748c2ecf20Sopenharmony_ci			kfree(pd);
10758c2ecf20Sopenharmony_ci			audioformat_free(fp);
10768c2ecf20Sopenharmony_ci			return NULL;
10778c2ecf20Sopenharmony_ci		}
10788c2ecf20Sopenharmony_ci	}
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	if (pd)
10818c2ecf20Sopenharmony_ci		*pd_out = pd;
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	return fp;
10848c2ecf20Sopenharmony_ci}
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_cistatic int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
10878c2ecf20Sopenharmony_ci					   int iface_no,
10888c2ecf20Sopenharmony_ci					   bool *has_non_pcm, bool non_pcm)
10898c2ecf20Sopenharmony_ci{
10908c2ecf20Sopenharmony_ci	struct usb_device *dev;
10918c2ecf20Sopenharmony_ci	struct usb_interface *iface;
10928c2ecf20Sopenharmony_ci	struct usb_host_interface *alts;
10938c2ecf20Sopenharmony_ci	struct usb_interface_descriptor *altsd;
10948c2ecf20Sopenharmony_ci	int i, altno, err, stream;
10958c2ecf20Sopenharmony_ci	struct audioformat *fp = NULL;
10968c2ecf20Sopenharmony_ci	struct snd_usb_power_domain *pd = NULL;
10978c2ecf20Sopenharmony_ci	int num, protocol;
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	dev = chip->dev;
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	/* parse the interface's altsettings */
11028c2ecf20Sopenharmony_ci	iface = usb_ifnum_to_if(dev, iface_no);
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	num = iface->num_altsetting;
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci	/*
11078c2ecf20Sopenharmony_ci	 * Dallas DS4201 workaround: It presents 5 altsettings, but the last
11088c2ecf20Sopenharmony_ci	 * one misses syncpipe, and does not produce any sound.
11098c2ecf20Sopenharmony_ci	 */
11108c2ecf20Sopenharmony_ci	if (chip->usb_id == USB_ID(0x04fa, 0x4201) && num >= 4)
11118c2ecf20Sopenharmony_ci		num = 4;
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
11148c2ecf20Sopenharmony_ci		alts = &iface->altsetting[i];
11158c2ecf20Sopenharmony_ci		altsd = get_iface_desc(alts);
11168c2ecf20Sopenharmony_ci		protocol = altsd->bInterfaceProtocol;
11178c2ecf20Sopenharmony_ci		/* skip invalid one */
11188c2ecf20Sopenharmony_ci		if (((altsd->bInterfaceClass != USB_CLASS_AUDIO ||
11198c2ecf20Sopenharmony_ci		      (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
11208c2ecf20Sopenharmony_ci		       altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC)) &&
11218c2ecf20Sopenharmony_ci		     altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
11228c2ecf20Sopenharmony_ci		    altsd->bNumEndpoints < 1 ||
11238c2ecf20Sopenharmony_ci		    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
11248c2ecf20Sopenharmony_ci			continue;
11258c2ecf20Sopenharmony_ci		/* must be isochronous */
11268c2ecf20Sopenharmony_ci		if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
11278c2ecf20Sopenharmony_ci		    USB_ENDPOINT_XFER_ISOC)
11288c2ecf20Sopenharmony_ci			continue;
11298c2ecf20Sopenharmony_ci		/* check direction */
11308c2ecf20Sopenharmony_ci		stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
11318c2ecf20Sopenharmony_ci			SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
11328c2ecf20Sopenharmony_ci		altno = altsd->bAlternateSetting;
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci		if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
11358c2ecf20Sopenharmony_ci			continue;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci		/*
11388c2ecf20Sopenharmony_ci		 * Roland audio streaming interfaces are marked with protocols
11398c2ecf20Sopenharmony_ci		 * 0/1/2, but are UAC 1 compatible.
11408c2ecf20Sopenharmony_ci		 */
11418c2ecf20Sopenharmony_ci		if (USB_ID_VENDOR(chip->usb_id) == 0x0582 &&
11428c2ecf20Sopenharmony_ci		    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
11438c2ecf20Sopenharmony_ci		    protocol <= 2)
11448c2ecf20Sopenharmony_ci			protocol = UAC_VERSION_1;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci		switch (protocol) {
11478c2ecf20Sopenharmony_ci		default:
11488c2ecf20Sopenharmony_ci			dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n",
11498c2ecf20Sopenharmony_ci				iface_no, altno, protocol);
11508c2ecf20Sopenharmony_ci			protocol = UAC_VERSION_1;
11518c2ecf20Sopenharmony_ci			fallthrough;
11528c2ecf20Sopenharmony_ci		case UAC_VERSION_1:
11538c2ecf20Sopenharmony_ci		case UAC_VERSION_2: {
11548c2ecf20Sopenharmony_ci			int bm_quirk = 0;
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci			/*
11578c2ecf20Sopenharmony_ci			 * Blue Microphones workaround: The last altsetting is
11588c2ecf20Sopenharmony_ci			 * identical with the previous one, except for a larger
11598c2ecf20Sopenharmony_ci			 * packet size, but is actually a mislabeled two-channel
11608c2ecf20Sopenharmony_ci			 * setting; ignore it.
11618c2ecf20Sopenharmony_ci			 *
11628c2ecf20Sopenharmony_ci			 * Part 1: prepare quirk flag
11638c2ecf20Sopenharmony_ci			 */
11648c2ecf20Sopenharmony_ci			if (altno == 2 && num == 3 &&
11658c2ecf20Sopenharmony_ci			    fp && fp->altsetting == 1 && fp->channels == 1 &&
11668c2ecf20Sopenharmony_ci			    fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
11678c2ecf20Sopenharmony_ci			    protocol == UAC_VERSION_1 &&
11688c2ecf20Sopenharmony_ci			    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
11698c2ecf20Sopenharmony_ci							fp->maxpacksize * 2)
11708c2ecf20Sopenharmony_ci				bm_quirk = 1;
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci			fp = snd_usb_get_audioformat_uac12(chip, alts, protocol,
11738c2ecf20Sopenharmony_ci							   iface_no, i, altno,
11748c2ecf20Sopenharmony_ci							   stream, bm_quirk);
11758c2ecf20Sopenharmony_ci			break;
11768c2ecf20Sopenharmony_ci		}
11778c2ecf20Sopenharmony_ci		case UAC_VERSION_3:
11788c2ecf20Sopenharmony_ci			fp = snd_usb_get_audioformat_uac3(chip, alts, &pd,
11798c2ecf20Sopenharmony_ci						iface_no, i, altno, stream);
11808c2ecf20Sopenharmony_ci			break;
11818c2ecf20Sopenharmony_ci		}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci		if (!fp)
11848c2ecf20Sopenharmony_ci			continue;
11858c2ecf20Sopenharmony_ci		else if (IS_ERR(fp))
11868c2ecf20Sopenharmony_ci			return PTR_ERR(fp);
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci		if (fp->fmt_type != UAC_FORMAT_TYPE_I)
11898c2ecf20Sopenharmony_ci			*has_non_pcm = true;
11908c2ecf20Sopenharmony_ci		if ((fp->fmt_type == UAC_FORMAT_TYPE_I) == non_pcm) {
11918c2ecf20Sopenharmony_ci			audioformat_free(fp);
11928c2ecf20Sopenharmony_ci			kfree(pd);
11938c2ecf20Sopenharmony_ci			fp = NULL;
11948c2ecf20Sopenharmony_ci			pd = NULL;
11958c2ecf20Sopenharmony_ci			continue;
11968c2ecf20Sopenharmony_ci		}
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci		dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
11998c2ecf20Sopenharmony_ci		if (protocol == UAC_VERSION_3)
12008c2ecf20Sopenharmony_ci			err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd);
12018c2ecf20Sopenharmony_ci		else
12028c2ecf20Sopenharmony_ci			err = snd_usb_add_audio_stream(chip, stream, fp);
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci		if (err < 0) {
12058c2ecf20Sopenharmony_ci			audioformat_free(fp);
12068c2ecf20Sopenharmony_ci			kfree(pd);
12078c2ecf20Sopenharmony_ci			return err;
12088c2ecf20Sopenharmony_ci		}
12098c2ecf20Sopenharmony_ci		/* try to set the interface... */
12108c2ecf20Sopenharmony_ci		usb_set_interface(chip->dev, iface_no, altno);
12118c2ecf20Sopenharmony_ci		snd_usb_init_pitch(chip, iface_no, alts, fp);
12128c2ecf20Sopenharmony_ci		snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
12138c2ecf20Sopenharmony_ci	}
12148c2ecf20Sopenharmony_ci	return 0;
12158c2ecf20Sopenharmony_ci}
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ciint snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
12188c2ecf20Sopenharmony_ci{
12198c2ecf20Sopenharmony_ci	int err;
12208c2ecf20Sopenharmony_ci	bool has_non_pcm = false;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	/* parse PCM formats */
12238c2ecf20Sopenharmony_ci	err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, false);
12248c2ecf20Sopenharmony_ci	if (err < 0)
12258c2ecf20Sopenharmony_ci		return err;
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	if (has_non_pcm) {
12288c2ecf20Sopenharmony_ci		/* parse non-PCM formats */
12298c2ecf20Sopenharmony_ci		err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, true);
12308c2ecf20Sopenharmony_ci		if (err < 0)
12318c2ecf20Sopenharmony_ci			return err;
12328c2ecf20Sopenharmony_ci	}
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	return 0;
12358c2ecf20Sopenharmony_ci}
12368c2ecf20Sopenharmony_ci
1237