diff options
author | Timofei Bondarenko <tim@ipi.ac.ru> | 2007-10-30 10:28:14 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:14 -0500 |
commit | 69b1f1e8337fc94a7ea0730588960e82676dc2dc (patch) | |
tree | b44d0756848e3dfc7713bbf57c20b4127bbd0a9e | |
parent | 045765253c610cb5acebb22ae94d759f586d9521 (diff) |
[ALSA] usb-audio - SB Live24-External better handling
This patch improves support for 'SB Live 24-bit Extarnal' USB card.
1) This card can go into muted state when a headphones connected or
disconnected. So notify mixer about changes in headphone jack.
2) Add LED controls and procfs support just as in similar Audigy 2 NX card.
3) Rename 'PCM Capture' conrol to 'Mic Capture' to reflect reality:
the card may adjust microphone input level only.
Signed-off-by: Timofei Bondarenko <tim@ipi.ac.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r-- | sound/usb/usbmixer.c | 33 | ||||
-rw-r--r-- | sound/usb/usbmixer_maps.c | 11 |
2 files changed, 39 insertions, 5 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 5e329690cfb1..1f1e91cee3fe 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -1703,6 +1703,11 @@ static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, | |||
1703 | case 19: /* speaker out jacks */ | 1703 | case 19: /* speaker out jacks */ |
1704 | case 20: /* headphones out jack */ | 1704 | case 20: /* headphones out jack */ |
1705 | break; | 1705 | break; |
1706 | /* live24ext: 4 = line-in jack */ | ||
1707 | case 3: /* hp-out jack (may actuate Mute) */ | ||
1708 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) | ||
1709 | snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id); | ||
1710 | break; | ||
1706 | default: | 1711 | default: |
1707 | snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid); | 1712 | snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid); |
1708 | break; | 1713 | break; |
@@ -1951,6 +1956,9 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | |||
1951 | int i, err; | 1956 | int i, err; |
1952 | 1957 | ||
1953 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { | 1958 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { |
1959 | if (i > 1 && /* Live24ext has 2 LEDs only */ | ||
1960 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) | ||
1961 | break; | ||
1954 | err = snd_ctl_add(mixer->chip->card, | 1962 | err = snd_ctl_add(mixer->chip->card, |
1955 | snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); | 1963 | snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); |
1956 | if (err < 0) | 1964 | if (err < 0) |
@@ -1963,28 +1971,42 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | |||
1963 | static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, | 1971 | static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, |
1964 | struct snd_info_buffer *buffer) | 1972 | struct snd_info_buffer *buffer) |
1965 | { | 1973 | { |
1966 | static const struct { | 1974 | static const struct sb_jack { |
1967 | int unitid; | 1975 | int unitid; |
1968 | const char *name; | 1976 | const char *name; |
1969 | } jacks[] = { | 1977 | } jacks_audigy2nx[] = { |
1970 | {4, "dig in "}, | 1978 | {4, "dig in "}, |
1971 | {7, "line in"}, | 1979 | {7, "line in"}, |
1972 | {19, "spk out"}, | 1980 | {19, "spk out"}, |
1973 | {20, "hph out"}, | 1981 | {20, "hph out"}, |
1982 | {-1, NULL} | ||
1983 | }, jacks_live24ext[] = { | ||
1984 | {4, "line in"}, /* &1=Line, &2=Mic*/ | ||
1985 | {3, "hph out"}, /* headphones */ | ||
1986 | {0, "RC "}, /* last command, 6 bytes see rc_config above */ | ||
1987 | {-1, NULL} | ||
1974 | }; | 1988 | }; |
1989 | const struct sb_jack *jacks; | ||
1975 | struct usb_mixer_interface *mixer = entry->private_data; | 1990 | struct usb_mixer_interface *mixer = entry->private_data; |
1976 | int i, err; | 1991 | int i, err; |
1977 | u8 buf[3]; | 1992 | u8 buf[3]; |
1978 | 1993 | ||
1979 | snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); | 1994 | snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); |
1980 | for (i = 0; i < ARRAY_SIZE(jacks); ++i) { | 1995 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) |
1996 | jacks = jacks_audigy2nx; | ||
1997 | else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) | ||
1998 | jacks = jacks_live24ext; | ||
1999 | else | ||
2000 | return; | ||
2001 | |||
2002 | for (i = 0; jacks[i].name; ++i) { | ||
1981 | snd_iprintf(buffer, "%s: ", jacks[i].name); | 2003 | snd_iprintf(buffer, "%s: ", jacks[i].name); |
1982 | err = snd_usb_ctl_msg(mixer->chip->dev, | 2004 | err = snd_usb_ctl_msg(mixer->chip->dev, |
1983 | usb_rcvctrlpipe(mixer->chip->dev, 0), | 2005 | usb_rcvctrlpipe(mixer->chip->dev, 0), |
1984 | GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | | 2006 | GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | |
1985 | USB_RECIP_INTERFACE, 0, | 2007 | USB_RECIP_INTERFACE, 0, |
1986 | jacks[i].unitid << 8, buf, 3, 100); | 2008 | jacks[i].unitid << 8, buf, 3, 100); |
1987 | if (err == 3 && buf[0] == 3) | 2009 | if (err == 3 && (buf[0] == 3 || buf[0] == 6)) |
1988 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); | 2010 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); |
1989 | else | 2011 | else |
1990 | snd_iprintf(buffer, "?\n"); | 2012 | snd_iprintf(buffer, "?\n"); |
@@ -2022,7 +2044,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif) | |||
2022 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) | 2044 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) |
2023 | goto _error; | 2045 | goto _error; |
2024 | 2046 | ||
2025 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) { | 2047 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || |
2048 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) { | ||
2026 | struct snd_info_entry *entry; | 2049 | struct snd_info_entry *entry; |
2027 | 2050 | ||
2028 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | 2051 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) |
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index 7c4dcb3f436a..d755be0ad811 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c | |||
@@ -187,6 +187,13 @@ static struct usbmix_selector_map audigy2nx_selectors[] = { | |||
187 | { 0 } /* terminator */ | 187 | { 0 } /* terminator */ |
188 | }; | 188 | }; |
189 | 189 | ||
190 | /* Creative SoundBlaster Live! 24-bit External */ | ||
191 | static struct usbmix_name_map live24ext_map[] = { | ||
192 | /* 2: PCM Playback Volume */ | ||
193 | { 5, "Mic Capture" }, /* FU, default PCM Capture Volume */ | ||
194 | { 0 } /* terminator */ | ||
195 | }; | ||
196 | |||
190 | /* LineX FM Transmitter entry - needed to bypass controls bug */ | 197 | /* LineX FM Transmitter entry - needed to bypass controls bug */ |
191 | static struct usbmix_name_map linex_map[] = { | 198 | static struct usbmix_name_map linex_map[] = { |
192 | /* 1: IT pcm */ | 199 | /* 1: IT pcm */ |
@@ -273,6 +280,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { | |||
273 | .map = audigy2nx_map, | 280 | .map = audigy2nx_map, |
274 | .selector_map = audigy2nx_selectors, | 281 | .selector_map = audigy2nx_selectors, |
275 | }, | 282 | }, |
283 | { | ||
284 | .id = USB_ID(0x041e, 0x3040), | ||
285 | .map = live24ext_map, | ||
286 | }, | ||
276 | { | 287 | { |
277 | /* Hercules DJ Console (Windows Edition) */ | 288 | /* Hercules DJ Console (Windows Edition) */ |
278 | .id = USB_ID(0x06f8, 0xb000), | 289 | .id = USB_ID(0x06f8, 0xb000), |