aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorChris J Arges <chris.j.arges@canonical.com>2014-11-12 13:07:02 -0500
committerTakashi Iwai <tiwai@suse.de>2014-11-13 01:32:39 -0500
commit76b188c4b370876018e3a778ec11a94a5316dbe4 (patch)
tree66068fe3d0d9e90c51f28141a31ae998c773f1d6 /sound/usb
parenteef90451605d79a5703756505087e0ef16da9077 (diff)
ALSA: usb-audio: Scarlett mixer interface for 6i6, 18i6, 18i8 and 18i20
This code contains the Scarlett mixer interface code that was originally written by Tobias Hoffman and Robin Gareus. Because the device doesn't properly implement UAC2 this code adds a mixer quirk for the device. Changes from the original code include removing the metering code along with dead code and comments. Compiler warnings were fixed. The code to initialize the sampling rate was causing a crash this was fixed as discussed on the mailing list. Error, and info messages were convered to dev_err and dev_info interfaces. The custom scarlett_mixer_elem_info struct was replaced with the more generic usb_mixer_elem_info to be able to recycle more code from mixer.c. This patch also makes additional modifications based on upstream comments. Individual control creation functions are removed and a generic function is no used. Macros for function calls are removed to improve readability. Hardcoded control initialization is removed. Save to HW functionality has been removed. Strings for enums are created dynamically for the mixer. Strings used for controls are now SNDRV_CTL_ELEM_ID_NAME_MAXLEN length. Signed-off-by: Chris J Arges <chris.j.arges@canonical.com> 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.c9
-rw-r--r--sound/usb/mixer_scarlett.c967
-rw-r--r--sound/usb/mixer_scarlett.h6
4 files changed, 983 insertions, 0 deletions
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 2b92f0dcbc4c..bcee4060fd18 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -9,6 +9,7 @@ snd-usb-audio-objs := card.o \
9 helper.o \ 9 helper.o \
10 mixer.o \ 10 mixer.o \
11 mixer_quirks.o \ 11 mixer_quirks.o \
12 mixer_scarlett.o \
12 pcm.o \ 13 pcm.o \
13 proc.o \ 14 proc.o \
14 quirks.o \ 15 quirks.o \
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index b8b1f48c1f50..7b9331a17026 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -41,6 +41,7 @@
41#include "usbaudio.h" 41#include "usbaudio.h"
42#include "mixer.h" 42#include "mixer.h"
43#include "mixer_quirks.h" 43#include "mixer_quirks.h"
44#include "mixer_scarlett.h"
44#include "helper.h" 45#include "helper.h"
45 46
46extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; 47extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
@@ -1770,6 +1771,14 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
1770 /* detection is disabled in mixer_maps.c */ 1771 /* detection is disabled in mixer_maps.c */
1771 err = snd_create_std_mono_table(mixer, ebox44_table); 1772 err = snd_create_std_mono_table(mixer, ebox44_table);
1772 break; 1773 break;
1774
1775 case USB_ID(0x1235, 0x8012): /* Focusrite Scarlett 6i6 */
1776 case USB_ID(0x1235, 0x8002): /* Focusrite Scarlett 8i6 */
1777 case USB_ID(0x1235, 0x8004): /* Focusrite Scarlett 18i6 */
1778 case USB_ID(0x1235, 0x8014): /* Focusrite Scarlett 18i8 */
1779 case USB_ID(0x1235, 0x800c): /* Focusrite Scarlett 18i20 */
1780 err = snd_scarlett_controls_create(mixer);
1781 break;
1773 } 1782 }
1774 1783
1775 return err; 1784 return err;
diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
new file mode 100644
index 000000000000..a0a874507de5
--- /dev/null
+++ b/sound/usb/mixer_scarlett.c
@@ -0,0 +1,967 @@
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
151enum {
152 SCARLETT_OUTPUTS,
153 SCARLETT_SWITCH_IMPEDANCE,
154 SCARLETT_SWITCH_PAD,
155};
156
157enum {
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
165struct 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
172struct scarlett_mixer_control {
173 unsigned char num;
174 unsigned char type;
175 const char *name;
176};
177
178struct 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
196static 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
205static 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
214static 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
223static 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
232static 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
244static 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
262static 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
288static 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
302static 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
321static 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
348static 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
365static 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
387static 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
397static 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
415static 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
435static 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
457static 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
465static const DECLARE_TLV_DB_SCALE(db_scale_scarlett_gain, -12800, 100, 0);
466
467static 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
479static 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
491static 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
499static 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
507static 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
515static 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
561static 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... */
609static 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... */
651static 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
690static 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
727static 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
769static 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
818static 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 */
874int 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}
diff --git a/sound/usb/mixer_scarlett.h b/sound/usb/mixer_scarlett.h
new file mode 100644
index 000000000000..19c592ab0332
--- /dev/null
+++ b/sound/usb/mixer_scarlett.h
@@ -0,0 +1,6 @@
1#ifndef __USB_MIXER_SCARLETT_H
2#define __USB_MIXER_SCARLETT_H
3
4int snd_scarlett_controls_create(struct usb_mixer_interface *mixer);
5
6#endif /* __USB_MIXER_SCARLETT_H */