aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-03-11 15:13:22 -0500
committerTakashi Iwai <tiwai@suse.de>2010-03-12 06:20:26 -0500
commit7b1eda223debcba706ab989a09c4eecb327aebdf (patch)
tree85a22d093120f4456bebfd0da938d727061942d5 /sound/usb
parent45d760567a7d773237b8996584a4ae0440d5e369 (diff)
ALSA: usb-mixer: factor out quirks
Move all non-standard mixer controls and vendor-specific extensions to a separate file. Some structs need to be exported now. Signed-off-by: Daniel Mack <daniel@caiaq.de> Cc: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/Makefile1
-rw-r--r--sound/usb/mixer_quirks.c411
-rw-r--r--sound/usb/mixer_quirks.h13
-rw-r--r--sound/usb/quirks.c1
-rw-r--r--sound/usb/usbmixer.c425
-rw-r--r--sound/usb/usbmixer.h45
6 files changed, 480 insertions, 416 deletions
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 0758d8dc8cde..744024a0a9fc 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -4,6 +4,7 @@
4 4
5snd-usb-audio-objs := card.o \ 5snd-usb-audio-objs := card.o \
6 usbmixer.o \ 6 usbmixer.o \
7 mixer_quirks.o \
7 proc.o \ 8 proc.o \
8 quirks.o \ 9 quirks.o \
9 format.o \ 10 format.o \
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
new file mode 100644
index 000000000000..d2f4dcdf59e3
--- /dev/null
+++ b/sound/usb/mixer_quirks.c
@@ -0,0 +1,411 @@
1/*
2 * USB Audio Driver for ALSA
3 *
4 * Quirks and vendor-specific extensions for mixer interfaces
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * Many codes borrowed from audio.c by
9 * Alan Cox (alan@lxorguk.ukuu.org.uk)
10 * Thomas Sailer (sailer@ife.ee.ethz.ch)
11 *
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28#include <linux/init.h>
29#include <linux/usb.h>
30#include <linux/usb/audio.h>
31
32#include <sound/core.h>
33#include <sound/control.h>
34#include <sound/hwdep.h>
35#include <sound/info.h>
36
37#include "usbaudio.h"
38#include "usbmixer.h"
39#include "mixer_quirks.h"
40#include "helper.h"
41
42/*
43 * Sound Blaster remote control configuration
44 *
45 * format of remote control data:
46 * Extigy: xx 00
47 * Audigy 2 NX: 06 80 xx 00 00 00
48 * Live! 24-bit: 06 80 xx yy 22 83
49 */
50static const struct rc_config {
51 u32 usb_id;
52 u8 offset;
53 u8 length;
54 u8 packet_length;
55 u8 min_packet_length; /* minimum accepted length of the URB result */
56 u8 mute_mixer_id;
57 u32 mute_code;
58} rc_configs[] = {
59 { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */
60 { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */
61 { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */
62 { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */
63};
64
65static void snd_usb_soundblaster_remote_complete(struct urb *urb)
66{
67 struct usb_mixer_interface *mixer = urb->context;
68 const struct rc_config *rc = mixer->rc_cfg;
69 u32 code;
70
71 if (urb->status < 0 || urb->actual_length < rc->min_packet_length)
72 return;
73
74 code = mixer->rc_buffer[rc->offset];
75 if (rc->length == 2)
76 code |= mixer->rc_buffer[rc->offset + 1] << 8;
77
78 /* the Mute button actually changes the mixer control */
79 if (code == rc->mute_code)
80 snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
81 mixer->rc_code = code;
82 wmb();
83 wake_up(&mixer->rc_waitq);
84}
85
86static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf,
87 long count, loff_t *offset)
88{
89 struct usb_mixer_interface *mixer = hw->private_data;
90 int err;
91 u32 rc_code;
92
93 if (count != 1 && count != 4)
94 return -EINVAL;
95 err = wait_event_interruptible(mixer->rc_waitq,
96 (rc_code = xchg(&mixer->rc_code, 0)) != 0);
97 if (err == 0) {
98 if (count == 1)
99 err = put_user(rc_code, buf);
100 else
101 err = put_user(rc_code, (u32 __user *)buf);
102 }
103 return err < 0 ? err : count;
104}
105
106static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *file,
107 poll_table *wait)
108{
109 struct usb_mixer_interface *mixer = hw->private_data;
110
111 poll_wait(file, &mixer->rc_waitq, wait);
112 return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
113}
114
115static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
116{
117 struct snd_hwdep *hwdep;
118 int err, len, i;
119
120 for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
121 if (rc_configs[i].usb_id == mixer->chip->usb_id)
122 break;
123 if (i >= ARRAY_SIZE(rc_configs))
124 return 0;
125 mixer->rc_cfg = &rc_configs[i];
126
127 len = mixer->rc_cfg->packet_length;
128
129 init_waitqueue_head(&mixer->rc_waitq);
130 err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
131 if (err < 0)
132 return err;
133 snprintf(hwdep->name, sizeof(hwdep->name),
134 "%s remote control", mixer->chip->card->shortname);
135 hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
136 hwdep->private_data = mixer;
137 hwdep->ops.read = snd_usb_sbrc_hwdep_read;
138 hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
139 hwdep->exclusive = 1;
140
141 mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
142 if (!mixer->rc_urb)
143 return -ENOMEM;
144 mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
145 if (!mixer->rc_setup_packet) {
146 usb_free_urb(mixer->rc_urb);
147 mixer->rc_urb = NULL;
148 return -ENOMEM;
149 }
150 mixer->rc_setup_packet->bRequestType =
151 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
152 mixer->rc_setup_packet->bRequest = UAC_GET_MEM;
153 mixer->rc_setup_packet->wValue = cpu_to_le16(0);
154 mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
155 mixer->rc_setup_packet->wLength = cpu_to_le16(len);
156 usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
157 usb_rcvctrlpipe(mixer->chip->dev, 0),
158 (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
159 snd_usb_soundblaster_remote_complete, mixer);
160 return 0;
161}
162
163#define snd_audigy2nx_led_info snd_ctl_boolean_mono_info
164
165static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
166{
167 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
168 int index = kcontrol->private_value;
169
170 ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
171 return 0;
172}
173
174static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
175{
176 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
177 int index = kcontrol->private_value;
178 int value = ucontrol->value.integer.value[0];
179 int err, changed;
180
181 if (value > 1)
182 return -EINVAL;
183 changed = value != mixer->audigy2nx_leds[index];
184 err = snd_usb_ctl_msg(mixer->chip->dev,
185 usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
186 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
187 value, index + 2, NULL, 0, 100);
188 if (err < 0)
189 return err;
190 mixer->audigy2nx_leds[index] = value;
191 return changed;
192}
193
194static struct snd_kcontrol_new snd_audigy2nx_controls[] = {
195 {
196 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
197 .name = "CMSS LED Switch",
198 .info = snd_audigy2nx_led_info,
199 .get = snd_audigy2nx_led_get,
200 .put = snd_audigy2nx_led_put,
201 .private_value = 0,
202 },
203 {
204 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
205 .name = "Power LED Switch",
206 .info = snd_audigy2nx_led_info,
207 .get = snd_audigy2nx_led_get,
208 .put = snd_audigy2nx_led_put,
209 .private_value = 1,
210 },
211 {
212 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
213 .name = "Dolby Digital LED Switch",
214 .info = snd_audigy2nx_led_info,
215 .get = snd_audigy2nx_led_get,
216 .put = snd_audigy2nx_led_put,
217 .private_value = 2,
218 },
219};
220
221static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
222{
223 int i, err;
224
225 for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
226 if (i > 1 && /* Live24ext has 2 LEDs only */
227 (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
228 mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
229 break;
230 err = snd_ctl_add(mixer->chip->card,
231 snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
232 if (err < 0)
233 return err;
234 }
235 mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
236 return 0;
237}
238
239static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
240 struct snd_info_buffer *buffer)
241{
242 static const struct sb_jack {
243 int unitid;
244 const char *name;
245 } jacks_audigy2nx[] = {
246 {4, "dig in "},
247 {7, "line in"},
248 {19, "spk out"},
249 {20, "hph out"},
250 {-1, NULL}
251 }, jacks_live24ext[] = {
252 {4, "line in"}, /* &1=Line, &2=Mic*/
253 {3, "hph out"}, /* headphones */
254 {0, "RC "}, /* last command, 6 bytes see rc_config above */
255 {-1, NULL}
256 };
257 const struct sb_jack *jacks;
258 struct usb_mixer_interface *mixer = entry->private_data;
259 int i, err;
260 u8 buf[3];
261
262 snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
263 if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
264 jacks = jacks_audigy2nx;
265 else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
266 mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
267 jacks = jacks_live24ext;
268 else
269 return;
270
271 for (i = 0; jacks[i].name; ++i) {
272 snd_iprintf(buffer, "%s: ", jacks[i].name);
273 err = snd_usb_ctl_msg(mixer->chip->dev,
274 usb_rcvctrlpipe(mixer->chip->dev, 0),
275 UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
276 USB_RECIP_INTERFACE, 0,
277 jacks[i].unitid << 8, buf, 3, 100);
278 if (err == 3 && (buf[0] == 3 || buf[0] == 6))
279 snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
280 else
281 snd_iprintf(buffer, "?\n");
282 }
283}
284
285static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
286 struct snd_ctl_elem_value *ucontrol)
287{
288 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
289
290 ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02);
291 return 0;
292}
293
294static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
295 struct snd_ctl_elem_value *ucontrol)
296{
297 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
298 u8 old_status, new_status;
299 int err, changed;
300
301 old_status = mixer->xonar_u1_status;
302 if (ucontrol->value.integer.value[0])
303 new_status = old_status | 0x02;
304 else
305 new_status = old_status & ~0x02;
306 changed = new_status != old_status;
307 err = snd_usb_ctl_msg(mixer->chip->dev,
308 usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
309 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
310 50, 0, &new_status, 1, 100);
311 if (err < 0)
312 return err;
313 mixer->xonar_u1_status = new_status;
314 return changed;
315}
316
317static struct snd_kcontrol_new snd_xonar_u1_output_switch = {
318 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
319 .name = "Digital Playback Switch",
320 .info = snd_ctl_boolean_mono_info,
321 .get = snd_xonar_u1_switch_get,
322 .put = snd_xonar_u1_switch_put,
323};
324
325static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
326{
327 int err;
328
329 err = snd_ctl_add(mixer->chip->card,
330 snd_ctl_new1(&snd_xonar_u1_output_switch, mixer));
331 if (err < 0)
332 return err;
333 mixer->xonar_u1_status = 0x05;
334 return 0;
335}
336
337void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
338 unsigned char samplerate_id)
339{
340 struct usb_mixer_interface *mixer;
341 struct usb_mixer_elem_info *cval;
342 int unitid = 12; /* SamleRate ExtensionUnit ID */
343
344 list_for_each_entry(mixer, &chip->mixer_list, list) {
345 cval = mixer->id_elems[unitid];
346 if (cval) {
347 snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
348 cval->control << 8,
349 samplerate_id);
350 snd_usb_mixer_notify_id(mixer, unitid);
351 }
352 break;
353 }
354}
355
356int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
357{
358 int err;
359 struct snd_info_entry *entry;
360
361 if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
362 return err;
363
364 if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
365 mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
366 mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
367 if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
368 return err;
369 if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
370 snd_info_set_text_ops(entry, mixer,
371 snd_audigy2nx_proc_read);
372 }
373
374 if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) ||
375 mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) {
376 err = snd_xonar_u1_controls_create(mixer);
377 if (err < 0)
378 return err;
379 }
380
381 return 0;
382}
383
384void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
385 int unitid)
386{
387 if (!mixer->rc_cfg)
388 return;
389 /* unit ids specific to Extigy/Audigy 2 NX: */
390 switch (unitid) {
391 case 0: /* remote control */
392 mixer->rc_urb->dev = mixer->chip->dev;
393 usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
394 break;
395 case 4: /* digital in jack */
396 case 7: /* line in jacks */
397 case 19: /* speaker out jacks */
398 case 20: /* headphones out jack */
399 break;
400 /* live24ext: 4 = line-in jack */
401 case 3: /* hp-out jack (may actuate Mute) */
402 if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
403 mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
404 snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
405 break;
406 default:
407 snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
408 break;
409 }
410}
411
diff --git a/sound/usb/mixer_quirks.h b/sound/usb/mixer_quirks.h
new file mode 100644
index 000000000000..bdbfab093816
--- /dev/null
+++ b/sound/usb/mixer_quirks.h
@@ -0,0 +1,13 @@
1#ifndef SND_USB_MIXER_QUIRKS_H
2#define SND_USB_MIXER_QUIRKS_H
3
4int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer);
5
6void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
7 unsigned char samplerate_id);
8
9void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
10 int unitid);
11
12#endif /* SND_USB_MIXER_QUIRKS_H */
13
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0c0b23b63794..a82cfeda21f0 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -25,6 +25,7 @@
25#include "usbaudio.h" 25#include "usbaudio.h"
26#include "card.h" 26#include "card.h"
27#include "usbmixer.h" 27#include "usbmixer.h"
28#include "mixer_quirks.h"
28#include "midi.h" 29#include "midi.h"
29#include "quirks.h" 30#include "quirks.h"
30#include "helper.h" 31#include "helper.h"
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index ab8f0f0b65be..ec2436e95321 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -43,60 +43,10 @@
43#include "usbaudio.h" 43#include "usbaudio.h"
44#include "usbmixer.h" 44#include "usbmixer.h"
45#include "helper.h" 45#include "helper.h"
46 46#include "mixer_quirks.h"
47/*
48 */
49
50/* ignore error from controls - for debugging */
51/* #define IGNORE_CTL_ERROR */
52
53/*
54 * Sound Blaster remote control configuration
55 *
56 * format of remote control data:
57 * Extigy: xx 00
58 * Audigy 2 NX: 06 80 xx 00 00 00
59 * Live! 24-bit: 06 80 xx yy 22 83
60 */
61static const struct rc_config {
62 u32 usb_id;
63 u8 offset;
64 u8 length;
65 u8 packet_length;
66 u8 min_packet_length; /* minimum accepted length of the URB result */
67 u8 mute_mixer_id;
68 u32 mute_code;
69} rc_configs[] = {
70 { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */
71 { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */
72 { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */
73 { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */
74};
75 47
76#define MAX_ID_ELEMS 256 48#define MAX_ID_ELEMS 256
77 49
78struct usb_mixer_interface {
79 struct snd_usb_audio *chip;
80 unsigned int ctrlif;
81 struct list_head list;
82 unsigned int ignore_ctl_error;
83 struct urb *urb;
84 /* array[MAX_ID_ELEMS], indexed by unit id */
85 struct usb_mixer_elem_info **id_elems;
86
87 /* Sound Blaster remote control stuff */
88 const struct rc_config *rc_cfg;
89 u32 rc_code;
90 wait_queue_head_t rc_waitq;
91 struct urb *rc_urb;
92 struct usb_ctrlrequest *rc_setup_packet;
93 u8 rc_buffer[6];
94
95 u8 audigy2nx_leds[3];
96 u8 xonar_u1_status;
97};
98
99
100struct usb_audio_term { 50struct usb_audio_term {
101 int id; 51 int id;
102 int type; 52 int type;
@@ -118,24 +68,6 @@ struct mixer_build {
118 const struct usbmix_selector_map *selector_map; 68 const struct usbmix_selector_map *selector_map;
119}; 69};
120 70
121#define MAX_CHANNELS 10 /* max logical channels */
122
123struct usb_mixer_elem_info {
124 struct usb_mixer_interface *mixer;
125 struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
126 struct snd_ctl_elem_id *elem_id;
127 unsigned int id;
128 unsigned int control; /* CS or ICN (high byte) */
129 unsigned int cmask; /* channel mask bitmap: 0 = master */
130 int channels;
131 int val_type;
132 int min, max, res;
133 int dBmin, dBmax;
134 int cached;
135 int cache_val[MAX_CHANNELS];
136 u8 initialized;
137};
138
139enum { 71enum {
140 USB_MIXER_BOOLEAN, 72 USB_MIXER_BOOLEAN,
141 USB_MIXER_INV_BOOLEAN, 73 USB_MIXER_INV_BOOLEAN,
@@ -431,7 +363,8 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
431 * set a mixer value 363 * set a mixer value
432 */ 364 */
433 365
434static int set_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int value_set) 366int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
367 int request, int validx, int value_set)
435{ 368{
436 unsigned char buf[2]; 369 unsigned char buf[2];
437 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 370 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -455,14 +388,14 @@ static int set_ctl_value(struct usb_mixer_elem_info *cval, int request, int vali
455 388
456static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) 389static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)
457{ 390{
458 return set_ctl_value(cval, UAC_SET_CUR, validx, value); 391 return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value);
459} 392}
460 393
461static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, 394static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
462 int index, int value) 395 int index, int value)
463{ 396{
464 int err; 397 int err;
465 err = set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel, 398 err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel,
466 value); 399 value);
467 if (err < 0) 400 if (err < 0)
468 return err; 401 return err;
@@ -751,7 +684,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
751 int last_valid_res = cval->res; 684 int last_valid_res = cval->res;
752 685
753 while (cval->res > 1) { 686 while (cval->res > 1) {
754 if (set_ctl_value(cval, UAC_SET_RES, (cval->control << 8) | minchn, cval->res / 2) < 0) 687 if (snd_usb_mixer_set_ctl_value(cval, UAC_SET_RES,
688 (cval->control << 8) | minchn, cval->res / 2) < 0)
755 break; 689 break;
756 cval->res /= 2; 690 cval->res /= 2;
757 } 691 }
@@ -1808,8 +1742,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
1808 return 0; 1742 return 0;
1809} 1743}
1810 1744
1811static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, 1745void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
1812 int unitid)
1813{ 1746{
1814 struct usb_mixer_elem_info *info; 1747 struct usb_mixer_elem_info *info;
1815 1748
@@ -1858,34 +1791,6 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
1858 } 1791 }
1859} 1792}
1860 1793
1861static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
1862 int unitid)
1863{
1864 if (!mixer->rc_cfg)
1865 return;
1866 /* unit ids specific to Extigy/Audigy 2 NX: */
1867 switch (unitid) {
1868 case 0: /* remote control */
1869 mixer->rc_urb->dev = mixer->chip->dev;
1870 usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
1871 break;
1872 case 4: /* digital in jack */
1873 case 7: /* line in jacks */
1874 case 19: /* speaker out jacks */
1875 case 20: /* headphones out jack */
1876 break;
1877 /* live24ext: 4 = line-in jack */
1878 case 3: /* hp-out jack (may actuate Mute) */
1879 if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
1880 mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
1881 snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
1882 break;
1883 default:
1884 snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
1885 break;
1886 }
1887}
1888
1889static void snd_usb_mixer_status_complete(struct urb *urb) 1794static void snd_usb_mixer_status_complete(struct urb *urb)
1890{ 1795{
1891 struct usb_mixer_interface *mixer = urb->context; 1796 struct usb_mixer_interface *mixer = urb->context;
@@ -1903,7 +1808,7 @@ static void snd_usb_mixer_status_complete(struct urb *urb)
1903 if (!(buf[0] & 0x40)) 1808 if (!(buf[0] & 0x40))
1904 snd_usb_mixer_notify_id(mixer, buf[1]); 1809 snd_usb_mixer_notify_id(mixer, buf[1]);
1905 else 1810 else
1906 snd_usb_mixer_memory_change(mixer, buf[1]); 1811 snd_usb_mixer_rc_memory_change(mixer, buf[1]);
1907 } 1812 }
1908 } 1813 }
1909 if (urb->status != -ENOENT && urb->status != -ECONNRESET) { 1814 if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
@@ -1947,296 +1852,6 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
1947 return 0; 1852 return 0;
1948} 1853}
1949 1854
1950static void snd_usb_soundblaster_remote_complete(struct urb *urb)
1951{
1952 struct usb_mixer_interface *mixer = urb->context;
1953 const struct rc_config *rc = mixer->rc_cfg;
1954 u32 code;
1955
1956 if (urb->status < 0 || urb->actual_length < rc->min_packet_length)
1957 return;
1958
1959 code = mixer->rc_buffer[rc->offset];
1960 if (rc->length == 2)
1961 code |= mixer->rc_buffer[rc->offset + 1] << 8;
1962
1963 /* the Mute button actually changes the mixer control */
1964 if (code == rc->mute_code)
1965 snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
1966 mixer->rc_code = code;
1967 wmb();
1968 wake_up(&mixer->rc_waitq);
1969}
1970
1971static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf,
1972 long count, loff_t *offset)
1973{
1974 struct usb_mixer_interface *mixer = hw->private_data;
1975 int err;
1976 u32 rc_code;
1977
1978 if (count != 1 && count != 4)
1979 return -EINVAL;
1980 err = wait_event_interruptible(mixer->rc_waitq,
1981 (rc_code = xchg(&mixer->rc_code, 0)) != 0);
1982 if (err == 0) {
1983 if (count == 1)
1984 err = put_user(rc_code, buf);
1985 else
1986 err = put_user(rc_code, (u32 __user *)buf);
1987 }
1988 return err < 0 ? err : count;
1989}
1990
1991static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *file,
1992 poll_table *wait)
1993{
1994 struct usb_mixer_interface *mixer = hw->private_data;
1995
1996 poll_wait(file, &mixer->rc_waitq, wait);
1997 return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
1998}
1999
2000static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
2001{
2002 struct snd_hwdep *hwdep;
2003 int err, len, i;
2004
2005 for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
2006 if (rc_configs[i].usb_id == mixer->chip->usb_id)
2007 break;
2008 if (i >= ARRAY_SIZE(rc_configs))
2009 return 0;
2010 mixer->rc_cfg = &rc_configs[i];
2011
2012 len = mixer->rc_cfg->packet_length;
2013
2014 init_waitqueue_head(&mixer->rc_waitq);
2015 err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
2016 if (err < 0)
2017 return err;
2018 snprintf(hwdep->name, sizeof(hwdep->name),
2019 "%s remote control", mixer->chip->card->shortname);
2020 hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
2021 hwdep->private_data = mixer;
2022 hwdep->ops.read = snd_usb_sbrc_hwdep_read;
2023 hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
2024 hwdep->exclusive = 1;
2025
2026 mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
2027 if (!mixer->rc_urb)
2028 return -ENOMEM;
2029 mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
2030 if (!mixer->rc_setup_packet) {
2031 usb_free_urb(mixer->rc_urb);
2032 mixer->rc_urb = NULL;
2033 return -ENOMEM;
2034 }
2035 mixer->rc_setup_packet->bRequestType =
2036 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
2037 mixer->rc_setup_packet->bRequest = UAC_GET_MEM;
2038 mixer->rc_setup_packet->wValue = cpu_to_le16(0);
2039 mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
2040 mixer->rc_setup_packet->wLength = cpu_to_le16(len);
2041 usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
2042 usb_rcvctrlpipe(mixer->chip->dev, 0),
2043 (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
2044 snd_usb_soundblaster_remote_complete, mixer);
2045 return 0;
2046}
2047
2048#define snd_audigy2nx_led_info snd_ctl_boolean_mono_info
2049
2050static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2051{
2052 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
2053 int index = kcontrol->private_value;
2054
2055 ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
2056 return 0;
2057}
2058
2059static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2060{
2061 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
2062 int index = kcontrol->private_value;
2063 int value = ucontrol->value.integer.value[0];
2064 int err, changed;
2065
2066 if (value > 1)
2067 return -EINVAL;
2068 changed = value != mixer->audigy2nx_leds[index];
2069 err = snd_usb_ctl_msg(mixer->chip->dev,
2070 usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
2071 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
2072 value, index + 2, NULL, 0, 100);
2073 if (err < 0)
2074 return err;
2075 mixer->audigy2nx_leds[index] = value;
2076 return changed;
2077}
2078
2079static struct snd_kcontrol_new snd_audigy2nx_controls[] = {
2080 {
2081 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2082 .name = "CMSS LED Switch",
2083 .info = snd_audigy2nx_led_info,
2084 .get = snd_audigy2nx_led_get,
2085 .put = snd_audigy2nx_led_put,
2086 .private_value = 0,
2087 },
2088 {
2089 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2090 .name = "Power LED Switch",
2091 .info = snd_audigy2nx_led_info,
2092 .get = snd_audigy2nx_led_get,
2093 .put = snd_audigy2nx_led_put,
2094 .private_value = 1,
2095 },
2096 {
2097 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2098 .name = "Dolby Digital LED Switch",
2099 .info = snd_audigy2nx_led_info,
2100 .get = snd_audigy2nx_led_get,
2101 .put = snd_audigy2nx_led_put,
2102 .private_value = 2,
2103 },
2104};
2105
2106static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
2107{
2108 int i, err;
2109
2110 for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
2111 if (i > 1 && /* Live24ext has 2 LEDs only */
2112 (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
2113 mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
2114 break;
2115 err = snd_ctl_add(mixer->chip->card,
2116 snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
2117 if (err < 0)
2118 return err;
2119 }
2120 mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
2121 return 0;
2122}
2123
2124static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
2125 struct snd_info_buffer *buffer)
2126{
2127 static const struct sb_jack {
2128 int unitid;
2129 const char *name;
2130 } jacks_audigy2nx[] = {
2131 {4, "dig in "},
2132 {7, "line in"},
2133 {19, "spk out"},
2134 {20, "hph out"},
2135 {-1, NULL}
2136 }, jacks_live24ext[] = {
2137 {4, "line in"}, /* &1=Line, &2=Mic*/
2138 {3, "hph out"}, /* headphones */
2139 {0, "RC "}, /* last command, 6 bytes see rc_config above */
2140 {-1, NULL}
2141 };
2142 const struct sb_jack *jacks;
2143 struct usb_mixer_interface *mixer = entry->private_data;
2144 int i, err;
2145 u8 buf[3];
2146
2147 snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
2148 if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
2149 jacks = jacks_audigy2nx;
2150 else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
2151 mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
2152 jacks = jacks_live24ext;
2153 else
2154 return;
2155
2156 for (i = 0; jacks[i].name; ++i) {
2157 snd_iprintf(buffer, "%s: ", jacks[i].name);
2158 err = snd_usb_ctl_msg(mixer->chip->dev,
2159 usb_rcvctrlpipe(mixer->chip->dev, 0),
2160 UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
2161 USB_RECIP_INTERFACE, 0,
2162 jacks[i].unitid << 8, buf, 3, 100);
2163 if (err == 3 && (buf[0] == 3 || buf[0] == 6))
2164 snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
2165 else
2166 snd_iprintf(buffer, "?\n");
2167 }
2168}
2169
2170static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
2171 struct snd_ctl_elem_value *ucontrol)
2172{
2173 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
2174
2175 ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02);
2176 return 0;
2177}
2178
2179static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
2180 struct snd_ctl_elem_value *ucontrol)
2181{
2182 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
2183 u8 old_status, new_status;
2184 int err, changed;
2185
2186 old_status = mixer->xonar_u1_status;
2187 if (ucontrol->value.integer.value[0])
2188 new_status = old_status | 0x02;
2189 else
2190 new_status = old_status & ~0x02;
2191 changed = new_status != old_status;
2192 err = snd_usb_ctl_msg(mixer->chip->dev,
2193 usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
2194 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
2195 50, 0, &new_status, 1, 100);
2196 if (err < 0)
2197 return err;
2198 mixer->xonar_u1_status = new_status;
2199 return changed;
2200}
2201
2202static struct snd_kcontrol_new snd_xonar_u1_output_switch = {
2203 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2204 .name = "Digital Playback Switch",
2205 .info = snd_ctl_boolean_mono_info,
2206 .get = snd_xonar_u1_switch_get,
2207 .put = snd_xonar_u1_switch_put,
2208};
2209
2210static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
2211{
2212 int err;
2213
2214 err = snd_ctl_add(mixer->chip->card,
2215 snd_ctl_new1(&snd_xonar_u1_output_switch, mixer));
2216 if (err < 0)
2217 return err;
2218 mixer->xonar_u1_status = 0x05;
2219 return 0;
2220}
2221
2222void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
2223 unsigned char samplerate_id)
2224{
2225 struct usb_mixer_interface *mixer;
2226 struct usb_mixer_elem_info *cval;
2227 int unitid = 12; /* SamleRate ExtensionUnit ID */
2228
2229 list_for_each_entry(mixer, &chip->mixer_list, list) {
2230 cval = mixer->id_elems[unitid];
2231 if (cval) {
2232 set_cur_ctl_value(cval, cval->control << 8,
2233 samplerate_id);
2234 snd_usb_mixer_notify_id(mixer, unitid);
2235 }
2236 break;
2237 }
2238}
2239
2240int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, 1855int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
2241 int ignore_error) 1856 int ignore_error)
2242{ 1857{
@@ -2277,25 +1892,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
2277 (err = snd_usb_mixer_status_create(mixer)) < 0) 1892 (err = snd_usb_mixer_status_create(mixer)) < 0)
2278 goto _error; 1893 goto _error;
2279 1894
2280 if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) 1895 snd_usb_mixer_apply_create_quirk(mixer);
2281 goto _error;
2282
2283 if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
2284 mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
2285 mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
2286 if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
2287 goto _error;
2288 if (!snd_card_proc_new(chip->card, "audigy2nx", &entry))
2289 snd_info_set_text_ops(entry, mixer,
2290 snd_audigy2nx_proc_read);
2291 }
2292
2293 if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) ||
2294 mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) {
2295 err = snd_xonar_u1_controls_create(mixer);
2296 if (err < 0)
2297 goto _error;
2298 }
2299 1896
2300 err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); 1897 err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
2301 if (err < 0) 1898 if (err < 0)
@@ -2316,7 +1913,7 @@ _error:
2316void snd_usb_mixer_disconnect(struct list_head *p) 1913void snd_usb_mixer_disconnect(struct list_head *p)
2317{ 1914{
2318 struct usb_mixer_interface *mixer; 1915 struct usb_mixer_interface *mixer;
2319 1916
2320 mixer = list_entry(p, struct usb_mixer_interface, list); 1917 mixer = list_entry(p, struct usb_mixer_interface, list);
2321 usb_kill_urb(mixer->urb); 1918 usb_kill_urb(mixer->urb);
2322 usb_kill_urb(mixer->rc_urb); 1919 usb_kill_urb(mixer->rc_urb);
diff --git a/sound/usb/usbmixer.h b/sound/usb/usbmixer.h
index e199e4bb02f2..63101ae201cc 100644
--- a/sound/usb/usbmixer.h
+++ b/sound/usb/usbmixer.h
@@ -1,11 +1,52 @@
1#ifndef __USBMIXER_H 1#ifndef __USBMIXER_H
2#define __USBMIXER_H 2#define __USBMIXER_H
3 3
4struct usb_mixer_interface {
5 struct snd_usb_audio *chip;
6 unsigned int ctrlif;
7 struct list_head list;
8 unsigned int ignore_ctl_error;
9 struct urb *urb;
10 /* array[MAX_ID_ELEMS], indexed by unit id */
11 struct usb_mixer_elem_info **id_elems;
12
13 /* Sound Blaster remote control stuff */
14 const struct rc_config *rc_cfg;
15 u32 rc_code;
16 wait_queue_head_t rc_waitq;
17 struct urb *rc_urb;
18 struct usb_ctrlrequest *rc_setup_packet;
19 u8 rc_buffer[6];
20
21 u8 audigy2nx_leds[3];
22 u8 xonar_u1_status;
23};
24
25#define MAX_CHANNELS 10 /* max logical channels */
26
27struct usb_mixer_elem_info {
28 struct usb_mixer_interface *mixer;
29 struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
30 struct snd_ctl_elem_id *elem_id;
31 unsigned int id;
32 unsigned int control; /* CS or ICN (high byte) */
33 unsigned int cmask; /* channel mask bitmap: 0 = master */
34 int channels;
35 int val_type;
36 int min, max, res;
37 int dBmin, dBmax;
38 int cached;
39 int cache_val[MAX_CHANNELS];
40 u8 initialized;
41};
42
4int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, 43int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
5 int ignore_error); 44 int ignore_error);
6void snd_usb_mixer_disconnect(struct list_head *p); 45void snd_usb_mixer_disconnect(struct list_head *p);
7 46
8void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, 47void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
9 unsigned char samplerate_id); 48
49int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
50 int request, int validx, int value_set);
10 51
11#endif /* __USBMIXER_H */ 52#endif /* __USBMIXER_H */