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