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/slab.h>
30#include <linux/usb.h>
31#include <linux/usb/audio.h>
32
33#include <sound/core.h>
34#include <sound/control.h>
35#include <sound/hwdep.h>
36#include <sound/info.h>
37
38#include "usbaudio.h"
39#include "mixer.h"
40#include "mixer_quirks.h"
41#include "helper.h"
42
43/*
44 * Sound Blaster remote control configuration
45 *
46 * format of remote control data:
47 * Extigy:       xx 00
48 * Audigy 2 NX:  06 80 xx 00 00 00
49 * Live! 24-bit: 06 80 xx yy 22 83
50 */
51static const struct rc_config {
52	u32 usb_id;
53	u8  offset;
54	u8  length;
55	u8  packet_length;
56	u8  min_packet_length; /* minimum accepted length of the URB result */
57	u8  mute_mixer_id;
58	u32 mute_code;
59} rc_configs[] = {
60	{ USB_ID(0x041e, 0x3000), 0, 1, 2, 1,  18, 0x0013 }, /* Extigy       */
61	{ USB_ID(0x041e, 0x3020), 2, 1, 6, 6,  18, 0x0013 }, /* Audigy 2 NX  */
62	{ USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
63	{ USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
64};
65
66static void snd_usb_soundblaster_remote_complete(struct urb *urb)
67{
68	struct usb_mixer_interface *mixer = urb->context;
69	const struct rc_config *rc = mixer->rc_cfg;
70	u32 code;
71
72	if (urb->status < 0 || urb->actual_length < rc->min_packet_length)
73		return;
74
75	code = mixer->rc_buffer[rc->offset];
76	if (rc->length == 2)
77		code |= mixer->rc_buffer[rc->offset + 1] << 8;
78
79	/* the Mute button actually changes the mixer control */
80	if (code == rc->mute_code)
81		snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
82	mixer->rc_code = code;
83	wmb();
84	wake_up(&mixer->rc_waitq);
85}
86
87static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf,
88				     long count, loff_t *offset)
89{
90	struct usb_mixer_interface *mixer = hw->private_data;
91	int err;
92	u32 rc_code;
93
94	if (count != 1 && count != 4)
95		return -EINVAL;
96	err = wait_event_interruptible(mixer->rc_waitq,
97				       (rc_code = xchg(&mixer->rc_code, 0)) != 0);
98	if (err == 0) {
99		if (count == 1)
100			err = put_user(rc_code, buf);
101		else
102			err = put_user(rc_code, (u32 __user *)buf);
103	}
104	return err < 0 ? err : count;
105}
106
107static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *file,
108					    poll_table *wait)
109{
110	struct usb_mixer_interface *mixer = hw->private_data;
111
112	poll_wait(file, &mixer->rc_waitq, wait);
113	return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
114}
115
116static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
117{
118	struct snd_hwdep *hwdep;
119	int err, len, i;
120
121	for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
122		if (rc_configs[i].usb_id == mixer->chip->usb_id)
123			break;
124	if (i >= ARRAY_SIZE(rc_configs))
125		return 0;
126	mixer->rc_cfg = &rc_configs[i];
127
128	len = mixer->rc_cfg->packet_length;
129
130	init_waitqueue_head(&mixer->rc_waitq);
131	err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
132	if (err < 0)
133		return err;
134	snprintf(hwdep->name, sizeof(hwdep->name),
135		 "%s remote control", mixer->chip->card->shortname);
136	hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
137	hwdep->private_data = mixer;
138	hwdep->ops.read = snd_usb_sbrc_hwdep_read;
139	hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
140	hwdep->exclusive = 1;
141
142	mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
143	if (!mixer->rc_urb)
144		return -ENOMEM;
145	mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
146	if (!mixer->rc_setup_packet) {
147		usb_free_urb(mixer->rc_urb);
148		mixer->rc_urb = NULL;
149		return -ENOMEM;
150	}
151	mixer->rc_setup_packet->bRequestType =
152		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
153	mixer->rc_setup_packet->bRequest = UAC_GET_MEM;
154	mixer->rc_setup_packet->wValue = cpu_to_le16(0);
155	mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
156	mixer->rc_setup_packet->wLength = cpu_to_le16(len);
157	usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
158			     usb_rcvctrlpipe(mixer->chip->dev, 0),
159			     (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
160			     snd_usb_soundblaster_remote_complete, mixer);
161	return 0;
162}
163
164#define snd_audigy2nx_led_info		snd_ctl_boolean_mono_info
165
166static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
167{
168	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
169	int index = kcontrol->private_value;
170
171	ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
172	return 0;
173}
174
175static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
176{
177	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
178	int index = kcontrol->private_value;
179	int value = ucontrol->value.integer.value[0];
180	int err, changed;
181
182	if (value > 1)
183		return -EINVAL;
184	changed = value != mixer->audigy2nx_leds[index];
185	err = snd_usb_ctl_msg(mixer->chip->dev,
186			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
187			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
188			      value, index + 2, NULL, 0, 100);
189	if (err < 0)
190		return err;
191	mixer->audigy2nx_leds[index] = value;
192	return changed;
193}
194
195static struct snd_kcontrol_new snd_audigy2nx_controls[] = {
196	{
197		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
198		.name = "CMSS LED Switch",
199		.info = snd_audigy2nx_led_info,
200		.get = snd_audigy2nx_led_get,
201		.put = snd_audigy2nx_led_put,
202		.private_value = 0,
203	},
204	{
205		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
206		.name = "Power LED Switch",
207		.info = snd_audigy2nx_led_info,
208		.get = snd_audigy2nx_led_get,
209		.put = snd_audigy2nx_led_put,
210		.private_value = 1,
211	},
212	{
213		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
214		.name = "Dolby Digital LED Switch",
215		.info = snd_audigy2nx_led_info,
216		.get = snd_audigy2nx_led_get,
217		.put = snd_audigy2nx_led_put,
218		.private_value = 2,
219	},
220};
221
222static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
223{
224	int i, err;
225
226	for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
227		if (i > 1 && /* Live24ext has 2 LEDs only */
228			(mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
229			 mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
230			break;
231		err = snd_ctl_add(mixer->chip->card,
232				  snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
233		if (err < 0)
234			return err;
235	}
236	mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
237	return 0;
238}
239
240static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
241				    struct snd_info_buffer *buffer)
242{
243	static const struct sb_jack {
244		int unitid;
245		const char *name;
246	}  jacks_audigy2nx[] = {
247		{4,  "dig in "},
248		{7,  "line in"},
249		{19, "spk out"},
250		{20, "hph out"},
251		{-1, NULL}
252	}, jacks_live24ext[] = {
253		{4,  "line in"}, /* &1=Line, &2=Mic*/
254		{3,  "hph out"}, /* headphones */
255		{0,  "RC     "}, /* last command, 6 bytes see rc_config above */
256		{-1, NULL}
257	};
258	const struct sb_jack *jacks;
259	struct usb_mixer_interface *mixer = entry->private_data;
260	int i, err;
261	u8 buf[3];
262
263	snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
264	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
265		jacks = jacks_audigy2nx;
266	else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
267		 mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
268		jacks = jacks_live24ext;
269	else
270		return;
271
272	for (i = 0; jacks[i].name; ++i) {
273		snd_iprintf(buffer, "%s: ", jacks[i].name);
274		err = snd_usb_ctl_msg(mixer->chip->dev,
275				      usb_rcvctrlpipe(mixer->chip->dev, 0),
276				      UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
277				      USB_RECIP_INTERFACE, 0,
278				      jacks[i].unitid << 8, buf, 3, 100);
279		if (err == 3 && (buf[0] == 3 || buf[0] == 6))
280			snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
281		else
282			snd_iprintf(buffer, "?\n");
283	}
284}
285
286static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
287				   struct snd_ctl_elem_value *ucontrol)
288{
289	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
290
291	ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02);
292	return 0;
293}
294
295static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
296				   struct snd_ctl_elem_value *ucontrol)
297{
298	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
299	u8 old_status, new_status;
300	int err, changed;
301
302	old_status = mixer->xonar_u1_status;
303	if (ucontrol->value.integer.value[0])
304		new_status = old_status | 0x02;
305	else
306		new_status = old_status & ~0x02;
307	changed = new_status != old_status;
308	err = snd_usb_ctl_msg(mixer->chip->dev,
309			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
310			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
311			      50, 0, &new_status, 1, 100);
312	if (err < 0)
313		return err;
314	mixer->xonar_u1_status = new_status;
315	return changed;
316}
317
318static struct snd_kcontrol_new snd_xonar_u1_output_switch = {
319	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
320	.name = "Digital Playback Switch",
321	.info = snd_ctl_boolean_mono_info,
322	.get = snd_xonar_u1_switch_get,
323	.put = snd_xonar_u1_switch_put,
324};
325
326static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
327{
328	int err;
329
330	err = snd_ctl_add(mixer->chip->card,
331			  snd_ctl_new1(&snd_xonar_u1_output_switch, mixer));
332	if (err < 0)
333		return err;
334	mixer->xonar_u1_status = 0x05;
335	return 0;
336}
337
338void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
339			       unsigned char samplerate_id)
340{
341	struct usb_mixer_interface *mixer;
342	struct usb_mixer_elem_info *cval;
343	int unitid = 12; /* SamleRate ExtensionUnit ID */
344
345	list_for_each_entry(mixer, &chip->mixer_list, list) {
346		cval = mixer->id_elems[unitid];
347		if (cval) {
348			snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
349						    cval->control << 8,
350						    samplerate_id);
351			snd_usb_mixer_notify_id(mixer, unitid);
352		}
353		break;
354	}
355}
356
357int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
358{
359	int err;
360	struct snd_info_entry *entry;
361
362	if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
363		return err;
364
365	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
366	    mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
367	    mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
368		if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
369			return err;
370		if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
371			snd_info_set_text_ops(entry, mixer,
372					      snd_audigy2nx_proc_read);
373	}
374
375	if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) ||
376	    mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) {
377		err = snd_xonar_u1_controls_create(mixer);
378		if (err < 0)
379			return err;
380	}
381
382	return 0;
383}
384
385void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
386				    int unitid)
387{
388	if (!mixer->rc_cfg)
389		return;
390	/* unit ids specific to Extigy/Audigy 2 NX: */
391	switch (unitid) {
392	case 0: /* remote control */
393		mixer->rc_urb->dev = mixer->chip->dev;
394		usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
395		break;
396	case 4: /* digital in jack */
397	case 7: /* line in jacks */
398	case 19: /* speaker out jacks */
399	case 20: /* headphones out jack */
400		break;
401	/* live24ext: 4 = line-in jack */
402	case 3:	/* hp-out jack (may actuate Mute) */
403		if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
404		    mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
405			snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
406		break;
407	default:
408		snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
409		break;
410	}
411}
412