aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r--sound/usb/mixer.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index cb345360f811..a060d005e209 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -313,8 +313,8 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
313 buf, sizeof(buf), 1000); 313 buf, sizeof(buf), 1000);
314 314
315 if (ret < 0) { 315 if (ret < 0) {
316 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", 316 snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
317 request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type); 317 request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
318 return ret; 318 return ret;
319 } 319 }
320 320
@@ -610,6 +610,7 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
610 */ 610 */
611static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term) 611static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term)
612{ 612{
613 int err;
613 void *p1; 614 void *p1;
614 615
615 memset(term, 0, sizeof(*term)); 616 memset(term, 0, sizeof(*term));
@@ -630,6 +631,11 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
630 term->channels = d->bNrChannels; 631 term->channels = d->bNrChannels;
631 term->chconfig = le32_to_cpu(d->bmChannelConfig); 632 term->chconfig = le32_to_cpu(d->bmChannelConfig);
632 term->name = d->iTerminal; 633 term->name = d->iTerminal;
634
635 /* call recursively to get the clock selectors */
636 err = check_input_term(state, d->bCSourceID, term);
637 if (err < 0)
638 return err;
633 } 639 }
634 return 0; 640 return 0;
635 case UAC_FEATURE_UNIT: { 641 case UAC_FEATURE_UNIT: {
@@ -646,7 +652,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
646 term->name = uac_mixer_unit_iMixer(d); 652 term->name = uac_mixer_unit_iMixer(d);
647 return 0; 653 return 0;
648 } 654 }
649 case UAC_SELECTOR_UNIT: { 655 case UAC_SELECTOR_UNIT:
656 case UAC2_CLOCK_SELECTOR: {
650 struct uac_selector_unit_descriptor *d = p1; 657 struct uac_selector_unit_descriptor *d = p1;
651 /* call recursively to retrieve the channel info */ 658 /* call recursively to retrieve the channel info */
652 if (check_input_term(state, d->baSourceID[0], term) < 0) 659 if (check_input_term(state, d->baSourceID[0], term) < 0)
@@ -669,6 +676,13 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
669 term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol); 676 term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol);
670 return 0; 677 return 0;
671 } 678 }
679 case UAC2_CLOCK_SOURCE: {
680 struct uac_clock_source_descriptor *d = p1;
681 term->type = d->bDescriptorSubtype << 16; /* virtual type */
682 term->id = id;
683 term->name = d->iClockSource;
684 return 0;
685 }
672 default: 686 default:
673 return -ENODEV; 687 return -ENODEV;
674 } 688 }
@@ -1610,7 +1624,7 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_
1610 struct usb_mixer_elem_info *cval = kcontrol->private_data; 1624 struct usb_mixer_elem_info *cval = kcontrol->private_data;
1611 int val, err; 1625 int val, err;
1612 1626
1613 err = get_cur_ctl_value(cval, 0, &val); 1627 err = get_cur_ctl_value(cval, cval->control << 8, &val);
1614 if (err < 0) { 1628 if (err < 0) {
1615 if (cval->mixer->ignore_ctl_error) { 1629 if (cval->mixer->ignore_ctl_error) {
1616 ucontrol->value.enumerated.item[0] = 0; 1630 ucontrol->value.enumerated.item[0] = 0;
@@ -1629,7 +1643,7 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
1629 struct usb_mixer_elem_info *cval = kcontrol->private_data; 1643 struct usb_mixer_elem_info *cval = kcontrol->private_data;
1630 int val, oval, err; 1644 int val, oval, err;
1631 1645
1632 err = get_cur_ctl_value(cval, 0, &oval); 1646 err = get_cur_ctl_value(cval, cval->control << 8, &oval);
1633 if (err < 0) { 1647 if (err < 0) {
1634 if (cval->mixer->ignore_ctl_error) 1648 if (cval->mixer->ignore_ctl_error)
1635 return 0; 1649 return 0;
@@ -1638,7 +1652,7 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
1638 val = ucontrol->value.enumerated.item[0]; 1652 val = ucontrol->value.enumerated.item[0];
1639 val = get_abs_value(cval, val); 1653 val = get_abs_value(cval, val);
1640 if (val != oval) { 1654 if (val != oval) {
1641 set_cur_ctl_value(cval, 0, val); 1655 set_cur_ctl_value(cval, cval->control << 8, val);
1642 return 1; 1656 return 1;
1643 } 1657 }
1644 return 0; 1658 return 0;
@@ -1720,6 +1734,11 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
1720 cval->res = 1; 1734 cval->res = 1;
1721 cval->initialized = 1; 1735 cval->initialized = 1;
1722 1736
1737 if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
1738 cval->control = UAC2_CX_CLOCK_SELECTOR;
1739 else
1740 cval->control = 0;
1741
1723 namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); 1742 namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
1724 if (! namelist) { 1743 if (! namelist) {
1725 snd_printk(KERN_ERR "cannot malloc\n"); 1744 snd_printk(KERN_ERR "cannot malloc\n");
@@ -1769,7 +1788,9 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
1769 if (! len) 1788 if (! len)
1770 strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); 1789 strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
1771 1790
1772 if ((state->oterm.type & 0xff00) == 0x0100) 1791 if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
1792 append_ctl_name(kctl, " Clock Source");
1793 else if ((state->oterm.type & 0xff00) == 0x0100)
1773 append_ctl_name(kctl, " Capture Source"); 1794 append_ctl_name(kctl, " Capture Source");
1774 else 1795 else
1775 append_ctl_name(kctl, " Playback Source"); 1796 append_ctl_name(kctl, " Playback Source");
@@ -1803,10 +1824,12 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
1803 1824
1804 switch (p1[2]) { 1825 switch (p1[2]) {
1805 case UAC_INPUT_TERMINAL: 1826 case UAC_INPUT_TERMINAL:
1827 case UAC2_CLOCK_SOURCE:
1806 return 0; /* NOP */ 1828 return 0; /* NOP */
1807 case UAC_MIXER_UNIT: 1829 case UAC_MIXER_UNIT:
1808 return parse_audio_mixer_unit(state, unitid, p1); 1830 return parse_audio_mixer_unit(state, unitid, p1);
1809 case UAC_SELECTOR_UNIT: 1831 case UAC_SELECTOR_UNIT:
1832 case UAC2_CLOCK_SELECTOR:
1810 return parse_audio_selector_unit(state, unitid, p1); 1833 return parse_audio_selector_unit(state, unitid, p1);
1811 case UAC_FEATURE_UNIT: 1834 case UAC_FEATURE_UNIT:
1812 return parse_audio_feature_unit(state, unitid, p1); 1835 return parse_audio_feature_unit(state, unitid, p1);
@@ -1903,6 +1926,11 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
1903 err = parse_audio_unit(&state, desc->bSourceID); 1926 err = parse_audio_unit(&state, desc->bSourceID);
1904 if (err < 0) 1927 if (err < 0)
1905 return err; 1928 return err;
1929
1930 /* for UAC2, use the same approach to also add the clock selectors */
1931 err = parse_audio_unit(&state, desc->bCSourceID);
1932 if (err < 0)
1933 return err;
1906 } 1934 }
1907 } 1935 }
1908 1936