Commit | Line | Data |
---|---|---|
76b188c4 CA |
1 | /* |
2 | * Scarlett Driver for ALSA | |
3 | * | |
4 | * Copyright (c) 2013 by Tobias Hoffmann | |
5 | * Copyright (c) 2013 by Robin Gareus <robin at gareus.org> | |
6 | * Copyright (c) 2002 by Takashi Iwai <tiwai at suse.de> | |
7 | * Copyright (c) 2014 by Chris J Arges <chris.j.arges at canonical.com> | |
8 | * | |
9 | * Many codes borrowed from audio.c by | |
10 | * Alan Cox (alan at lxorguk.ukuu.org.uk) | |
11 | * Thomas Sailer (sailer at ife.ee.ethz.ch) | |
12 | * | |
13 | * Code cleanup: | |
14 | * David Henningsson <david.henningsson at canonical.com> | |
15 | * | |
16 | * This program is free software; you can redistribute it and/or modify | |
17 | * it under the terms of the GNU General Public License as published by | |
18 | * the Free Software Foundation; either version 2 of the License, or | |
19 | * (at your option) any later version. | |
20 | * | |
21 | * This program is distributed in the hope that it will be useful, | |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | * GNU General Public License for more details. | |
25 | * | |
26 | */ | |
27 | ||
28 | /* | |
29 | * Rewritten and extended to support more models, e.g. Scarlett 18i8. | |
30 | * | |
31 | * Auto-detection via UAC2 is not feasible to properly discover the vast | |
32 | * majority of features. It's related to both Linux/ALSA's UAC2 as well as | |
33 | * Focusrite's implementation of it. Eventually quirks may be sufficient but | |
34 | * right now it's a major headache to work arount these things. | |
35 | * | |
36 | * NB. Neither the OSX nor the win driver provided by Focusrite performs | |
37 | * discovery, they seem to operate the same as this driver. | |
38 | */ | |
39 | ||
40 | /* Mixer Interface for the Focusrite Scarlett 18i6 audio interface. | |
41 | * | |
42 | * The protocol was reverse engineered by looking at communication between | |
43 | * Scarlett MixControl (v 1.2.128.0) and the Focusrite(R) Scarlett 18i6 | |
44 | * (firmware v305) using wireshark and usbmon in January 2013. | |
45 | * Extended in July 2013. | |
46 | * | |
47 | * this mixer gives complete access to all features of the device: | |
48 | * - change Impedance of inputs (Line-in, Mic / Instrument, Hi-Z) | |
49 | * - select clock source | |
50 | * - dynamic input to mixer-matrix assignment | |
51 | * - 18 x 6 mixer-matrix gain stages | |
52 | * - bus routing & volume control | |
53 | * - automatic re-initialization on connect if device was power-cycled | |
54 | * | |
55 | * USB URB commands overview (bRequest = 0x01 = UAC2_CS_CUR) | |
56 | * wIndex | |
57 | * 0x01 Analog Input line/instrument impedance switch, wValue=0x0901 + | |
58 | * channel, data=Line/Inst (2bytes) | |
59 | * pad (-10dB) switch, wValue=0x0b01 + channel, data=Off/On (2bytes) | |
60 | * ?? wValue=0x0803/04, ?? (2bytes) | |
61 | * 0x0a Master Volume, wValue=0x0200+bus[0:all + only 1..4?] data(2bytes) | |
62 | * Bus Mute/Unmute wValue=0x0100+bus[0:all + only 1..4?], data(2bytes) | |
63 | * 0x28 Clock source, wValue=0x0100, data={1:int,2:spdif,3:adat} (1byte) | |
64 | * 0x29 Set Sample-rate, wValue=0x0100, data=sample-rate(4bytes) | |
65 | * 0x32 Mixer mux, wValue=0x0600 + mixer-channel, data=input-to-connect(2bytes) | |
66 | * 0x33 Output mux, wValue=bus, data=input-to-connect(2bytes) | |
67 | * 0x34 Capture mux, wValue=0...18, data=input-to-connect(2bytes) | |
68 | * 0x3c Matrix Mixer gains, wValue=mixer-node data=gain(2bytes) | |
69 | * ?? [sometimes](4bytes, e.g 0x000003be 0x000003bf ...03ff) | |
70 | * | |
71 | * USB reads: (i.e. actually issued by original software) | |
72 | * 0x01 wValue=0x0901+channel (1byte!!), wValue=0x0b01+channed (1byte!!) | |
73 | * 0x29 wValue=0x0100 sample-rate(4bytes) | |
74 | * wValue=0x0200 ?? 1byte (only once) | |
75 | * 0x2a wValue=0x0100 ?? 4bytes, sample-rate2 ?? | |
76 | * | |
77 | * USB reads with bRequest = 0x03 = UAC2_CS_MEM | |
78 | * 0x3c wValue=0x0002 1byte: sync status (locked=1) | |
79 | * wValue=0x0000 18*2byte: peak meter (inputs) | |
80 | * wValue=0x0001 8(?)*2byte: peak meter (mix) | |
81 | * wValue=0x0003 6*2byte: peak meter (pcm/daw) | |
82 | * | |
83 | * USB write with bRequest = 0x03 | |
84 | * 0x3c Save settings to hardware: wValue=0x005a, data=0xa5 | |
85 | * | |
86 | * | |
87 | * <ditaa> | |
88 | * /--------------\ 18chn 6chn /--------------\ | |
89 | * | Hardware in +--+-------\ /------+--+ ALSA PCM out | | |
90 | * \--------------/ | | | | \--------------/ | |
91 | * | | | | | |
92 | * | v v | | |
93 | * | +---------------+ | | |
94 | * | \ Matrix Mux / | | |
95 | * | +-----+-----+ | | |
96 | * | | | | |
97 | * | | 18chn | | |
98 | * | v | | |
99 | * | +-----------+ | | |
100 | * | | Mixer | | | |
101 | * | | Matrix | | | |
102 | * | | | | | |
103 | * | | 18x6 Gain | | | |
104 | * | | stages | | | |
105 | * | +-----+-----+ | | |
106 | * | | | | |
107 | * | | | | |
108 | * | 18chn | 6chn | 6chn | |
109 | * v v v | |
110 | * ========================= | |
111 | * +---------------+ +--—------------+ | |
112 | * \ Output Mux / \ Capture Mux / | |
113 | * +-----+-----+ +-----+-----+ | |
114 | * | | | |
115 | * | 6chn | | |
116 | * v | | |
117 | * +-------------+ | | |
118 | * | Master Gain | | | |
119 | * +------+------+ | | |
120 | * | | | |
121 | * | 6chn | 18chn | |
122 | * | (3 stereo pairs) | | |
123 | * /--------------\ | | /--------------\ | |
124 | * | Hardware out |<--/ \-->| ALSA PCM in | | |
125 | * \--------------/ \--------------/ | |
126 | * </ditaa> | |
127 | * | |
128 | */ | |
129 | ||
130 | #include <linux/slab.h> | |
131 | #include <linux/usb.h> | |
132 | #include <linux/usb/audio-v2.h> | |
133 | ||
134 | #include <sound/core.h> | |
135 | #include <sound/control.h> | |
136 | #include <sound/tlv.h> | |
137 | ||
138 | #include "usbaudio.h" | |
139 | #include "mixer.h" | |
140 | #include "helper.h" | |
141 | #include "power.h" | |
142 | ||
143 | #include "mixer_scarlett.h" | |
144 | ||
145 | /* some gui mixers can't handle negative ctl values */ | |
146 | #define SND_SCARLETT_LEVEL_BIAS 128 | |
147 | #define SND_SCARLETT_MATRIX_IN_MAX 18 | |
148 | #define SND_SCARLETT_CONTROLS_MAX 10 | |
149 | #define SND_SCARLETT_OFFSETS_MAX 5 | |
150 | ||
151 | enum { | |
152 | SCARLETT_OUTPUTS, | |
153 | SCARLETT_SWITCH_IMPEDANCE, | |
154 | SCARLETT_SWITCH_PAD, | |
155 | }; | |
156 | ||
157 | enum { | |
158 | SCARLETT_OFFSET_PCM = 0, | |
159 | SCARLETT_OFFSET_ANALOG = 1, | |
160 | SCARLETT_OFFSET_SPDIF = 2, | |
161 | SCARLETT_OFFSET_ADAT = 3, | |
162 | SCARLETT_OFFSET_MIX = 4, | |
163 | }; | |
164 | ||
165 | struct scarlett_mixer_elem_enum_info { | |
166 | int start; | |
167 | int len; | |
168 | int offsets[SND_SCARLETT_OFFSETS_MAX]; | |
169 | char const * const *names; | |
170 | }; | |
171 | ||
172 | struct scarlett_mixer_control { | |
173 | unsigned char num; | |
174 | unsigned char type; | |
175 | const char *name; | |
176 | }; | |
177 | ||
178 | struct scarlett_device_info { | |
179 | int matrix_in; | |
180 | int matrix_out; | |
181 | int input_len; | |
182 | int output_len; | |
183 | ||
184 | struct scarlett_mixer_elem_enum_info opt_master; | |
185 | struct scarlett_mixer_elem_enum_info opt_matrix; | |
186 | ||
187 | /* initial values for matrix mux */ | |
188 | int matrix_mux_init[SND_SCARLETT_MATRIX_IN_MAX]; | |
189 | ||
190 | int num_controls; /* number of items in controls */ | |
191 | const struct scarlett_mixer_control controls[SND_SCARLETT_CONTROLS_MAX]; | |
192 | }; | |
193 | ||
194 | /********************** Enum Strings *************************/ | |
195 | ||
196 | static const struct scarlett_mixer_elem_enum_info opt_pad = { | |
197 | .start = 0, | |
198 | .len = 2, | |
199 | .offsets = {}, | |
200 | .names = (char const * const []){ | |
201 | "0dB", "-10dB" | |
202 | } | |
203 | }; | |
204 | ||
205 | static const struct scarlett_mixer_elem_enum_info opt_impedance = { | |
206 | .start = 0, | |
207 | .len = 2, | |
208 | .offsets = {}, | |
209 | .names = (char const * const []){ | |
210 | "Line", "Hi-Z" | |
211 | } | |
212 | }; | |
213 | ||
214 | static const struct scarlett_mixer_elem_enum_info opt_clock = { | |
215 | .start = 1, | |
216 | .len = 3, | |
217 | .offsets = {}, | |
218 | .names = (char const * const []){ | |
219 | "Internal", "SPDIF", "ADAT" | |
220 | } | |
221 | }; | |
222 | ||
223 | static const struct scarlett_mixer_elem_enum_info opt_sync = { | |
224 | .start = 0, | |
225 | .len = 2, | |
226 | .offsets = {}, | |
227 | .names = (char const * const []){ | |
228 | "No Lock", "Locked" | |
229 | } | |
230 | }; | |
231 | ||
232 | static int scarlett_ctl_switch_info(struct snd_kcontrol *kctl, | |
233 | struct snd_ctl_elem_info *uinfo) | |
234 | { | |
235 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
236 | ||
237 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | |
238 | uinfo->count = elem->channels; | |
239 | uinfo->value.integer.min = 0; | |
240 | uinfo->value.integer.max = 1; | |
241 | return 0; | |
242 | } | |
243 | ||
244 | static int scarlett_ctl_switch_get(struct snd_kcontrol *kctl, | |
245 | struct snd_ctl_elem_value *ucontrol) | |
246 | { | |
247 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
248 | int i, err, val; | |
249 | ||
250 | for (i = 0; i < elem->channels; i++) { | |
251 | err = snd_usb_get_cur_mix_value(elem, i, i, &val); | |
252 | if (err < 0) | |
253 | return err; | |
254 | ||
255 | val = !val; /* invert mute logic for mixer */ | |
256 | ucontrol->value.integer.value[i] = val; | |
257 | } | |
258 | ||
259 | return 0; | |
260 | } | |
261 | ||
262 | static int scarlett_ctl_switch_put(struct snd_kcontrol *kctl, | |
263 | struct snd_ctl_elem_value *ucontrol) | |
264 | { | |
265 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
266 | int i, changed = 0; | |
267 | int err, oval, val; | |
268 | ||
269 | for (i = 0; i < elem->channels; i++) { | |
270 | err = snd_usb_get_cur_mix_value(elem, i, i, &oval); | |
271 | if (err < 0) | |
272 | return err; | |
273 | ||
274 | val = ucontrol->value.integer.value[i]; | |
275 | val = !val; | |
276 | if (oval != val) { | |
277 | err = snd_usb_set_cur_mix_value(elem, i, i, val); | |
278 | if (err < 0) | |
279 | return err; | |
280 | ||
281 | changed = 1; | |
282 | } | |
283 | } | |
284 | ||
285 | return changed; | |
286 | } | |
287 | ||
288 | static int scarlett_ctl_info(struct snd_kcontrol *kctl, | |
289 | struct snd_ctl_elem_info *uinfo) | |
290 | { | |
291 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
292 | ||
293 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
294 | uinfo->count = elem->channels; | |
295 | uinfo->value.integer.min = 0; | |
296 | uinfo->value.integer.max = (int)kctl->private_value + | |
297 | SND_SCARLETT_LEVEL_BIAS; | |
298 | uinfo->value.integer.step = 1; | |
299 | return 0; | |
300 | } | |
301 | ||
302 | static int scarlett_ctl_get(struct snd_kcontrol *kctl, | |
303 | struct snd_ctl_elem_value *ucontrol) | |
304 | { | |
305 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
306 | int i, err, val; | |
307 | ||
308 | for (i = 0; i < elem->channels; i++) { | |
309 | err = snd_usb_get_cur_mix_value(elem, i, i, &val); | |
310 | if (err < 0) | |
311 | return err; | |
312 | ||
313 | val = clamp(val / 256, -128, (int)kctl->private_value) + | |
314 | SND_SCARLETT_LEVEL_BIAS; | |
315 | ucontrol->value.integer.value[i] = val; | |
316 | } | |
317 | ||
318 | return 0; | |
319 | } | |
320 | ||
321 | static int scarlett_ctl_put(struct snd_kcontrol *kctl, | |
322 | struct snd_ctl_elem_value *ucontrol) | |
323 | { | |
324 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
325 | int i, changed = 0; | |
326 | int err, oval, val; | |
327 | ||
328 | for (i = 0; i < elem->channels; i++) { | |
329 | err = snd_usb_get_cur_mix_value(elem, i, i, &oval); | |
330 | if (err < 0) | |
331 | return err; | |
332 | ||
333 | val = ucontrol->value.integer.value[i] - | |
334 | SND_SCARLETT_LEVEL_BIAS; | |
335 | val = val * 256; | |
336 | if (oval != val) { | |
337 | err = snd_usb_set_cur_mix_value(elem, i, i, val); | |
338 | if (err < 0) | |
339 | return err; | |
340 | ||
341 | changed = 1; | |
342 | } | |
343 | } | |
344 | ||
345 | return changed; | |
346 | } | |
347 | ||
348 | static void scarlett_generate_name(int i, char *dst, int offsets[]) | |
349 | { | |
350 | if (i > offsets[SCARLETT_OFFSET_MIX]) | |
351 | sprintf(dst, "Mix %c", | |
352 | 'A'+(i - offsets[SCARLETT_OFFSET_MIX] - 1)); | |
353 | else if (i > offsets[SCARLETT_OFFSET_ADAT]) | |
354 | sprintf(dst, "ADAT %d", i - offsets[SCARLETT_OFFSET_ADAT]); | |
355 | else if (i > offsets[SCARLETT_OFFSET_SPDIF]) | |
356 | sprintf(dst, "SPDIF %d", i - offsets[SCARLETT_OFFSET_SPDIF]); | |
357 | else if (i > offsets[SCARLETT_OFFSET_ANALOG]) | |
358 | sprintf(dst, "Analog %d", i - offsets[SCARLETT_OFFSET_ANALOG]); | |
359 | else if (i > offsets[SCARLETT_OFFSET_PCM]) | |
360 | sprintf(dst, "PCM %d", i - offsets[SCARLETT_OFFSET_PCM]); | |
361 | else | |
362 | sprintf(dst, "Off"); | |
363 | } | |
364 | ||
365 | static int scarlett_ctl_enum_dynamic_info(struct snd_kcontrol *kctl, | |
366 | struct snd_ctl_elem_info *uinfo) | |
367 | { | |
368 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
369 | struct scarlett_mixer_elem_enum_info *opt = elem->private_data; | |
370 | unsigned int items = opt->len; | |
371 | ||
372 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | |
373 | uinfo->count = elem->channels; | |
374 | uinfo->value.enumerated.items = items; | |
375 | ||
376 | if (uinfo->value.enumerated.item >= items) | |
377 | uinfo->value.enumerated.item = items - 1; | |
378 | ||
379 | /* generate name dynamically based on item number and offset info */ | |
380 | scarlett_generate_name(uinfo->value.enumerated.item, | |
381 | uinfo->value.enumerated.name, | |
382 | opt->offsets); | |
383 | ||
384 | return 0; | |
385 | } | |
386 | ||
387 | static int scarlett_ctl_enum_info(struct snd_kcontrol *kctl, | |
388 | struct snd_ctl_elem_info *uinfo) | |
389 | { | |
390 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
391 | struct scarlett_mixer_elem_enum_info *opt = elem->private_data; | |
392 | ||
393 | return snd_ctl_enum_info(uinfo, elem->channels, opt->len, | |
394 | (const char * const *)opt->names); | |
395 | } | |
396 | ||
397 | static int scarlett_ctl_enum_get(struct snd_kcontrol *kctl, | |
398 | struct snd_ctl_elem_value *ucontrol) | |
399 | { | |
400 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
401 | struct scarlett_mixer_elem_enum_info *opt = elem->private_data; | |
402 | int err, val; | |
403 | ||
404 | err = snd_usb_get_cur_mix_value(elem, 0, 0, &val); | |
405 | if (err < 0) | |
406 | return err; | |
407 | ||
408 | val = clamp(val - opt->start, 0, opt->len-1); | |
409 | ||
410 | ucontrol->value.enumerated.item[0] = val; | |
411 | ||
412 | return 0; | |
413 | } | |
414 | ||
415 | static int scarlett_ctl_enum_put(struct snd_kcontrol *kctl, | |
416 | struct snd_ctl_elem_value *ucontrol) | |
417 | { | |
418 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
419 | struct scarlett_mixer_elem_enum_info *opt = elem->private_data; | |
420 | int err, oval, val; | |
421 | ||
422 | err = snd_usb_get_cur_mix_value(elem, 0, 0, &oval); | |
423 | if (err < 0) | |
424 | return err; | |
425 | ||
426 | val = ucontrol->value.integer.value[0]; | |
427 | val = val + opt->start; | |
428 | if (val != oval) { | |
429 | snd_usb_set_cur_mix_value(elem, 0, 0, val); | |
430 | return 1; | |
431 | } | |
432 | return 0; | |
433 | } | |
434 | ||
435 | static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl, | |
436 | struct snd_ctl_elem_value *ucontrol) | |
437 | { | |
438 | struct usb_mixer_elem_info *elem = kctl->private_data; | |
439 | struct snd_usb_audio *chip = elem->mixer->chip; | |
440 | unsigned char buf[2 * MAX_CHANNELS] = {0, }; | |
441 | int wValue = (elem->control << 8) | elem->idx_off; | |
442 | int idx = snd_usb_ctrl_intf(chip) | (elem->id << 8); | |
443 | int err; | |
444 | ||
445 | err = snd_usb_ctl_msg(chip->dev, | |
446 | usb_rcvctrlpipe(chip->dev, 0), | |
447 | UAC2_CS_MEM, | |
448 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | | |
449 | USB_DIR_IN, wValue, idx, buf, elem->channels); | |
450 | if (err < 0) | |
451 | return err; | |
452 | ||
453 | ucontrol->value.enumerated.item[0] = clamp((int)buf[0], 0, 1); | |
454 | return 0; | |
455 | } | |
456 | ||
457 | static struct snd_kcontrol_new usb_scarlett_ctl_switch = { | |
458 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
459 | .name = "", | |
460 | .info = scarlett_ctl_switch_info, | |
461 | .get = scarlett_ctl_switch_get, | |
462 | .put = scarlett_ctl_switch_put, | |
463 | }; | |
464 | ||
465 | static const DECLARE_TLV_DB_SCALE(db_scale_scarlett_gain, -12800, 100, 0); | |
466 | ||
467 | static struct snd_kcontrol_new usb_scarlett_ctl = { | |
468 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
469 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | |
470 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | |
471 | .name = "", | |
472 | .info = scarlett_ctl_info, | |
473 | .get = scarlett_ctl_get, | |
474 | .put = scarlett_ctl_put, | |
475 | .private_value = 6, /* max value */ | |
476 | .tlv = { .p = db_scale_scarlett_gain } | |
477 | }; | |
478 | ||
479 | static struct snd_kcontrol_new usb_scarlett_ctl_master = { | |
480 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
481 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | |
482 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | |
483 | .name = "", | |
484 | .info = scarlett_ctl_info, | |
485 | .get = scarlett_ctl_get, | |
486 | .put = scarlett_ctl_put, | |
487 | .private_value = 6, /* max value */ | |
488 | .tlv = { .p = db_scale_scarlett_gain } | |
489 | }; | |
490 | ||
491 | static struct snd_kcontrol_new usb_scarlett_ctl_enum = { | |
492 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
493 | .name = "", | |
494 | .info = scarlett_ctl_enum_info, | |
495 | .get = scarlett_ctl_enum_get, | |
496 | .put = scarlett_ctl_enum_put, | |
497 | }; | |
498 | ||
499 | static struct snd_kcontrol_new usb_scarlett_ctl_dynamic_enum = { | |
500 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
501 | .name = "", | |
502 | .info = scarlett_ctl_enum_dynamic_info, | |
503 | .get = scarlett_ctl_enum_get, | |
504 | .put = scarlett_ctl_enum_put, | |
505 | }; | |
506 | ||
507 | static struct snd_kcontrol_new usb_scarlett_ctl_sync = { | |
508 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
509 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | |
510 | .name = "", | |
511 | .info = scarlett_ctl_enum_info, | |
512 | .get = scarlett_ctl_meter_get, | |
513 | }; | |
514 | ||
515 | static int add_new_ctl(struct usb_mixer_interface *mixer, | |
516 | const struct snd_kcontrol_new *ncontrol, | |
517 | int index, int offset, int num, | |
518 | int val_type, int channels, const char *name, | |
519 | const struct scarlett_mixer_elem_enum_info *opt, | |
520 | struct usb_mixer_elem_info **elem_ret | |
521 | ) | |
522 | { | |
523 | struct snd_kcontrol *kctl; | |
524 | struct usb_mixer_elem_info *elem; | |
525 | int err; | |
526 | ||
527 | elem = kzalloc(sizeof(*elem), GFP_KERNEL); | |
528 | if (!elem) | |
529 | return -ENOMEM; | |
530 | ||
531 | elem->mixer = mixer; | |
532 | elem->control = offset; | |
533 | elem->idx_off = num; | |
534 | elem->id = index; | |
535 | elem->val_type = val_type; | |
536 | ||
537 | elem->channels = channels; | |
538 | ||
539 | /* add scarlett_mixer_elem_enum_info struct */ | |
540 | elem->private_data = (void *)opt; | |
541 | ||
542 | kctl = snd_ctl_new1(ncontrol, elem); | |
543 | if (!kctl) { | |
544 | kfree(elem); | |
545 | return -ENOMEM; | |
546 | } | |
547 | kctl->private_free = snd_usb_mixer_elem_free; | |
548 | ||
549 | strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); | |
550 | ||
551 | err = snd_ctl_add(mixer->chip->card, kctl); | |
552 | if (err < 0) | |
553 | return err; | |
554 | ||
555 | if (elem_ret) | |
556 | *elem_ret = elem; | |
557 | ||
558 | return 0; | |
559 | } | |
560 | ||
561 | static int add_output_ctls(struct usb_mixer_interface *mixer, | |
562 | int index, const char *name, | |
563 | const struct scarlett_device_info *info) | |
564 | { | |
565 | int err; | |
566 | char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | |
567 | struct usb_mixer_elem_info *elem; | |
568 | ||
569 | /* Add mute switch */ | |
570 | snprintf(mx, sizeof(mx), "Master %d (%s) Playback Switch", | |
571 | index + 1, name); | |
572 | err = add_new_ctl(mixer, &usb_scarlett_ctl_switch, 0x0a, 0x01, | |
573 | 2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem); | |
574 | if (err < 0) | |
575 | return err; | |
576 | ||
577 | /* Add volume control and initialize to 0 */ | |
578 | snprintf(mx, sizeof(mx), "Master %d (%s) Playback Volume", | |
579 | index + 1, name); | |
580 | err = add_new_ctl(mixer, &usb_scarlett_ctl_master, 0x0a, 0x02, | |
581 | 2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem); | |
582 | if (err < 0) | |
583 | return err; | |
584 | ||
585 | /* Add L channel source playback enumeration */ | |
586 | snprintf(mx, sizeof(mx), "Master %dL (%s) Source Playback Enum", | |
587 | index + 1, name); | |
588 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, 0x33, 0x00, | |
589 | 2*index, USB_MIXER_S16, 1, mx, &info->opt_master, | |
590 | &elem); | |
591 | if (err < 0) | |
592 | return err; | |
593 | ||
594 | /* Add R channel source playback enumeration */ | |
595 | snprintf(mx, sizeof(mx), "Master %dR (%s) Source Playback Enum", | |
596 | index + 1, name); | |
597 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, 0x33, 0x00, | |
598 | 2*index+1, USB_MIXER_S16, 1, mx, &info->opt_master, | |
599 | &elem); | |
600 | if (err < 0) | |
601 | return err; | |
602 | ||
603 | return 0; | |
604 | } | |
605 | ||
606 | /********************** device-specific config *************************/ | |
607 | ||
608 | /* untested... */ | |
609 | static struct scarlett_device_info s6i6_info = { | |
610 | .matrix_in = 18, | |
611 | .matrix_out = 8, | |
612 | .input_len = 6, | |
613 | .output_len = 6, | |
614 | ||
615 | .opt_master = { | |
616 | .start = -1, | |
617 | .len = 27, | |
618 | .offsets = {0, 12, 16, 18, 18}, | |
619 | .names = NULL | |
620 | }, | |
621 | ||
622 | .opt_matrix = { | |
623 | .start = -1, | |
624 | .len = 19, | |
625 | .offsets = {0, 12, 16, 18, 18}, | |
626 | .names = NULL | |
627 | }, | |
628 | ||
629 | .num_controls = 0, | |
630 | .controls = { | |
631 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | |
632 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" }, | |
633 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | |
634 | { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
635 | { .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
636 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
637 | { .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
638 | { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
639 | { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
640 | }, | |
641 | ||
642 | .matrix_mux_init = { | |
643 | 12, 13, 14, 15, /* Analog -> 1..4 */ | |
644 | 16, 17, /* SPDIF -> 5,6 */ | |
645 | 0, 1, 2, 3, 4, 5, 6, 7, /* PCM[1..12] -> 7..18 */ | |
646 | 8, 9, 10, 11 | |
647 | } | |
648 | }; | |
649 | ||
650 | /* untested... */ | |
651 | static struct scarlett_device_info s8i6_info = { | |
652 | .matrix_in = 18, | |
653 | .matrix_out = 6, | |
654 | .input_len = 8, | |
655 | .output_len = 6, | |
656 | ||
657 | .opt_master = { | |
658 | .start = -1, | |
659 | .len = 25, | |
660 | .offsets = {0, 12, 16, 18, 18}, | |
661 | .names = NULL | |
662 | }, | |
663 | ||
664 | .opt_matrix = { | |
665 | .start = -1, | |
666 | .len = 19, | |
667 | .offsets = {0, 12, 16, 18, 18}, | |
668 | .names = NULL | |
669 | }, | |
670 | ||
671 | .num_controls = 7, | |
672 | .controls = { | |
673 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | |
674 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" }, | |
675 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | |
676 | { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
677 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
678 | { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
679 | { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
680 | }, | |
681 | ||
682 | .matrix_mux_init = { | |
683 | 12, 13, 14, 15, /* Analog -> 1..4 */ | |
684 | 16, 17, /* SPDIF -> 5,6 */ | |
685 | 0, 1, 2, 3, 4, 5, 6, 7, /* PCM[1..12] -> 7..18 */ | |
686 | 8, 9, 10, 11 | |
687 | } | |
688 | }; | |
689 | ||
690 | static struct scarlett_device_info s18i6_info = { | |
691 | .matrix_in = 18, | |
692 | .matrix_out = 6, | |
693 | .input_len = 18, | |
694 | .output_len = 6, | |
695 | ||
696 | .opt_master = { | |
697 | .start = -1, | |
698 | .len = 31, | |
699 | .offsets = {0, 6, 14, 16, 24}, | |
700 | .names = NULL, | |
701 | }, | |
702 | ||
703 | .opt_matrix = { | |
704 | .start = -1, | |
705 | .len = 25, | |
706 | .offsets = {0, 6, 14, 16, 24}, | |
707 | .names = NULL, | |
708 | }, | |
709 | ||
710 | .num_controls = 5, | |
711 | .controls = { | |
712 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | |
713 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" }, | |
714 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | |
715 | { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
716 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
717 | }, | |
718 | ||
719 | .matrix_mux_init = { | |
720 | 6, 7, 8, 9, 10, 11, 12, 13, /* Analog -> 1..8 */ | |
721 | 16, 17, 18, 19, 20, 21, /* ADAT[1..6] -> 9..14 */ | |
722 | 14, 15, /* SPDIF -> 15,16 */ | |
723 | 0, 1 /* PCM[1,2] -> 17,18 */ | |
724 | } | |
725 | }; | |
726 | ||
727 | static struct scarlett_device_info s18i8_info = { | |
728 | .matrix_in = 18, | |
729 | .matrix_out = 8, | |
730 | .input_len = 18, | |
731 | .output_len = 8, | |
732 | ||
733 | .opt_master = { | |
734 | .start = -1, | |
735 | .len = 35, | |
736 | .offsets = {0, 8, 16, 18, 26}, | |
737 | .names = NULL | |
738 | }, | |
739 | ||
740 | .opt_matrix = { | |
741 | .start = -1, | |
742 | .len = 27, | |
743 | .offsets = {0, 8, 16, 18, 26}, | |
744 | .names = NULL | |
745 | }, | |
746 | ||
747 | .num_controls = 10, | |
748 | .controls = { | |
749 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | |
750 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone 1" }, | |
751 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "Headphone 2" }, | |
752 | { .num = 3, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | |
753 | { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
754 | { .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
755 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
756 | { .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
757 | { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
758 | { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
759 | }, | |
760 | ||
761 | .matrix_mux_init = { | |
762 | 8, 9, 10, 11, 12, 13, 14, 15, /* Analog -> 1..8 */ | |
763 | 18, 19, 20, 21, 22, 23, /* ADAT[1..6] -> 9..14 */ | |
764 | 16, 17, /* SPDIF -> 15,16 */ | |
765 | 0, 1 /* PCM[1,2] -> 17,18 */ | |
766 | } | |
767 | }; | |
768 | ||
769 | static struct scarlett_device_info s18i20_info = { | |
770 | .matrix_in = 18, | |
771 | .matrix_out = 8, | |
772 | .input_len = 18, | |
773 | .output_len = 20, | |
774 | ||
775 | .opt_master = { | |
776 | .start = -1, | |
777 | .len = 47, | |
778 | .offsets = {0, 20, 28, 30, 38}, | |
779 | .names = NULL | |
780 | }, | |
781 | ||
782 | .opt_matrix = { | |
783 | .start = -1, | |
784 | .len = 39, | |
785 | .offsets = {0, 20, 28, 30, 38}, | |
786 | .names = NULL | |
787 | }, | |
788 | ||
789 | .num_controls = 10, | |
790 | .controls = { | |
791 | { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" }, | |
792 | { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Line 3/4" }, | |
793 | { .num = 2, .type = SCARLETT_OUTPUTS, .name = "Line 5/6" }, | |
794 | { .num = 3, .type = SCARLETT_OUTPUTS, .name = "Line 7/8" }, | |
795 | { .num = 4, .type = SCARLETT_OUTPUTS, .name = "Line 9/10" }, | |
796 | { .num = 5, .type = SCARLETT_OUTPUTS, .name = "SPDIF" }, | |
797 | { .num = 6, .type = SCARLETT_OUTPUTS, .name = "ADAT 1/2" }, | |
798 | { .num = 7, .type = SCARLETT_OUTPUTS, .name = "ADAT 3/4" }, | |
799 | { .num = 8, .type = SCARLETT_OUTPUTS, .name = "ADAT 5/6" }, | |
800 | { .num = 9, .type = SCARLETT_OUTPUTS, .name = "ADAT 7/8" }, | |
801 | /*{ .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
802 | { .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
803 | { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL}, | |
804 | { .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
805 | { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL}, | |
806 | { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL},*/ | |
807 | }, | |
808 | ||
809 | .matrix_mux_init = { | |
810 | 20, 21, 22, 23, 24, 25, 26, 27, /* Analog -> 1..8 */ | |
811 | 30, 31, 32, 33, 34, 35, /* ADAT[1..6] -> 9..14 */ | |
812 | 28, 29, /* SPDIF -> 15,16 */ | |
813 | 0, 1 /* PCM[1,2] -> 17,18 */ | |
814 | } | |
815 | }; | |
816 | ||
817 | ||
818 | static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer, | |
819 | struct scarlett_device_info *info) | |
820 | { | |
821 | int i, err; | |
822 | char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | |
823 | const struct scarlett_mixer_control *ctl; | |
824 | struct usb_mixer_elem_info *elem; | |
825 | ||
826 | /* create master switch and playback volume */ | |
827 | err = add_new_ctl(mixer, &usb_scarlett_ctl_switch, 0x0a, 0x01, 0, | |
828 | USB_MIXER_S16, 1, "Master Playback Switch", NULL, | |
829 | &elem); | |
830 | if (err < 0) | |
831 | return err; | |
832 | ||
833 | err = add_new_ctl(mixer, &usb_scarlett_ctl_master, 0x0a, 0x02, 0, | |
834 | USB_MIXER_S16, 1, "Master Playback Volume", NULL, | |
835 | &elem); | |
836 | if (err < 0) | |
837 | return err; | |
838 | ||
839 | /* iterate through controls in info struct and create each one */ | |
840 | for (i = 0; i < info->num_controls; i++) { | |
841 | ctl = &info->controls[i]; | |
842 | ||
843 | switch (ctl->type) { | |
844 | case SCARLETT_OUTPUTS: | |
845 | err = add_output_ctls(mixer, ctl->num, ctl->name, info); | |
846 | if (err < 0) | |
847 | return err; | |
848 | break; | |
849 | case SCARLETT_SWITCH_IMPEDANCE: | |
850 | sprintf(mx, "Input %d Impedance Switch", ctl->num); | |
851 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, 0x01, | |
852 | 0x09, ctl->num, USB_MIXER_S16, 1, mx, | |
853 | &opt_impedance, &elem); | |
854 | if (err < 0) | |
855 | return err; | |
856 | break; | |
857 | case SCARLETT_SWITCH_PAD: | |
858 | sprintf(mx, "Input %d Pad Switch", ctl->num); | |
859 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, 0x01, | |
860 | 0x0b, ctl->num, USB_MIXER_S16, 1, mx, | |
861 | &opt_pad, &elem); | |
862 | if (err < 0) | |
863 | return err; | |
864 | break; | |
865 | } | |
866 | } | |
867 | ||
868 | return 0; | |
869 | } | |
870 | ||
871 | /* | |
872 | * Create and initialize a mixer for the Focusrite(R) Scarlett | |
873 | */ | |
874 | int snd_scarlett_controls_create(struct usb_mixer_interface *mixer) | |
875 | { | |
876 | int err, i, o; | |
877 | char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | |
878 | struct scarlett_device_info *info; | |
879 | struct usb_mixer_elem_info *elem; | |
880 | static char sample_rate_buffer[4] = { '\x80', '\xbb', '\x00', '\x00' }; | |
881 | ||
882 | /* only use UAC_VERSION_2 */ | |
883 | if (!mixer->protocol) | |
884 | return 0; | |
885 | ||
886 | switch (mixer->chip->usb_id) { | |
887 | case USB_ID(0x1235, 0x8012): | |
888 | info = &s6i6_info; | |
889 | break; | |
890 | case USB_ID(0x1235, 0x8002): | |
891 | info = &s8i6_info; | |
892 | break; | |
893 | case USB_ID(0x1235, 0x8004): | |
894 | info = &s18i6_info; | |
895 | break; | |
896 | case USB_ID(0x1235, 0x8014): | |
897 | info = &s18i8_info; | |
898 | break; | |
899 | case USB_ID(0x1235, 0x800c): | |
900 | info = &s18i20_info; | |
901 | break; | |
902 | default: /* device not (yet) supported */ | |
903 | return -EINVAL; | |
904 | } | |
905 | ||
906 | /* generic function to create controls */ | |
907 | err = scarlett_controls_create_generic(mixer, info); | |
908 | if (err < 0) | |
909 | return err; | |
910 | ||
911 | /* setup matrix controls */ | |
912 | for (i = 0; i < info->matrix_in; i++) { | |
913 | snprintf(mx, sizeof(mx), "Matrix %02d Input Playback Route", | |
914 | i+1); | |
915 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, 0x32, | |
916 | 0x06, i, USB_MIXER_S16, 1, mx, | |
917 | &info->opt_matrix, &elem); | |
918 | if (err < 0) | |
919 | return err; | |
920 | ||
921 | for (o = 0; o < info->matrix_out; o++) { | |
922 | sprintf(mx, "Matrix %02d Mix %c Playback Volume", i+1, | |
923 | o+'A'); | |
924 | err = add_new_ctl(mixer, &usb_scarlett_ctl, 0x3c, 0x00, | |
925 | (i << 3) + (o & 0x07), USB_MIXER_S16, | |
926 | 1, mx, NULL, &elem); | |
927 | if (err < 0) | |
928 | return err; | |
929 | ||
930 | } | |
931 | } | |
932 | ||
933 | for (i = 0; i < info->input_len; i++) { | |
934 | snprintf(mx, sizeof(mx), "Input Source %02d Capture Route", | |
935 | i+1); | |
936 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, 0x34, | |
937 | 0x00, i, USB_MIXER_S16, 1, mx, | |
938 | &info->opt_master, &elem); | |
939 | if (err < 0) | |
940 | return err; | |
941 | } | |
942 | ||
943 | /* val_len == 1 needed here */ | |
944 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, 0x28, 0x01, 0, | |
945 | USB_MIXER_U8, 1, "Sample Clock Source", | |
946 | &opt_clock, &elem); | |
947 | if (err < 0) | |
948 | return err; | |
949 | ||
950 | /* val_len == 1 and UAC2_CS_MEM */ | |
951 | err = add_new_ctl(mixer, &usb_scarlett_ctl_sync, 0x3c, 0x00, 2, | |
952 | USB_MIXER_U8, 1, "Sample Clock Sync Status", | |
953 | &opt_sync, &elem); | |
954 | if (err < 0) | |
955 | return err; | |
956 | ||
957 | /* initialize sampling rate to 48000 */ | |
958 | err = snd_usb_ctl_msg(mixer->chip->dev, | |
959 | usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR, | |
960 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | | |
961 | USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->chip) | | |
962 | (0x29 << 8), sample_rate_buffer, 4); | |
963 | if (err < 0) | |
964 | return err; | |
965 | ||
966 | return err; | |
967 | } |