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