diff options
author | Ian Douglas Scott <ian@iandouglasscott.com> | 2018-01-16 18:34:50 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2018-01-18 04:12:59 -0500 |
commit | 388fdb8f882af67ff8394d9420c1e0e42ba35619 (patch) | |
tree | 8ba10325eabe10fa8a0a1720254d506544623c2b | |
parent | 1b6832be1b61f63ef367e48050617e870a46b417 (diff) |
ALSA: usb-audio: Support changing input on Sound Blaster E1
The E1 has two headphone jacks, one of which can be set as a microphone
input. In the default mode, it uses the built-in microphone as an input.
By sending a special command, the second headphone jack is instead used
as an input.
This might work with the E3 as well, but I don't have one of those to
test it.
Signed-off-by: Ian Douglas Scott <ian@iandouglasscott.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/usb/mixer_quirks.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index e1e7ce9ab217..e6359d341878 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -27,6 +27,7 @@ | |||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/hid.h> | ||
30 | #include <linux/init.h> | 31 | #include <linux/init.h> |
31 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
32 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
@@ -1721,6 +1722,83 @@ static int snd_microii_controls_create(struct usb_mixer_interface *mixer) | |||
1721 | return 0; | 1722 | return 0; |
1722 | } | 1723 | } |
1723 | 1724 | ||
1725 | /* Creative Sound Blaster E1 */ | ||
1726 | |||
1727 | static int snd_soundblaster_e1_switch_get(struct snd_kcontrol *kcontrol, | ||
1728 | struct snd_ctl_elem_value *ucontrol) | ||
1729 | { | ||
1730 | ucontrol->value.integer.value[0] = kcontrol->private_value; | ||
1731 | return 0; | ||
1732 | } | ||
1733 | |||
1734 | static int snd_soundblaster_e1_switch_update(struct usb_mixer_interface *mixer, | ||
1735 | unsigned char state) | ||
1736 | { | ||
1737 | struct snd_usb_audio *chip = mixer->chip; | ||
1738 | int err; | ||
1739 | unsigned char buff[2]; | ||
1740 | |||
1741 | buff[0] = 0x02; | ||
1742 | buff[1] = state ? 0x02 : 0x00; | ||
1743 | |||
1744 | err = snd_usb_lock_shutdown(chip); | ||
1745 | if (err < 0) | ||
1746 | return err; | ||
1747 | err = snd_usb_ctl_msg(chip->dev, | ||
1748 | usb_sndctrlpipe(chip->dev, 0), HID_REQ_SET_REPORT, | ||
1749 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
1750 | 0x0202, 3, buff, 2); | ||
1751 | snd_usb_unlock_shutdown(chip); | ||
1752 | return err; | ||
1753 | } | ||
1754 | |||
1755 | static int snd_soundblaster_e1_switch_put(struct snd_kcontrol *kcontrol, | ||
1756 | struct snd_ctl_elem_value *ucontrol) | ||
1757 | { | ||
1758 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); | ||
1759 | unsigned char value = !!ucontrol->value.integer.value[0]; | ||
1760 | int err; | ||
1761 | |||
1762 | if (kcontrol->private_value == value) | ||
1763 | return 0; | ||
1764 | kcontrol->private_value = value; | ||
1765 | err = snd_soundblaster_e1_switch_update(list->mixer, value); | ||
1766 | return err < 0 ? err : 1; | ||
1767 | } | ||
1768 | |||
1769 | static int snd_soundblaster_e1_switch_resume(struct usb_mixer_elem_list *list) | ||
1770 | { | ||
1771 | return snd_soundblaster_e1_switch_update(list->mixer, | ||
1772 | list->kctl->private_value); | ||
1773 | } | ||
1774 | |||
1775 | static int snd_soundblaster_e1_switch_info(struct snd_kcontrol *kcontrol, | ||
1776 | struct snd_ctl_elem_info *uinfo) | ||
1777 | { | ||
1778 | static const char *const texts[2] = { | ||
1779 | "Mic", "Aux" | ||
1780 | }; | ||
1781 | |||
1782 | return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); | ||
1783 | } | ||
1784 | |||
1785 | static struct snd_kcontrol_new snd_soundblaster_e1_input_switch = { | ||
1786 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1787 | .name = "Input Source", | ||
1788 | .info = snd_soundblaster_e1_switch_info, | ||
1789 | .get = snd_soundblaster_e1_switch_get, | ||
1790 | .put = snd_soundblaster_e1_switch_put, | ||
1791 | .private_value = 0, | ||
1792 | }; | ||
1793 | |||
1794 | static int snd_soundblaster_e1_switch_create(struct usb_mixer_interface *mixer) | ||
1795 | { | ||
1796 | return add_single_ctl_with_resume(mixer, 0, | ||
1797 | snd_soundblaster_e1_switch_resume, | ||
1798 | &snd_soundblaster_e1_input_switch, | ||
1799 | NULL); | ||
1800 | } | ||
1801 | |||
1724 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | 1802 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) |
1725 | { | 1803 | { |
1726 | int err = 0; | 1804 | int err = 0; |
@@ -1802,6 +1880,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
1802 | case USB_ID(0x1235, 0x800c): /* Focusrite Scarlett 18i20 */ | 1880 | case USB_ID(0x1235, 0x800c): /* Focusrite Scarlett 18i20 */ |
1803 | err = snd_scarlett_controls_create(mixer); | 1881 | err = snd_scarlett_controls_create(mixer); |
1804 | break; | 1882 | break; |
1883 | |||
1884 | case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */ | ||
1885 | err = snd_soundblaster_e1_switch_create(mixer); | ||
1886 | break; | ||
1805 | } | 1887 | } |
1806 | 1888 | ||
1807 | return err; | 1889 | return err; |