aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRuslan Bilovol <ruslan.bilovol@gmail.com>2018-05-03 21:24:04 -0400
committerTakashi Iwai <tiwai@suse.de>2018-05-13 02:54:35 -0400
commit17156f23e93c0f59e06dd2aaffd06221341caaee (patch)
treef7eac9dcff74c160bc43f1a032b5d15647fbe1d8
parent10aa7cad37d330dbff6a285af56dc4a7153a8f00 (diff)
ALSA: usb: add UAC3 BADD profiles support
Recently released USB Audio Class 3.0 specification contains BADD (Basic Audio Device Definition) document which describes pre-defined UAC3 configurations. BADD support is mandatory for UAC3 devices, it should be implemented as a separate USB device configuration. As per BADD document, class-specific descriptors shall not be included in the Device’s Configuration descriptor ("inferred"), but host can guess them from BADD profile number, number of endpoints and their max packed sizes. This patch adds support of all BADD profiles from the spec Signed-off-by: Ruslan Bilovol <ruslan.bilovol@gmail.com> Tested-by: Jorge Sanjuan <jorge.sanjuan@codethink.co.uk> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/card.c14
-rw-r--r--sound/usb/clock.c9
-rw-r--r--sound/usb/mixer.c327
-rw-r--r--sound/usb/mixer_maps.c65
-rw-r--r--sound/usb/stream.c83
-rw-r--r--sound/usb/usbaudio.h2
6 files changed, 459 insertions, 41 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 0d7a5d70634e..f6c3c1cd591e 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -307,6 +307,20 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
307 return -EINVAL; 307 return -EINVAL;
308 } 308 }
309 309
310 if (protocol == UAC_VERSION_3) {
311 int badd = assoc->bFunctionSubClass;
312
313 if (badd != UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0 &&
314 (badd < UAC3_FUNCTION_SUBCLASS_GENERIC_IO ||
315 badd > UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE)) {
316 dev_err(&dev->dev,
317 "Unsupported UAC3 BADD profile\n");
318 return -EINVAL;
319 }
320
321 chip->badd_profile = badd;
322 }
323
310 for (i = 0; i < assoc->bInterfaceCount; i++) { 324 for (i = 0; i < assoc->bInterfaceCount; i++) {
311 int intf = assoc->bFirstInterface + i; 325 int intf = assoc->bFirstInterface + i;
312 326
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 0b030d8fe3fa..17673f37fcc8 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -587,8 +587,15 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
587 default: 587 default:
588 return set_sample_rate_v1(chip, iface, alts, fmt, rate); 588 return set_sample_rate_v1(chip, iface, alts, fmt, rate);
589 589
590 case UAC_VERSION_2:
591 case UAC_VERSION_3: 590 case UAC_VERSION_3:
591 if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
592 if (rate != UAC3_BADD_SAMPLING_RATE)
593 return -ENXIO;
594 else
595 return 0;
596 }
597 /* fall through */
598 case UAC_VERSION_2:
592 return set_sample_rate_v2v3(chip, iface, alts, fmt, rate); 599 return set_sample_rate_v2v3(chip, iface, alts, fmt, rate);
593 } 600 }
594} 601}
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 76417943ff85..4987982250d5 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -112,14 +112,12 @@ enum {
112#include "mixer_maps.c" 112#include "mixer_maps.c"
113 113
114static const struct usbmix_name_map * 114static const struct usbmix_name_map *
115find_map(struct mixer_build *state, int unitid, int control) 115find_map(const struct usbmix_name_map *p, int unitid, int control)
116{ 116{
117 const struct usbmix_name_map *p = state->map;
118
119 if (!p) 117 if (!p)
120 return NULL; 118 return NULL;
121 119
122 for (p = state->map; p->id; p++) { 120 for (; p->id; p++) {
123 if (p->id == unitid && 121 if (p->id == unitid &&
124 (!control || !p->control || control == p->control)) 122 (!control || !p->control || control == p->control))
125 return p; 123 return p;
@@ -1333,16 +1331,16 @@ static struct usb_feature_control_info *get_feature_control_info(int control)
1333 return NULL; 1331 return NULL;
1334} 1332}
1335 1333
1336static void build_feature_ctl(struct mixer_build *state, void *raw_desc, 1334static void __build_feature_ctl(struct usb_mixer_interface *mixer,
1337 unsigned int ctl_mask, int control, 1335 const struct usbmix_name_map *imap,
1338 struct usb_audio_term *iterm, int unitid, 1336 unsigned int ctl_mask, int control,
1339 int readonly_mask) 1337 struct usb_audio_term *iterm,
1338 struct usb_audio_term *oterm,
1339 int unitid, int nameid, int readonly_mask)
1340{ 1340{
1341 struct uac_feature_unit_descriptor *desc = raw_desc;
1342 struct usb_feature_control_info *ctl_info; 1341 struct usb_feature_control_info *ctl_info;
1343 unsigned int len = 0; 1342 unsigned int len = 0;
1344 int mapped_name = 0; 1343 int mapped_name = 0;
1345 int nameid = uac_feature_unit_iFeature(desc);
1346 struct snd_kcontrol *kctl; 1344 struct snd_kcontrol *kctl;
1347 struct usb_mixer_elem_info *cval; 1345 struct usb_mixer_elem_info *cval;
1348 const struct usbmix_name_map *map; 1346 const struct usbmix_name_map *map;
@@ -1353,14 +1351,14 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1353 return; 1351 return;
1354 } 1352 }
1355 1353
1356 map = find_map(state, unitid, control); 1354 map = find_map(imap, unitid, control);
1357 if (check_ignored_ctl(map)) 1355 if (check_ignored_ctl(map))
1358 return; 1356 return;
1359 1357
1360 cval = kzalloc(sizeof(*cval), GFP_KERNEL); 1358 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
1361 if (!cval) 1359 if (!cval)
1362 return; 1360 return;
1363 snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid); 1361 snd_usb_mixer_elem_init_std(&cval->head, mixer, unitid);
1364 cval->control = control; 1362 cval->control = control;
1365 cval->cmask = ctl_mask; 1363 cval->cmask = ctl_mask;
1366 1364
@@ -1369,7 +1367,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1369 kfree(cval); 1367 kfree(cval);
1370 return; 1368 return;
1371 } 1369 }
1372 if (state->mixer->protocol == UAC_VERSION_1) 1370 if (mixer->protocol == UAC_VERSION_1)
1373 cval->val_type = ctl_info->type; 1371 cval->val_type = ctl_info->type;
1374 else /* UAC_VERSION_2 */ 1372 else /* UAC_VERSION_2 */
1375 cval->val_type = ctl_info->type_uac2 >= 0 ? 1373 cval->val_type = ctl_info->type_uac2 >= 0 ?
@@ -1398,7 +1396,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1398 kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); 1396 kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
1399 1397
1400 if (!kctl) { 1398 if (!kctl) {
1401 usb_audio_err(state->chip, "cannot malloc kcontrol\n"); 1399 usb_audio_err(mixer->chip, "cannot malloc kcontrol\n");
1402 kfree(cval); 1400 kfree(cval);
1403 return; 1401 return;
1404 } 1402 }
@@ -1407,7 +1405,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1407 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); 1405 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
1408 mapped_name = len != 0; 1406 mapped_name = len != 0;
1409 if (!len && nameid) 1407 if (!len && nameid)
1410 len = snd_usb_copy_string_desc(state->chip, nameid, 1408 len = snd_usb_copy_string_desc(mixer->chip, nameid,
1411 kctl->id.name, sizeof(kctl->id.name)); 1409 kctl->id.name, sizeof(kctl->id.name));
1412 1410
1413 switch (control) { 1411 switch (control) {
@@ -1422,10 +1420,12 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1422 * - otherwise, anonymous name. 1420 * - otherwise, anonymous name.
1423 */ 1421 */
1424 if (!len) { 1422 if (!len) {
1425 len = get_term_name(state->chip, iterm, kctl->id.name, 1423 if (iterm)
1426 sizeof(kctl->id.name), 1); 1424 len = get_term_name(mixer->chip, iterm,
1427 if (!len) 1425 kctl->id.name,
1428 len = get_term_name(state->chip, &state->oterm, 1426 sizeof(kctl->id.name), 1);
1427 if (!len && oterm)
1428 len = get_term_name(mixer->chip, oterm,
1429 kctl->id.name, 1429 kctl->id.name,
1430 sizeof(kctl->id.name), 1); 1430 sizeof(kctl->id.name), 1);
1431 if (!len) 1431 if (!len)
@@ -1434,15 +1434,15 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1434 } 1434 }
1435 1435
1436 if (!mapped_name) 1436 if (!mapped_name)
1437 check_no_speaker_on_headset(kctl, state->mixer->chip->card); 1437 check_no_speaker_on_headset(kctl, mixer->chip->card);
1438 1438
1439 /* 1439 /*
1440 * determine the stream direction: 1440 * determine the stream direction:
1441 * if the connected output is USB stream, then it's likely a 1441 * if the connected output is USB stream, then it's likely a
1442 * capture stream. otherwise it should be playback (hopefully :) 1442 * capture stream. otherwise it should be playback (hopefully :)
1443 */ 1443 */
1444 if (!mapped_name && !(state->oterm.type >> 16)) { 1444 if (!mapped_name && oterm && !(oterm->type >> 16)) {
1445 if ((state->oterm.type & 0xff00) == 0x0100) 1445 if ((oterm->type & 0xff00) == 0x0100)
1446 append_ctl_name(kctl, " Capture"); 1446 append_ctl_name(kctl, " Capture");
1447 else 1447 else
1448 append_ctl_name(kctl, " Playback"); 1448 append_ctl_name(kctl, " Playback");
@@ -1470,7 +1470,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1470 } 1470 }
1471 } 1471 }
1472 1472
1473 snd_usb_mixer_fu_apply_quirk(state->mixer, cval, unitid, kctl); 1473 snd_usb_mixer_fu_apply_quirk(mixer, cval, unitid, kctl);
1474 1474
1475 range = (cval->max - cval->min) / cval->res; 1475 range = (cval->max - cval->min) / cval->res;
1476 /* 1476 /*
@@ -1479,21 +1479,41 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1479 * devices. It will definitively catch all buggy Logitech devices. 1479 * devices. It will definitively catch all buggy Logitech devices.
1480 */ 1480 */
1481 if (range > 384) { 1481 if (range > 384) {
1482 usb_audio_warn(state->chip, 1482 usb_audio_warn(mixer->chip,
1483 "Warning! Unlikely big volume range (=%u), cval->res is probably wrong.", 1483 "Warning! Unlikely big volume range (=%u), cval->res is probably wrong.",
1484 range); 1484 range);
1485 usb_audio_warn(state->chip, 1485 usb_audio_warn(mixer->chip,
1486 "[%d] FU [%s] ch = %d, val = %d/%d/%d", 1486 "[%d] FU [%s] ch = %d, val = %d/%d/%d",
1487 cval->head.id, kctl->id.name, cval->channels, 1487 cval->head.id, kctl->id.name, cval->channels,
1488 cval->min, cval->max, cval->res); 1488 cval->min, cval->max, cval->res);
1489 } 1489 }
1490 1490
1491 usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", 1491 usb_audio_dbg(mixer->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
1492 cval->head.id, kctl->id.name, cval->channels, 1492 cval->head.id, kctl->id.name, cval->channels,
1493 cval->min, cval->max, cval->res); 1493 cval->min, cval->max, cval->res);
1494 snd_usb_mixer_add_control(&cval->head, kctl); 1494 snd_usb_mixer_add_control(&cval->head, kctl);
1495} 1495}
1496 1496
1497static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1498 unsigned int ctl_mask, int control,
1499 struct usb_audio_term *iterm, int unitid,
1500 int readonly_mask)
1501{
1502 struct uac_feature_unit_descriptor *desc = raw_desc;
1503 int nameid = uac_feature_unit_iFeature(desc);
1504
1505 __build_feature_ctl(state->mixer, state->map, ctl_mask, control,
1506 iterm, &state->oterm, unitid, nameid, readonly_mask);
1507}
1508
1509static void build_feature_ctl_badd(struct usb_mixer_interface *mixer,
1510 unsigned int ctl_mask, int control, int unitid,
1511 const struct usbmix_name_map *badd_map)
1512{
1513 __build_feature_ctl(mixer, badd_map, ctl_mask, control,
1514 NULL, NULL, unitid, 0, 0);
1515}
1516
1497static void get_connector_control_name(struct mixer_build *state, 1517static void get_connector_control_name(struct mixer_build *state,
1498 struct usb_audio_term *term, 1518 struct usb_audio_term *term,
1499 bool is_input, char *name, int name_size) 1519 bool is_input, char *name, int name_size)
@@ -1807,7 +1827,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
1807 struct snd_kcontrol *kctl; 1827 struct snd_kcontrol *kctl;
1808 const struct usbmix_name_map *map; 1828 const struct usbmix_name_map *map;
1809 1829
1810 map = find_map(state, unitid, 0); 1830 map = find_map(state->map, unitid, 0);
1811 if (check_ignored_ctl(map)) 1831 if (check_ignored_ctl(map))
1812 return; 1832 return;
1813 1833
@@ -2106,7 +2126,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
2106 2126
2107 if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1)))) 2127 if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1))))
2108 continue; 2128 continue;
2109 map = find_map(state, unitid, valinfo->control); 2129 map = find_map(state->map, unitid, valinfo->control);
2110 if (check_ignored_ctl(map)) 2130 if (check_ignored_ctl(map))
2111 continue; 2131 continue;
2112 cval = kzalloc(sizeof(*cval), GFP_KERNEL); 2132 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
@@ -2310,7 +2330,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
2310 if (desc->bNrInPins == 1) /* only one ? nonsense! */ 2330 if (desc->bNrInPins == 1) /* only one ? nonsense! */
2311 return 0; 2331 return 0;
2312 2332
2313 map = find_map(state, unitid, 0); 2333 map = find_map(state->map, unitid, 0);
2314 if (check_ignored_ctl(map)) 2334 if (check_ignored_ctl(map))
2315 return 0; 2335 return 0;
2316 2336
@@ -2497,6 +2517,246 @@ static int snd_usb_mixer_dev_free(struct snd_device *device)
2497 return 0; 2517 return 0;
2498} 2518}
2499 2519
2520/* UAC3 predefined channels configuration */
2521struct uac3_badd_profile {
2522 int subclass;
2523 const char *name;
2524 int c_chmask; /* capture channels mask */
2525 int p_chmask; /* playback channels mask */
2526 int st_chmask; /* side tone mixing channel mask */
2527};
2528
2529static struct uac3_badd_profile uac3_badd_profiles[] = {
2530 {
2531 /*
2532 * BAIF, BAOF or combination of both
2533 * IN: Mono or Stereo cfg, Mono alt possible
2534 * OUT: Mono or Stereo cfg, Mono alt possible
2535 */
2536 .subclass = UAC3_FUNCTION_SUBCLASS_GENERIC_IO,
2537 .name = "GENERIC IO",
2538 .c_chmask = -1, /* dynamic channels */
2539 .p_chmask = -1, /* dynamic channels */
2540 },
2541 {
2542 /* BAOF; Stereo only cfg, Mono alt possible */
2543 .subclass = UAC3_FUNCTION_SUBCLASS_HEADPHONE,
2544 .name = "HEADPHONE",
2545 .p_chmask = 3,
2546 },
2547 {
2548 /* BAOF; Mono or Stereo cfg, Mono alt possible */
2549 .subclass = UAC3_FUNCTION_SUBCLASS_SPEAKER,
2550 .name = "SPEAKER",
2551 .p_chmask = -1, /* dynamic channels */
2552 },
2553 {
2554 /* BAIF; Mono or Stereo cfg, Mono alt possible */
2555 .subclass = UAC3_FUNCTION_SUBCLASS_MICROPHONE,
2556 .name = "MICROPHONE",
2557 .c_chmask = -1, /* dynamic channels */
2558 },
2559 {
2560 /*
2561 * BAIOF topology
2562 * IN: Mono only
2563 * OUT: Mono or Stereo cfg, Mono alt possible
2564 */
2565 .subclass = UAC3_FUNCTION_SUBCLASS_HEADSET,
2566 .name = "HEADSET",
2567 .c_chmask = 1,
2568 .p_chmask = -1, /* dynamic channels */
2569 .st_chmask = 1,
2570 },
2571 {
2572 /* BAIOF; IN: Mono only; OUT: Stereo only, Mono alt possible */
2573 .subclass = UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER,
2574 .name = "HEADSET ADAPTER",
2575 .c_chmask = 1,
2576 .p_chmask = 3,
2577 .st_chmask = 1,
2578 },
2579 {
2580 /* BAIF + BAOF; IN: Mono only; OUT: Mono only */
2581 .subclass = UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE,
2582 .name = "SPEAKERPHONE",
2583 .c_chmask = 1,
2584 .p_chmask = 1,
2585 },
2586 { 0 } /* terminator */
2587};
2588
2589static bool uac3_badd_func_has_valid_channels(struct usb_mixer_interface *mixer,
2590 struct uac3_badd_profile *f,
2591 int c_chmask, int p_chmask)
2592{
2593 /*
2594 * If both playback/capture channels are dynamic, make sure
2595 * at least one channel is present
2596 */
2597 if (f->c_chmask < 0 && f->p_chmask < 0) {
2598 if (!c_chmask && !p_chmask) {
2599 usb_audio_warn(mixer->chip, "BAAD %s: no channels?",
2600 f->name);
2601 return false;
2602 }
2603 return true;
2604 }
2605
2606 if ((f->c_chmask < 0 && !c_chmask) ||
2607 (f->c_chmask >= 0 && f->c_chmask != c_chmask)) {
2608 usb_audio_warn(mixer->chip, "BAAD %s c_chmask mismatch",
2609 f->name);
2610 return false;
2611 }
2612 if ((f->p_chmask < 0 && !p_chmask) ||
2613 (f->p_chmask >= 0 && f->p_chmask != p_chmask)) {
2614 usb_audio_warn(mixer->chip, "BAAD %s p_chmask mismatch",
2615 f->name);
2616 return false;
2617 }
2618 return true;
2619}
2620
2621/*
2622 * create mixer controls for UAC3 BADD profiles
2623 *
2624 * UAC3 BADD device doesn't contain CS descriptors thus we will guess everything
2625 *
2626 * BADD device may contain Mixer Unit, which doesn't have any controls, skip it
2627 */
2628static int snd_usb_mixer_controls_badd(struct usb_mixer_interface *mixer,
2629 int ctrlif)
2630{
2631 struct usb_device *dev = mixer->chip->dev;
2632 struct usb_interface_assoc_descriptor *assoc;
2633 int badd_profile = mixer->chip->badd_profile;
2634 struct uac3_badd_profile *f;
2635 const struct usbmix_ctl_map *map;
2636 int p_chmask = 0, c_chmask = 0, st_chmask = 0;
2637 int i;
2638
2639 assoc = usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
2640
2641 /* Detect BADD capture/playback channels from AS EP descriptors */
2642 for (i = 0; i < assoc->bInterfaceCount; i++) {
2643 int intf = assoc->bFirstInterface + i;
2644
2645 struct usb_interface *iface;
2646 struct usb_host_interface *alts;
2647 struct usb_interface_descriptor *altsd;
2648 unsigned int maxpacksize;
2649 char dir_in;
2650 int chmask, num;
2651
2652 if (intf == ctrlif)
2653 continue;
2654
2655 iface = usb_ifnum_to_if(dev, intf);
2656 num = iface->num_altsetting;
2657
2658 if (num < 2)
2659 return -EINVAL;
2660
2661 /*
2662 * The number of Channels in an AudioStreaming interface
2663 * and the audio sample bit resolution (16 bits or 24
2664 * bits) can be derived from the wMaxPacketSize field in
2665 * the Standard AS Audio Data Endpoint descriptor in
2666 * Alternate Setting 1
2667 */
2668 alts = &iface->altsetting[1];
2669 altsd = get_iface_desc(alts);
2670
2671 if (altsd->bNumEndpoints < 1)
2672 return -EINVAL;
2673
2674 /* check direction */
2675 dir_in = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN);
2676 maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
2677
2678 switch (maxpacksize) {
2679 default:
2680 usb_audio_err(mixer->chip,
2681 "incorrect wMaxPacketSize 0x%x for BADD profile\n",
2682 maxpacksize);
2683 return -EINVAL;
2684 case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16:
2685 case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16:
2686 case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24:
2687 case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24:
2688 chmask = 1;
2689 break;
2690 case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16:
2691 case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16:
2692 case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24:
2693 case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24:
2694 chmask = 3;
2695 break;
2696 }
2697
2698 if (dir_in)
2699 c_chmask = chmask;
2700 else
2701 p_chmask = chmask;
2702 }
2703
2704 usb_audio_dbg(mixer->chip,
2705 "UAC3 BADD profile 0x%x: detected c_chmask=%d p_chmask=%d\n",
2706 badd_profile, c_chmask, p_chmask);
2707
2708 /* check the mapping table */
2709 for (map = uac3_badd_usbmix_ctl_maps; map->id; map++) {
2710 if (map->id == badd_profile)
2711 break;
2712 }
2713
2714 if (!map->id)
2715 return -EINVAL;
2716
2717 for (f = uac3_badd_profiles; f->name; f++) {
2718 if (badd_profile == f->subclass)
2719 break;
2720 }
2721 if (!f->name)
2722 return -EINVAL;
2723 if (!uac3_badd_func_has_valid_channels(mixer, f, c_chmask, p_chmask))
2724 return -EINVAL;
2725 st_chmask = f->st_chmask;
2726
2727 /* Playback */
2728 if (p_chmask) {
2729 /* Master channel, always writable */
2730 build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE,
2731 UAC3_BADD_FU_ID2, map->map);
2732 /* Mono/Stereo volume channels, always writable */
2733 build_feature_ctl_badd(mixer, p_chmask, UAC_FU_VOLUME,
2734 UAC3_BADD_FU_ID2, map->map);
2735 }
2736
2737 /* Capture */
2738 if (c_chmask) {
2739 /* Master channel, always writable */
2740 build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE,
2741 UAC3_BADD_FU_ID5, map->map);
2742 /* Mono/Stereo volume channels, always writable */
2743 build_feature_ctl_badd(mixer, c_chmask, UAC_FU_VOLUME,
2744 UAC3_BADD_FU_ID5, map->map);
2745 }
2746
2747 /* Side tone-mixing */
2748 if (st_chmask) {
2749 /* Master channel, always writable */
2750 build_feature_ctl_badd(mixer, 0, UAC_FU_MUTE,
2751 UAC3_BADD_FU_ID7, map->map);
2752 /* Mono volume channel, always writable */
2753 build_feature_ctl_badd(mixer, 1, UAC_FU_VOLUME,
2754 UAC3_BADD_FU_ID7, map->map);
2755 }
2756
2757 return 0;
2758}
2759
2500/* 2760/*
2501 * create mixer controls 2761 * create mixer controls
2502 * 2762 *
@@ -2882,9 +3142,14 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
2882 break; 3142 break;
2883 } 3143 }
2884 3144
2885 if ((err = snd_usb_mixer_controls(mixer)) < 0 || 3145 if (mixer->protocol == UAC_VERSION_3 &&
2886 (err = snd_usb_mixer_status_create(mixer)) < 0) 3146 chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
3147 if ((err = snd_usb_mixer_controls_badd(mixer, ctrlif)) < 0)
3148 goto _error;
3149 } else if ((err = snd_usb_mixer_controls(mixer)) < 0 ||
3150 (err = snd_usb_mixer_status_create(mixer)) < 0) {
2887 goto _error; 3151 goto _error;
3152 }
2888 err = create_keep_iface_ctl(mixer); 3153 err = create_keep_iface_ctl(mixer);
2889 if (err < 0) 3154 if (err < 0)
2890 goto _error; 3155 goto _error;
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index eaa03acd4686..71069e110897 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -485,3 +485,68 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
485 { 0 } /* terminator */ 485 { 0 } /* terminator */
486}; 486};
487 487
488/*
489 * Control map entries for UAC3 BADD profiles
490 */
491
492static struct usbmix_name_map uac3_badd_generic_io_map[] = {
493 { UAC3_BADD_FU_ID2, "Generic Out Playback" },
494 { UAC3_BADD_FU_ID5, "Generic In Capture" },
495 { 0 } /* terminator */
496};
497static struct usbmix_name_map uac3_badd_headphone_map[] = {
498 { UAC3_BADD_FU_ID2, "Headphone Playback" },
499 { 0 } /* terminator */
500};
501static struct usbmix_name_map uac3_badd_speaker_map[] = {
502 { UAC3_BADD_FU_ID2, "Speaker Playback" },
503 { 0 } /* terminator */
504};
505static struct usbmix_name_map uac3_badd_microphone_map[] = {
506 { UAC3_BADD_FU_ID5, "Mic Capture" },
507 { 0 } /* terminator */
508};
509/* Covers also 'headset adapter' profile */
510static struct usbmix_name_map uac3_badd_headset_map[] = {
511 { UAC3_BADD_FU_ID2, "Headset Playback" },
512 { UAC3_BADD_FU_ID5, "Headset Capture" },
513 { UAC3_BADD_FU_ID7, "Sidetone Mixing" },
514 { 0 } /* terminator */
515};
516static struct usbmix_name_map uac3_badd_speakerphone_map[] = {
517 { UAC3_BADD_FU_ID2, "Speaker Playback" },
518 { UAC3_BADD_FU_ID5, "Mic Capture" },
519 { 0 } /* terminator */
520};
521
522static struct usbmix_ctl_map uac3_badd_usbmix_ctl_maps[] = {
523 {
524 .id = UAC3_FUNCTION_SUBCLASS_GENERIC_IO,
525 .map = uac3_badd_generic_io_map,
526 },
527 {
528 .id = UAC3_FUNCTION_SUBCLASS_HEADPHONE,
529 .map = uac3_badd_headphone_map,
530 },
531 {
532 .id = UAC3_FUNCTION_SUBCLASS_SPEAKER,
533 .map = uac3_badd_speaker_map,
534 },
535 {
536 .id = UAC3_FUNCTION_SUBCLASS_MICROPHONE,
537 .map = uac3_badd_microphone_map,
538 },
539 {
540 .id = UAC3_FUNCTION_SUBCLASS_HEADSET,
541 .map = uac3_badd_headset_map,
542 },
543 {
544 .id = UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER,
545 .map = uac3_badd_headset_map,
546 },
547 {
548 .id = UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE,
549 .map = uac3_badd_speakerphone_map,
550 },
551 { 0 } /* terminator */
552};
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 764be07474a8..de8bbb304199 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -817,15 +817,67 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
817 struct uac3_input_terminal_descriptor *input_term; 817 struct uac3_input_terminal_descriptor *input_term;
818 struct uac3_output_terminal_descriptor *output_term; 818 struct uac3_output_terminal_descriptor *output_term;
819 struct uac3_cluster_header_descriptor *cluster; 819 struct uac3_cluster_header_descriptor *cluster;
820 struct uac3_as_header_descriptor *as; 820 struct uac3_as_header_descriptor *as = NULL;
821 struct uac3_hc_descriptor_header hc_header; 821 struct uac3_hc_descriptor_header hc_header;
822 struct snd_pcm_chmap_elem *chmap; 822 struct snd_pcm_chmap_elem *chmap;
823 unsigned char badd_profile;
824 u64 badd_formats = 0;
823 unsigned int num_channels; 825 unsigned int num_channels;
824 struct audioformat *fp; 826 struct audioformat *fp;
825 u16 cluster_id, wLength; 827 u16 cluster_id, wLength;
826 int clock = 0; 828 int clock = 0;
827 int err; 829 int err;
828 830
831 badd_profile = chip->badd_profile;
832
833 if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
834 unsigned int maxpacksize =
835 le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
836
837 switch (maxpacksize) {
838 default:
839 dev_err(&dev->dev,
840 "%u:%d : incorrect wMaxPacketSize for BADD profile\n",
841 iface_no, altno);
842 return NULL;
843 case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16:
844 case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16:
845 badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
846 num_channels = 1;
847 break;
848 case UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24:
849 case UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24:
850 badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
851 num_channels = 1;
852 break;
853 case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16:
854 case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16:
855 badd_formats = SNDRV_PCM_FMTBIT_S16_LE;
856 num_channels = 2;
857 break;
858 case UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24:
859 case UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24:
860 badd_formats = SNDRV_PCM_FMTBIT_S24_3LE;
861 num_channels = 2;
862 break;
863 }
864
865 chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
866 if (!chmap)
867 return ERR_PTR(-ENOMEM);
868
869 if (num_channels == 1) {
870 chmap->map[0] = SNDRV_CHMAP_MONO;
871 } else {
872 chmap->map[0] = SNDRV_CHMAP_FL;
873 chmap->map[1] = SNDRV_CHMAP_FR;
874 }
875
876 chmap->channels = num_channels;
877 clock = UAC3_BADD_CS_ID9;
878 goto found_clock;
879 }
880
829 as = snd_usb_find_csint_desc(alts->extra, alts->extralen, 881 as = snd_usb_find_csint_desc(alts->extra, alts->extralen,
830 NULL, UAC_AS_GENERAL); 882 NULL, UAC_AS_GENERAL);
831 if (!as) { 883 if (!as) {
@@ -931,16 +983,29 @@ found_clock:
931 if (!fp) 983 if (!fp)
932 return ERR_PTR(-ENOMEM); 984 return ERR_PTR(-ENOMEM);
933 985
934 fp->attributes = parse_uac_endpoint_attributes(chip, alts,
935 UAC_VERSION_3,
936 iface_no);
937 fp->chmap = chmap; 986 fp->chmap = chmap;
938 987
939 /* ok, let's parse further... */ 988 if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
940 if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { 989 fp->attributes = 0; /* No attributes */
941 kfree(fp->rate_table); 990
942 kfree(fp); 991 fp->fmt_type = UAC_FORMAT_TYPE_I;
943 return NULL; 992 fp->formats = badd_formats;
993
994 fp->nr_rates = 0; /* SNDRV_PCM_RATE_CONTINUOUS */
995 fp->rate_min = UAC3_BADD_SAMPLING_RATE;
996 fp->rate_max = UAC3_BADD_SAMPLING_RATE;
997 fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
998
999 } else {
1000 fp->attributes = parse_uac_endpoint_attributes(chip, alts,
1001 UAC_VERSION_3,
1002 iface_no);
1003 /* ok, let's parse further... */
1004 if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) {
1005 kfree(fp->rate_table);
1006 kfree(fp);
1007 return NULL;
1008 }
944 } 1009 }
945 1010
946 return fp; 1011 return fp;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1cb6b3e9483c..7b28cbde22c0 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -49,6 +49,8 @@ struct snd_usb_audio {
49 int num_suspended_intf; 49 int num_suspended_intf;
50 int sample_rate_read_error; 50 int sample_rate_read_error;
51 51
52 int badd_profile; /* UAC3 BADD profile */
53
52 struct list_head pcm_list; /* list of pcm streams */ 54 struct list_head pcm_list; /* list of pcm streams */
53 struct list_head ep_list; /* list of audio-related endpoints */ 55 struct list_head ep_list; /* list of audio-related endpoints */
54 int pcm_devs; 56 int pcm_devs;