aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-05-31 07:35:44 -0400
committerTakashi Iwai <tiwai@suse.de>2010-05-31 12:18:04 -0400
commit09414207d4daab8c4990bface3a79fdba3474bec (patch)
treeaee93c37d2ff13f676342f139ecd5ccdadaf28d3
parent67e1daa0bb30eda6ec5add27c3abf4536030f5a6 (diff)
ALSA: usb-audio: export UAC2 clock selectors as mixer controls
The UAC2 clock selectors are fortunately compatible with UAC1 audio selector units, so we can simply reuse the same approach to get all the linked units. Requests to this control need a different CS value though. Signed-off-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-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