xref: /openbmc/linux/sound/usb/mixer_scarlett2.c (revision c845428b7a9157523103100806bc8130d64769c8)
1*771ad4dfSGeoffrey D. Bennett // SPDX-License-Identifier: GPL-2.0
2*771ad4dfSGeoffrey D. Bennett /*
3*771ad4dfSGeoffrey D. Bennett  *   Focusrite Scarlett 2 Protocol Driver for ALSA
4*771ad4dfSGeoffrey D. Bennett  *   (including Scarlett 2nd Gen, 3rd Gen, Clarett USB, and Clarett+
5*771ad4dfSGeoffrey D. Bennett  *   series products)
6*771ad4dfSGeoffrey D. Bennett  *
7*771ad4dfSGeoffrey D. Bennett  *   Supported models:
8*771ad4dfSGeoffrey D. Bennett  *   - 6i6/18i8/18i20 Gen 2
9*771ad4dfSGeoffrey D. Bennett  *   - Solo/2i2/4i4/8i6/18i8/18i20 Gen 3
10*771ad4dfSGeoffrey D. Bennett  *   - Clarett 2Pre/4Pre/8Pre USB
11*771ad4dfSGeoffrey D. Bennett  *   - Clarett+ 2Pre/4Pre/8Pre
12*771ad4dfSGeoffrey D. Bennett  *
13*771ad4dfSGeoffrey D. Bennett  *   Copyright (c) 2018-2023 by Geoffrey D. Bennett <g at b4.vu>
14*771ad4dfSGeoffrey D. Bennett  *   Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com>
15*771ad4dfSGeoffrey D. Bennett  *   Copyright (c) 2022 by Christian Colglazier <christian@cacolglazier.com>
16*771ad4dfSGeoffrey D. Bennett  *
17*771ad4dfSGeoffrey D. Bennett  *   Based on the Scarlett (Gen 1) Driver for ALSA:
18*771ad4dfSGeoffrey D. Bennett  *
19*771ad4dfSGeoffrey D. Bennett  *   Copyright (c) 2013 by Tobias Hoffmann
20*771ad4dfSGeoffrey D. Bennett  *   Copyright (c) 2013 by Robin Gareus <robin at gareus.org>
21*771ad4dfSGeoffrey D. Bennett  *   Copyright (c) 2002 by Takashi Iwai <tiwai at suse.de>
22*771ad4dfSGeoffrey D. Bennett  *   Copyright (c) 2014 by Chris J Arges <chris.j.arges at canonical.com>
23*771ad4dfSGeoffrey D. Bennett  *
24*771ad4dfSGeoffrey D. Bennett  *   Many codes borrowed from audio.c by
25*771ad4dfSGeoffrey D. Bennett  *     Alan Cox (alan at lxorguk.ukuu.org.uk)
26*771ad4dfSGeoffrey D. Bennett  *     Thomas Sailer (sailer at ife.ee.ethz.ch)
27*771ad4dfSGeoffrey D. Bennett  *
28*771ad4dfSGeoffrey D. Bennett  *   Code cleanup:
29*771ad4dfSGeoffrey D. Bennett  *   David Henningsson <david.henningsson at canonical.com>
30*771ad4dfSGeoffrey D. Bennett  */
31*771ad4dfSGeoffrey D. Bennett 
32*771ad4dfSGeoffrey D. Bennett /* The protocol was reverse engineered by looking at the communication
33*771ad4dfSGeoffrey D. Bennett  * between Focusrite Control 2.3.4 and the Focusrite(R) Scarlett 18i20
34*771ad4dfSGeoffrey D. Bennett  * (firmware 1083) using usbmon in July-August 2018.
35*771ad4dfSGeoffrey D. Bennett  *
36*771ad4dfSGeoffrey D. Bennett  * Scarlett 18i8 support added in April 2019.
37*771ad4dfSGeoffrey D. Bennett  *
38*771ad4dfSGeoffrey D. Bennett  * Scarlett 6i6 support added in June 2019 (thanks to Martin Wittmann
39*771ad4dfSGeoffrey D. Bennett  * for providing usbmon output and testing).
40*771ad4dfSGeoffrey D. Bennett  *
41*771ad4dfSGeoffrey D. Bennett  * Scarlett 4i4/8i6 Gen 3 support added in May 2020 (thanks to Laurent
42*771ad4dfSGeoffrey D. Bennett  * Debricon for donating a 4i4 and to Fredrik Unger for providing 8i6
43*771ad4dfSGeoffrey D. Bennett  * usbmon output and testing).
44*771ad4dfSGeoffrey D. Bennett  *
45*771ad4dfSGeoffrey D. Bennett  * Scarlett 18i8/18i20 Gen 3 support added in June 2020 (thanks to
46*771ad4dfSGeoffrey D. Bennett  * Darren Jaeckel, Alex Sedlack, and Clovis Lunel for providing usbmon
47*771ad4dfSGeoffrey D. Bennett  * output, protocol traces and testing).
48*771ad4dfSGeoffrey D. Bennett  *
49*771ad4dfSGeoffrey D. Bennett  * Support for loading mixer volume and mux configuration from the
50*771ad4dfSGeoffrey D. Bennett  * interface during driver initialisation added in May 2021 (thanks to
51*771ad4dfSGeoffrey D. Bennett  * Vladimir Sadovnikov for figuring out how).
52*771ad4dfSGeoffrey D. Bennett  *
53*771ad4dfSGeoffrey D. Bennett  * Support for Solo/2i2 Gen 3 added in May 2021 (thanks to Alexander
54*771ad4dfSGeoffrey D. Bennett  * Vorona for 2i2 protocol traces).
55*771ad4dfSGeoffrey D. Bennett  *
56*771ad4dfSGeoffrey D. Bennett  * Support for phantom power, direct monitoring, speaker switching,
57*771ad4dfSGeoffrey D. Bennett  * and talkback added in May-June 2021.
58*771ad4dfSGeoffrey D. Bennett  *
59*771ad4dfSGeoffrey D. Bennett  * Support for Clarett+ 8Pre added in Aug 2022 by Christian
60*771ad4dfSGeoffrey D. Bennett  * Colglazier.
61*771ad4dfSGeoffrey D. Bennett  *
62*771ad4dfSGeoffrey D. Bennett  * Support for Clarett 8Pre USB added in Sep 2023 (thanks to Philippe
63*771ad4dfSGeoffrey D. Bennett  * Perrot for confirmation).
64*771ad4dfSGeoffrey D. Bennett  *
65*771ad4dfSGeoffrey D. Bennett  * Support for Clarett+ 4Pre and 2Pre added in Sep 2023 (thanks to
66*771ad4dfSGeoffrey D. Bennett  * Gregory Rozzo for donating a 4Pre, and David Sherwood and Patrice
67*771ad4dfSGeoffrey D. Bennett  * Peterson for usbmon output).
68*771ad4dfSGeoffrey D. Bennett  *
69*771ad4dfSGeoffrey D. Bennett  * Support for Clarett 2Pre and 4Pre USB added in Oct 2023.
70*771ad4dfSGeoffrey D. Bennett  *
71*771ad4dfSGeoffrey D. Bennett  * This ALSA mixer gives access to (model-dependent):
72*771ad4dfSGeoffrey D. Bennett  *  - input, output, mixer-matrix muxes
73*771ad4dfSGeoffrey D. Bennett  *  - mixer-matrix gain stages
74*771ad4dfSGeoffrey D. Bennett  *  - gain/volume/mute controls
75*771ad4dfSGeoffrey D. Bennett  *  - level meters
76*771ad4dfSGeoffrey D. Bennett  *  - line/inst level, pad, and air controls
77*771ad4dfSGeoffrey D. Bennett  *  - phantom power, direct monitor, speaker switching, and talkback
78*771ad4dfSGeoffrey D. Bennett  *    controls
79*771ad4dfSGeoffrey D. Bennett  *  - disable/enable MSD mode
80*771ad4dfSGeoffrey D. Bennett  *  - disable/enable standalone mode
81*771ad4dfSGeoffrey D. Bennett  *
82*771ad4dfSGeoffrey D. Bennett  * <ditaa>
83*771ad4dfSGeoffrey D. Bennett  *    /--------------\    18chn            20chn     /--------------\
84*771ad4dfSGeoffrey D. Bennett  *    | Hardware  in +--+------\    /-------------+--+ ALSA PCM out |
85*771ad4dfSGeoffrey D. Bennett  *    \--------------/  |      |    |             |  \--------------/
86*771ad4dfSGeoffrey D. Bennett  *                      |      |    |    /-----\  |
87*771ad4dfSGeoffrey D. Bennett  *                      |      |    |    |     |  |
88*771ad4dfSGeoffrey D. Bennett  *                      |      v    v    v     |  |
89*771ad4dfSGeoffrey D. Bennett  *                      |   +---------------+  |  |
90*771ad4dfSGeoffrey D. Bennett  *                      |    \ Matrix  Mux /   |  |
91*771ad4dfSGeoffrey D. Bennett  *                      |     +-----+-----+    |  |
92*771ad4dfSGeoffrey D. Bennett  *                      |           |          |  |
93*771ad4dfSGeoffrey D. Bennett  *                      |           |18chn     |  |
94*771ad4dfSGeoffrey D. Bennett  *                      |           |          |  |
95*771ad4dfSGeoffrey D. Bennett  *                      |           |     10chn|  |
96*771ad4dfSGeoffrey D. Bennett  *                      |           v          |  |
97*771ad4dfSGeoffrey D. Bennett  *                      |     +------------+   |  |
98*771ad4dfSGeoffrey D. Bennett  *                      |     | Mixer      |   |  |
99*771ad4dfSGeoffrey D. Bennett  *                      |     |     Matrix |   |  |
100*771ad4dfSGeoffrey D. Bennett  *                      |     |            |   |  |
101*771ad4dfSGeoffrey D. Bennett  *                      |     | 18x10 Gain |   |  |
102*771ad4dfSGeoffrey D. Bennett  *                      |     |   stages   |   |  |
103*771ad4dfSGeoffrey D. Bennett  *                      |     +-----+------+   |  |
104*771ad4dfSGeoffrey D. Bennett  *                      |           |          |  |
105*771ad4dfSGeoffrey D. Bennett  *                      |18chn      |10chn     |  |20chn
106*771ad4dfSGeoffrey D. Bennett  *                      |           |          |  |
107*771ad4dfSGeoffrey D. Bennett  *                      |           +----------/  |
108*771ad4dfSGeoffrey D. Bennett  *                      |           |             |
109*771ad4dfSGeoffrey D. Bennett  *                      v           v             v
110*771ad4dfSGeoffrey D. Bennett  *                      ===========================
111*771ad4dfSGeoffrey D. Bennett  *               +---------------+       +--—------------+
112*771ad4dfSGeoffrey D. Bennett  *                \ Output  Mux /         \ Capture Mux /
113*771ad4dfSGeoffrey D. Bennett  *                 +---+---+---+           +-----+-----+
114*771ad4dfSGeoffrey D. Bennett  *                     |   |                     |
115*771ad4dfSGeoffrey D. Bennett  *                10chn|   |                     |18chn
116*771ad4dfSGeoffrey D. Bennett  *                     |   |                     |
117*771ad4dfSGeoffrey D. Bennett  *  /--------------\   |   |                     |   /--------------\
118*771ad4dfSGeoffrey D. Bennett  *  | S/PDIF, ADAT |<--/   |10chn                \-->| ALSA PCM in  |
119*771ad4dfSGeoffrey D. Bennett  *  | Hardware out |       |                         \--------------/
120*771ad4dfSGeoffrey D. Bennett  *  \--------------/       |
121*771ad4dfSGeoffrey D. Bennett  *                         v
122*771ad4dfSGeoffrey D. Bennett  *                  +-------------+    Software gain per channel.
123*771ad4dfSGeoffrey D. Bennett  *                  | Master Gain |<-- 18i20 only: Switch per channel
124*771ad4dfSGeoffrey D. Bennett  *                  +------+------+    to select HW or SW gain control.
125*771ad4dfSGeoffrey D. Bennett  *                         |
126*771ad4dfSGeoffrey D. Bennett  *                         |10chn
127*771ad4dfSGeoffrey D. Bennett  *  /--------------\       |
128*771ad4dfSGeoffrey D. Bennett  *  | Analogue     |<------/
129*771ad4dfSGeoffrey D. Bennett  *  | Hardware out |
130*771ad4dfSGeoffrey D. Bennett  *  \--------------/
131*771ad4dfSGeoffrey D. Bennett  * </ditaa>
132*771ad4dfSGeoffrey D. Bennett  *
133*771ad4dfSGeoffrey D. Bennett  * Gen 3 devices have a Mass Storage Device (MSD) mode where a small
134*771ad4dfSGeoffrey D. Bennett  * disk with registration and driver download information is presented
135*771ad4dfSGeoffrey D. Bennett  * to the host. To access the full functionality of the device without
136*771ad4dfSGeoffrey D. Bennett  * proprietary software, MSD mode can be disabled by:
137*771ad4dfSGeoffrey D. Bennett  * - holding down the 48V button for five seconds while powering on
138*771ad4dfSGeoffrey D. Bennett  *   the device, or
139*771ad4dfSGeoffrey D. Bennett  * - using this driver and alsamixer to change the "MSD Mode" setting
140*771ad4dfSGeoffrey D. Bennett  *   to Off and power-cycling the device
141*771ad4dfSGeoffrey D. Bennett  */
142*771ad4dfSGeoffrey D. Bennett 
143*771ad4dfSGeoffrey D. Bennett #include <linux/slab.h>
144*771ad4dfSGeoffrey D. Bennett #include <linux/usb.h>
145*771ad4dfSGeoffrey D. Bennett #include <linux/moduleparam.h>
146*771ad4dfSGeoffrey D. Bennett 
147*771ad4dfSGeoffrey D. Bennett #include <sound/control.h>
148*771ad4dfSGeoffrey D. Bennett #include <sound/tlv.h>
149*771ad4dfSGeoffrey D. Bennett 
150*771ad4dfSGeoffrey D. Bennett #include "usbaudio.h"
151*771ad4dfSGeoffrey D. Bennett #include "mixer.h"
152*771ad4dfSGeoffrey D. Bennett #include "helper.h"
153*771ad4dfSGeoffrey D. Bennett 
154*771ad4dfSGeoffrey D. Bennett #include "mixer_scarlett2.h"
155*771ad4dfSGeoffrey D. Bennett 
156*771ad4dfSGeoffrey D. Bennett /* device_setup value to allow turning MSD mode back on */
157*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MSD_ENABLE 0x02
158*771ad4dfSGeoffrey D. Bennett 
159*771ad4dfSGeoffrey D. Bennett /* device_setup value to disable this mixer driver */
160*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_DISABLE 0x04
161*771ad4dfSGeoffrey D. Bennett 
162*771ad4dfSGeoffrey D. Bennett /* some gui mixers can't handle negative ctl values */
163*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_VOLUME_BIAS 127
164*771ad4dfSGeoffrey D. Bennett 
165*771ad4dfSGeoffrey D. Bennett /* mixer range from -80dB to +6dB in 0.5dB steps */
166*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MIXER_MIN_DB -80
167*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MIXER_BIAS (-SCARLETT2_MIXER_MIN_DB * 2)
168*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MIXER_MAX_DB 6
169*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MIXER_MAX_VALUE \
170*771ad4dfSGeoffrey D. Bennett 	((SCARLETT2_MIXER_MAX_DB - SCARLETT2_MIXER_MIN_DB) * 2)
171*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MIXER_VALUE_COUNT (SCARLETT2_MIXER_MAX_VALUE + 1)
172*771ad4dfSGeoffrey D. Bennett 
173*771ad4dfSGeoffrey D. Bennett /* map from (dB + 80) * 2 to mixer value
174*771ad4dfSGeoffrey D. Bennett  * for dB in 0 .. 172: int(8192 * pow(10, ((dB - 160) / 2 / 20)))
175*771ad4dfSGeoffrey D. Bennett  */
176*771ad4dfSGeoffrey D. Bennett static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = {
177*771ad4dfSGeoffrey D. Bennett 	0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
178*771ad4dfSGeoffrey D. Bennett 	2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8,
179*771ad4dfSGeoffrey D. Bennett 	9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
180*771ad4dfSGeoffrey D. Bennett 	23, 24, 25, 27, 29, 30, 32, 34, 36, 38, 41, 43, 46, 48, 51,
181*771ad4dfSGeoffrey D. Bennett 	54, 57, 61, 65, 68, 73, 77, 81, 86, 91, 97, 103, 109, 115,
182*771ad4dfSGeoffrey D. Bennett 	122, 129, 137, 145, 154, 163, 173, 183, 194, 205, 217, 230,
183*771ad4dfSGeoffrey D. Bennett 	244, 259, 274, 290, 307, 326, 345, 365, 387, 410, 434, 460,
184*771ad4dfSGeoffrey D. Bennett 	487, 516, 547, 579, 614, 650, 689, 730, 773, 819, 867, 919,
185*771ad4dfSGeoffrey D. Bennett 	973, 1031, 1092, 1157, 1225, 1298, 1375, 1456, 1543, 1634,
186*771ad4dfSGeoffrey D. Bennett 	1731, 1833, 1942, 2057, 2179, 2308, 2445, 2590, 2744, 2906,
187*771ad4dfSGeoffrey D. Bennett 	3078, 3261, 3454, 3659, 3876, 4105, 4349, 4606, 4879, 5168,
188*771ad4dfSGeoffrey D. Bennett 	5475, 5799, 6143, 6507, 6892, 7301, 7733, 8192, 8677, 9191,
189*771ad4dfSGeoffrey D. Bennett 	9736, 10313, 10924, 11571, 12257, 12983, 13752, 14567, 15430,
190*771ad4dfSGeoffrey D. Bennett 	16345
191*771ad4dfSGeoffrey D. Bennett };
192*771ad4dfSGeoffrey D. Bennett 
193*771ad4dfSGeoffrey D. Bennett /* Maximum number of analogue outputs */
194*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_ANALOGUE_MAX 10
195*771ad4dfSGeoffrey D. Bennett 
196*771ad4dfSGeoffrey D. Bennett /* Maximum number of level and pad switches */
197*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_LEVEL_SWITCH_MAX 2
198*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_PAD_SWITCH_MAX 8
199*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_AIR_SWITCH_MAX 8
200*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_PHANTOM_SWITCH_MAX 2
201*771ad4dfSGeoffrey D. Bennett 
202*771ad4dfSGeoffrey D. Bennett /* Maximum number of inputs to the mixer */
203*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_INPUT_MIX_MAX 25
204*771ad4dfSGeoffrey D. Bennett 
205*771ad4dfSGeoffrey D. Bennett /* Maximum number of outputs from the mixer */
206*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_OUTPUT_MIX_MAX 12
207*771ad4dfSGeoffrey D. Bennett 
208*771ad4dfSGeoffrey D. Bennett /* Maximum size of the data in the USB mux assignment message:
209*771ad4dfSGeoffrey D. Bennett  * 20 inputs, 20 outputs, 25 matrix inputs, 12 spare
210*771ad4dfSGeoffrey D. Bennett  */
211*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MUX_MAX 77
212*771ad4dfSGeoffrey D. Bennett 
213*771ad4dfSGeoffrey D. Bennett /* Maximum number of meters (sum of output port counts) */
214*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MAX_METERS 65
215*771ad4dfSGeoffrey D. Bennett 
216*771ad4dfSGeoffrey D. Bennett /* There are three different sets of configuration parameters across
217*771ad4dfSGeoffrey D. Bennett  * the devices
218*771ad4dfSGeoffrey D. Bennett  */
219*771ad4dfSGeoffrey D. Bennett enum {
220*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_SET_NO_MIXER = 0,
221*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_SET_GEN_2 = 1,
222*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_SET_GEN_3 = 2,
223*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_SET_CLARETT = 3,
224*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_SET_COUNT = 4
225*771ad4dfSGeoffrey D. Bennett };
226*771ad4dfSGeoffrey D. Bennett 
227*771ad4dfSGeoffrey D. Bennett /* Hardware port types:
228*771ad4dfSGeoffrey D. Bennett  * - None (no input to mux)
229*771ad4dfSGeoffrey D. Bennett  * - Analogue I/O
230*771ad4dfSGeoffrey D. Bennett  * - S/PDIF I/O
231*771ad4dfSGeoffrey D. Bennett  * - ADAT I/O
232*771ad4dfSGeoffrey D. Bennett  * - Mixer I/O
233*771ad4dfSGeoffrey D. Bennett  * - PCM I/O
234*771ad4dfSGeoffrey D. Bennett  */
235*771ad4dfSGeoffrey D. Bennett enum {
236*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_TYPE_NONE     = 0,
237*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_TYPE_ANALOGUE = 1,
238*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_TYPE_SPDIF    = 2,
239*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_TYPE_ADAT     = 3,
240*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_TYPE_MIX      = 4,
241*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_TYPE_PCM      = 5,
242*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_TYPE_COUNT    = 6,
243*771ad4dfSGeoffrey D. Bennett };
244*771ad4dfSGeoffrey D. Bennett 
245*771ad4dfSGeoffrey D. Bennett /* I/O count of each port type kept in struct scarlett2_ports */
246*771ad4dfSGeoffrey D. Bennett enum {
247*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_IN    = 0,
248*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_OUT   = 1,
249*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_PORT_DIRNS = 2,
250*771ad4dfSGeoffrey D. Bennett };
251*771ad4dfSGeoffrey D. Bennett 
252*771ad4dfSGeoffrey D. Bennett /* Dim/Mute buttons on the 18i20 */
253*771ad4dfSGeoffrey D. Bennett enum {
254*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_BUTTON_MUTE    = 0,
255*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_BUTTON_DIM     = 1,
256*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_DIM_MUTE_COUNT = 2,
257*771ad4dfSGeoffrey D. Bennett };
258*771ad4dfSGeoffrey D. Bennett 
259*771ad4dfSGeoffrey D. Bennett static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = {
260*771ad4dfSGeoffrey D. Bennett 	"Mute Playback Switch", "Dim Playback Switch"
261*771ad4dfSGeoffrey D. Bennett };
262*771ad4dfSGeoffrey D. Bennett 
263*771ad4dfSGeoffrey D. Bennett /* Description of each hardware port type:
264*771ad4dfSGeoffrey D. Bennett  * - id: hardware ID of this port type
265*771ad4dfSGeoffrey D. Bennett  * - src_descr: printf format string for mux input selections
266*771ad4dfSGeoffrey D. Bennett  * - src_num_offset: added to channel number for the fprintf
267*771ad4dfSGeoffrey D. Bennett  * - dst_descr: printf format string for mixer controls
268*771ad4dfSGeoffrey D. Bennett  */
269*771ad4dfSGeoffrey D. Bennett struct scarlett2_port {
270*771ad4dfSGeoffrey D. Bennett 	u16 id;
271*771ad4dfSGeoffrey D. Bennett 	const char * const src_descr;
272*771ad4dfSGeoffrey D. Bennett 	int src_num_offset;
273*771ad4dfSGeoffrey D. Bennett 	const char * const dst_descr;
274*771ad4dfSGeoffrey D. Bennett };
275*771ad4dfSGeoffrey D. Bennett 
276*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_port scarlett2_ports[SCARLETT2_PORT_TYPE_COUNT] = {
277*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_PORT_TYPE_NONE] = {
278*771ad4dfSGeoffrey D. Bennett 		.id = 0x000,
279*771ad4dfSGeoffrey D. Bennett 		.src_descr = "Off"
280*771ad4dfSGeoffrey D. Bennett 	},
281*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_PORT_TYPE_ANALOGUE] = {
282*771ad4dfSGeoffrey D. Bennett 		.id = 0x080,
283*771ad4dfSGeoffrey D. Bennett 		.src_descr = "Analogue %d",
284*771ad4dfSGeoffrey D. Bennett 		.src_num_offset = 1,
285*771ad4dfSGeoffrey D. Bennett 		.dst_descr = "Analogue Output %02d Playback"
286*771ad4dfSGeoffrey D. Bennett 	},
287*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_PORT_TYPE_SPDIF] = {
288*771ad4dfSGeoffrey D. Bennett 		.id = 0x180,
289*771ad4dfSGeoffrey D. Bennett 		.src_descr = "S/PDIF %d",
290*771ad4dfSGeoffrey D. Bennett 		.src_num_offset = 1,
291*771ad4dfSGeoffrey D. Bennett 		.dst_descr = "S/PDIF Output %d Playback"
292*771ad4dfSGeoffrey D. Bennett 	},
293*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_PORT_TYPE_ADAT] = {
294*771ad4dfSGeoffrey D. Bennett 		.id = 0x200,
295*771ad4dfSGeoffrey D. Bennett 		.src_descr = "ADAT %d",
296*771ad4dfSGeoffrey D. Bennett 		.src_num_offset = 1,
297*771ad4dfSGeoffrey D. Bennett 		.dst_descr = "ADAT Output %d Playback"
298*771ad4dfSGeoffrey D. Bennett 	},
299*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_PORT_TYPE_MIX] = {
300*771ad4dfSGeoffrey D. Bennett 		.id = 0x300,
301*771ad4dfSGeoffrey D. Bennett 		.src_descr = "Mix %c",
302*771ad4dfSGeoffrey D. Bennett 		.src_num_offset = 'A',
303*771ad4dfSGeoffrey D. Bennett 		.dst_descr = "Mixer Input %02d Capture"
304*771ad4dfSGeoffrey D. Bennett 	},
305*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_PORT_TYPE_PCM] = {
306*771ad4dfSGeoffrey D. Bennett 		.id = 0x600,
307*771ad4dfSGeoffrey D. Bennett 		.src_descr = "PCM %d",
308*771ad4dfSGeoffrey D. Bennett 		.src_num_offset = 1,
309*771ad4dfSGeoffrey D. Bennett 		.dst_descr = "PCM %02d Capture"
310*771ad4dfSGeoffrey D. Bennett 	},
311*771ad4dfSGeoffrey D. Bennett };
312*771ad4dfSGeoffrey D. Bennett 
313*771ad4dfSGeoffrey D. Bennett /* Number of mux tables: one for each band of sample rates
314*771ad4dfSGeoffrey D. Bennett  * (44.1/48kHz, 88.2/96kHz, and 176.4/176kHz)
315*771ad4dfSGeoffrey D. Bennett  */
316*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MUX_TABLES 3
317*771ad4dfSGeoffrey D. Bennett 
318*771ad4dfSGeoffrey D. Bennett /* Maximum number of entries in a mux table */
319*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_MAX_MUX_ENTRIES 10
320*771ad4dfSGeoffrey D. Bennett 
321*771ad4dfSGeoffrey D. Bennett /* One entry within mux_assignment defines the port type and range of
322*771ad4dfSGeoffrey D. Bennett  * ports to add to the set_mux message. The end of the list is marked
323*771ad4dfSGeoffrey D. Bennett  * with count == 0.
324*771ad4dfSGeoffrey D. Bennett  */
325*771ad4dfSGeoffrey D. Bennett struct scarlett2_mux_entry {
326*771ad4dfSGeoffrey D. Bennett 	u8 port_type;
327*771ad4dfSGeoffrey D. Bennett 	u8 start;
328*771ad4dfSGeoffrey D. Bennett 	u8 count;
329*771ad4dfSGeoffrey D. Bennett };
330*771ad4dfSGeoffrey D. Bennett 
331*771ad4dfSGeoffrey D. Bennett struct scarlett2_device_info {
332*771ad4dfSGeoffrey D. Bennett 	/* Gen 3 devices have an internal MSD mode switch that needs
333*771ad4dfSGeoffrey D. Bennett 	 * to be disabled in order to access the full functionality of
334*771ad4dfSGeoffrey D. Bennett 	 * the device.
335*771ad4dfSGeoffrey D. Bennett 	 */
336*771ad4dfSGeoffrey D. Bennett 	u8 has_msd_mode;
337*771ad4dfSGeoffrey D. Bennett 
338*771ad4dfSGeoffrey D. Bennett 	/* which set of configuration parameters the device uses */
339*771ad4dfSGeoffrey D. Bennett 	u8 config_set;
340*771ad4dfSGeoffrey D. Bennett 
341*771ad4dfSGeoffrey D. Bennett 	/* line out hw volume is sw controlled */
342*771ad4dfSGeoffrey D. Bennett 	u8 line_out_hw_vol;
343*771ad4dfSGeoffrey D. Bennett 
344*771ad4dfSGeoffrey D. Bennett 	/* support for main/alt speaker switching */
345*771ad4dfSGeoffrey D. Bennett 	u8 has_speaker_switching;
346*771ad4dfSGeoffrey D. Bennett 
347*771ad4dfSGeoffrey D. Bennett 	/* support for talkback microphone */
348*771ad4dfSGeoffrey D. Bennett 	u8 has_talkback;
349*771ad4dfSGeoffrey D. Bennett 
350*771ad4dfSGeoffrey D. Bennett 	/* the number of analogue inputs with a software switchable
351*771ad4dfSGeoffrey D. Bennett 	 * level control that can be set to line or instrument
352*771ad4dfSGeoffrey D. Bennett 	 */
353*771ad4dfSGeoffrey D. Bennett 	u8 level_input_count;
354*771ad4dfSGeoffrey D. Bennett 
355*771ad4dfSGeoffrey D. Bennett 	/* the first input with a level control (0-based) */
356*771ad4dfSGeoffrey D. Bennett 	u8 level_input_first;
357*771ad4dfSGeoffrey D. Bennett 
358*771ad4dfSGeoffrey D. Bennett 	/* the number of analogue inputs with a software switchable
359*771ad4dfSGeoffrey D. Bennett 	 * 10dB pad control
360*771ad4dfSGeoffrey D. Bennett 	 */
361*771ad4dfSGeoffrey D. Bennett 	u8 pad_input_count;
362*771ad4dfSGeoffrey D. Bennett 
363*771ad4dfSGeoffrey D. Bennett 	/* the number of analogue inputs with a software switchable
364*771ad4dfSGeoffrey D. Bennett 	 * "air" control
365*771ad4dfSGeoffrey D. Bennett 	 */
366*771ad4dfSGeoffrey D. Bennett 	u8 air_input_count;
367*771ad4dfSGeoffrey D. Bennett 
368*771ad4dfSGeoffrey D. Bennett 	/* the number of phantom (48V) software switchable controls */
369*771ad4dfSGeoffrey D. Bennett 	u8 phantom_count;
370*771ad4dfSGeoffrey D. Bennett 
371*771ad4dfSGeoffrey D. Bennett 	/* the number of inputs each phantom switch controls */
372*771ad4dfSGeoffrey D. Bennett 	u8 inputs_per_phantom;
373*771ad4dfSGeoffrey D. Bennett 
374*771ad4dfSGeoffrey D. Bennett 	/* the number of direct monitor options
375*771ad4dfSGeoffrey D. Bennett 	 * (0 = none, 1 = mono only, 2 = mono/stereo)
376*771ad4dfSGeoffrey D. Bennett 	 */
377*771ad4dfSGeoffrey D. Bennett 	u8 direct_monitor;
378*771ad4dfSGeoffrey D. Bennett 
379*771ad4dfSGeoffrey D. Bennett 	/* remap analogue outputs; 18i8 Gen 3 has "line 3/4" connected
380*771ad4dfSGeoffrey D. Bennett 	 * internally to the analogue 7/8 outputs
381*771ad4dfSGeoffrey D. Bennett 	 */
382*771ad4dfSGeoffrey D. Bennett 	u8 line_out_remap_enable;
383*771ad4dfSGeoffrey D. Bennett 	u8 line_out_remap[SCARLETT2_ANALOGUE_MAX];
384*771ad4dfSGeoffrey D. Bennett 
385*771ad4dfSGeoffrey D. Bennett 	/* additional description for the line out volume controls */
386*771ad4dfSGeoffrey D. Bennett 	const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX];
387*771ad4dfSGeoffrey D. Bennett 
388*771ad4dfSGeoffrey D. Bennett 	/* number of sources/destinations of each port type */
389*771ad4dfSGeoffrey D. Bennett 	const int port_count[SCARLETT2_PORT_TYPE_COUNT][SCARLETT2_PORT_DIRNS];
390*771ad4dfSGeoffrey D. Bennett 
391*771ad4dfSGeoffrey D. Bennett 	/* layout/order of the entries in the set_mux message */
392*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_mux_entry mux_assignment[SCARLETT2_MUX_TABLES]
393*771ad4dfSGeoffrey D. Bennett 						 [SCARLETT2_MAX_MUX_ENTRIES];
394*771ad4dfSGeoffrey D. Bennett };
395*771ad4dfSGeoffrey D. Bennett 
396*771ad4dfSGeoffrey D. Bennett struct scarlett2_data {
397*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer;
398*771ad4dfSGeoffrey D. Bennett 	struct mutex usb_mutex; /* prevent sending concurrent USB requests */
399*771ad4dfSGeoffrey D. Bennett 	struct mutex data_mutex; /* lock access to this data */
400*771ad4dfSGeoffrey D. Bennett 	struct delayed_work work;
401*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info;
402*771ad4dfSGeoffrey D. Bennett 	const char *series_name;
403*771ad4dfSGeoffrey D. Bennett 	__u8 bInterfaceNumber;
404*771ad4dfSGeoffrey D. Bennett 	__u8 bEndpointAddress;
405*771ad4dfSGeoffrey D. Bennett 	__u16 wMaxPacketSize;
406*771ad4dfSGeoffrey D. Bennett 	__u8 bInterval;
407*771ad4dfSGeoffrey D. Bennett 	int num_mux_srcs;
408*771ad4dfSGeoffrey D. Bennett 	int num_mux_dsts;
409*771ad4dfSGeoffrey D. Bennett 	u16 scarlett2_seq;
410*771ad4dfSGeoffrey D. Bennett 	u8 sync_updated;
411*771ad4dfSGeoffrey D. Bennett 	u8 vol_updated;
412*771ad4dfSGeoffrey D. Bennett 	u8 input_other_updated;
413*771ad4dfSGeoffrey D. Bennett 	u8 monitor_other_updated;
414*771ad4dfSGeoffrey D. Bennett 	u8 mux_updated;
415*771ad4dfSGeoffrey D. Bennett 	u8 speaker_switching_switched;
416*771ad4dfSGeoffrey D. Bennett 	u8 sync;
417*771ad4dfSGeoffrey D. Bennett 	u8 master_vol;
418*771ad4dfSGeoffrey D. Bennett 	u8 vol[SCARLETT2_ANALOGUE_MAX];
419*771ad4dfSGeoffrey D. Bennett 	u8 vol_sw_hw_switch[SCARLETT2_ANALOGUE_MAX];
420*771ad4dfSGeoffrey D. Bennett 	u8 mute_switch[SCARLETT2_ANALOGUE_MAX];
421*771ad4dfSGeoffrey D. Bennett 	u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX];
422*771ad4dfSGeoffrey D. Bennett 	u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX];
423*771ad4dfSGeoffrey D. Bennett 	u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT];
424*771ad4dfSGeoffrey D. Bennett 	u8 air_switch[SCARLETT2_AIR_SWITCH_MAX];
425*771ad4dfSGeoffrey D. Bennett 	u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX];
426*771ad4dfSGeoffrey D. Bennett 	u8 phantom_persistence;
427*771ad4dfSGeoffrey D. Bennett 	u8 direct_monitor_switch;
428*771ad4dfSGeoffrey D. Bennett 	u8 speaker_switching_switch;
429*771ad4dfSGeoffrey D. Bennett 	u8 talkback_switch;
430*771ad4dfSGeoffrey D. Bennett 	u8 talkback_map[SCARLETT2_OUTPUT_MIX_MAX];
431*771ad4dfSGeoffrey D. Bennett 	u8 msd_switch;
432*771ad4dfSGeoffrey D. Bennett 	u8 standalone_switch;
433*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *sync_ctl;
434*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *master_vol_ctl;
435*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX];
436*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *sw_hw_ctls[SCARLETT2_ANALOGUE_MAX];
437*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *mute_ctls[SCARLETT2_ANALOGUE_MAX];
438*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *dim_mute_ctls[SCARLETT2_DIM_MUTE_COUNT];
439*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *level_ctls[SCARLETT2_LEVEL_SWITCH_MAX];
440*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *pad_ctls[SCARLETT2_PAD_SWITCH_MAX];
441*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *air_ctls[SCARLETT2_AIR_SWITCH_MAX];
442*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX];
443*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *mux_ctls[SCARLETT2_MUX_MAX];
444*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *direct_monitor_ctl;
445*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *speaker_switching_ctl;
446*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *talkback_ctl;
447*771ad4dfSGeoffrey D. Bennett 	u8 mux[SCARLETT2_MUX_MAX];
448*771ad4dfSGeoffrey D. Bennett 	u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX];
449*771ad4dfSGeoffrey D. Bennett };
450*771ad4dfSGeoffrey D. Bennett 
451*771ad4dfSGeoffrey D. Bennett /*** Model-specific data ***/
452*771ad4dfSGeoffrey D. Bennett 
453*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info s6i6_gen2_info = {
454*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_GEN_2,
455*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
456*771ad4dfSGeoffrey D. Bennett 	.pad_input_count = 2,
457*771ad4dfSGeoffrey D. Bennett 
458*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
459*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 L",
460*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 R",
461*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 L",
462*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 R",
463*771ad4dfSGeoffrey D. Bennett 	},
464*771ad4dfSGeoffrey D. Bennett 
465*771ad4dfSGeoffrey D. Bennett 	.port_count = {
466*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
467*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = {  4,  4 },
468*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
469*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
470*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = {  6,  6 },
471*771ad4dfSGeoffrey D. Bennett 	},
472*771ad4dfSGeoffrey D. Bennett 
473*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
474*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  6 },
475*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
476*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
477*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
478*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
479*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
480*771ad4dfSGeoffrey D. Bennett 	}, {
481*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  6 },
482*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
483*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
484*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
485*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
486*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
487*771ad4dfSGeoffrey D. Bennett 	}, {
488*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  6 },
489*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
490*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
491*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
492*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
493*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
494*771ad4dfSGeoffrey D. Bennett 	} },
495*771ad4dfSGeoffrey D. Bennett };
496*771ad4dfSGeoffrey D. Bennett 
497*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info s18i8_gen2_info = {
498*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_GEN_2,
499*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
500*771ad4dfSGeoffrey D. Bennett 	.pad_input_count = 4,
501*771ad4dfSGeoffrey D. Bennett 
502*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
503*771ad4dfSGeoffrey D. Bennett 		"Monitor L",
504*771ad4dfSGeoffrey D. Bennett 		"Monitor R",
505*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 L",
506*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 R",
507*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 L",
508*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 R",
509*771ad4dfSGeoffrey D. Bennett 	},
510*771ad4dfSGeoffrey D. Bennett 
511*771ad4dfSGeoffrey D. Bennett 	.port_count = {
512*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
513*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = {  8,  6 },
514*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
515*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ADAT]     = {  8,  0 },
516*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
517*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = {  8, 18 },
518*771ad4dfSGeoffrey D. Bennett 	},
519*771ad4dfSGeoffrey D. Bennett 
520*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
521*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 18 },
522*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
523*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
524*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
525*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
526*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
527*771ad4dfSGeoffrey D. Bennett 	}, {
528*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 14 },
529*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
530*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
531*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
532*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
533*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
534*771ad4dfSGeoffrey D. Bennett 	}, {
535*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 10 },
536*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
537*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
538*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
539*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  4 },
540*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
541*771ad4dfSGeoffrey D. Bennett 	} },
542*771ad4dfSGeoffrey D. Bennett };
543*771ad4dfSGeoffrey D. Bennett 
544*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info s18i20_gen2_info = {
545*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_GEN_2,
546*771ad4dfSGeoffrey D. Bennett 	.line_out_hw_vol = 1,
547*771ad4dfSGeoffrey D. Bennett 
548*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
549*771ad4dfSGeoffrey D. Bennett 		"Monitor L",
550*771ad4dfSGeoffrey D. Bennett 		"Monitor R",
551*771ad4dfSGeoffrey D. Bennett 		NULL,
552*771ad4dfSGeoffrey D. Bennett 		NULL,
553*771ad4dfSGeoffrey D. Bennett 		NULL,
554*771ad4dfSGeoffrey D. Bennett 		NULL,
555*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 L",
556*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 R",
557*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 L",
558*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 R",
559*771ad4dfSGeoffrey D. Bennett 	},
560*771ad4dfSGeoffrey D. Bennett 
561*771ad4dfSGeoffrey D. Bennett 	.port_count = {
562*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
563*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = {  8, 10 },
564*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
565*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ADAT]     = {  8,  8 },
566*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
567*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = { 20, 18 },
568*771ad4dfSGeoffrey D. Bennett 	},
569*771ad4dfSGeoffrey D. Bennett 
570*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
571*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 18 },
572*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
573*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
574*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ADAT,     0,  8 },
575*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
576*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
577*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
578*771ad4dfSGeoffrey D. Bennett 	}, {
579*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 14 },
580*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
581*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
582*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ADAT,     0,  4 },
583*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
584*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
585*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
586*771ad4dfSGeoffrey D. Bennett 	}, {
587*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 10 },
588*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
589*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
590*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
591*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  6 },
592*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
593*771ad4dfSGeoffrey D. Bennett 	} },
594*771ad4dfSGeoffrey D. Bennett };
595*771ad4dfSGeoffrey D. Bennett 
596*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info solo_gen3_info = {
597*771ad4dfSGeoffrey D. Bennett 	.has_msd_mode = 1,
598*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_NO_MIXER,
599*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 1,
600*771ad4dfSGeoffrey D. Bennett 	.level_input_first = 1,
601*771ad4dfSGeoffrey D. Bennett 	.air_input_count = 1,
602*771ad4dfSGeoffrey D. Bennett 	.phantom_count = 1,
603*771ad4dfSGeoffrey D. Bennett 	.inputs_per_phantom = 1,
604*771ad4dfSGeoffrey D. Bennett 	.direct_monitor = 1,
605*771ad4dfSGeoffrey D. Bennett };
606*771ad4dfSGeoffrey D. Bennett 
607*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info s2i2_gen3_info = {
608*771ad4dfSGeoffrey D. Bennett 	.has_msd_mode = 1,
609*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_NO_MIXER,
610*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
611*771ad4dfSGeoffrey D. Bennett 	.air_input_count = 2,
612*771ad4dfSGeoffrey D. Bennett 	.phantom_count = 1,
613*771ad4dfSGeoffrey D. Bennett 	.inputs_per_phantom = 2,
614*771ad4dfSGeoffrey D. Bennett 	.direct_monitor = 2,
615*771ad4dfSGeoffrey D. Bennett };
616*771ad4dfSGeoffrey D. Bennett 
617*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info s4i4_gen3_info = {
618*771ad4dfSGeoffrey D. Bennett 	.has_msd_mode = 1,
619*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_GEN_3,
620*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
621*771ad4dfSGeoffrey D. Bennett 	.pad_input_count = 2,
622*771ad4dfSGeoffrey D. Bennett 	.air_input_count = 2,
623*771ad4dfSGeoffrey D. Bennett 	.phantom_count = 1,
624*771ad4dfSGeoffrey D. Bennett 	.inputs_per_phantom = 2,
625*771ad4dfSGeoffrey D. Bennett 
626*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
627*771ad4dfSGeoffrey D. Bennett 		"Monitor L",
628*771ad4dfSGeoffrey D. Bennett 		"Monitor R",
629*771ad4dfSGeoffrey D. Bennett 		"Headphones L",
630*771ad4dfSGeoffrey D. Bennett 		"Headphones R",
631*771ad4dfSGeoffrey D. Bennett 	},
632*771ad4dfSGeoffrey D. Bennett 
633*771ad4dfSGeoffrey D. Bennett 	.port_count = {
634*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = { 1, 0 },
635*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = { 4, 4 },
636*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 6, 8 },
637*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = { 4, 6 },
638*771ad4dfSGeoffrey D. Bennett 	},
639*771ad4dfSGeoffrey D. Bennett 
640*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
641*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  6 },
642*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
643*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0,  8 },
644*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0, 16 },
645*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
646*771ad4dfSGeoffrey D. Bennett 	}, {
647*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  6 },
648*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
649*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0,  8 },
650*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0, 16 },
651*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
652*771ad4dfSGeoffrey D. Bennett 	}, {
653*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  6 },
654*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
655*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0,  8 },
656*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0, 16 },
657*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
658*771ad4dfSGeoffrey D. Bennett 	} },
659*771ad4dfSGeoffrey D. Bennett };
660*771ad4dfSGeoffrey D. Bennett 
661*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info s8i6_gen3_info = {
662*771ad4dfSGeoffrey D. Bennett 	.has_msd_mode = 1,
663*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_GEN_3,
664*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
665*771ad4dfSGeoffrey D. Bennett 	.pad_input_count = 2,
666*771ad4dfSGeoffrey D. Bennett 	.air_input_count = 2,
667*771ad4dfSGeoffrey D. Bennett 	.phantom_count = 1,
668*771ad4dfSGeoffrey D. Bennett 	.inputs_per_phantom = 2,
669*771ad4dfSGeoffrey D. Bennett 
670*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
671*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 L",
672*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 R",
673*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 L",
674*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 R",
675*771ad4dfSGeoffrey D. Bennett 	},
676*771ad4dfSGeoffrey D. Bennett 
677*771ad4dfSGeoffrey D. Bennett 	.port_count = {
678*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = { 1,  0 },
679*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = { 6,  4 },
680*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_SPDIF]    = { 2,  2 },
681*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 8,  8 },
682*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = { 6, 10 },
683*771ad4dfSGeoffrey D. Bennett 	},
684*771ad4dfSGeoffrey D. Bennett 
685*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
686*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  8 },
687*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
688*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
689*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      8,  2 },
690*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0,  8 },
691*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0, 18 },
692*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
693*771ad4dfSGeoffrey D. Bennett 	}, {
694*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  8 },
695*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
696*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
697*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      8,  2 },
698*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0,  8 },
699*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0, 18 },
700*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
701*771ad4dfSGeoffrey D. Bennett 	}, {
702*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  8 },
703*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
704*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
705*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      8,  2 },
706*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0,  8 },
707*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0, 18 },
708*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
709*771ad4dfSGeoffrey D. Bennett 	} },
710*771ad4dfSGeoffrey D. Bennett };
711*771ad4dfSGeoffrey D. Bennett 
712*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info s18i8_gen3_info = {
713*771ad4dfSGeoffrey D. Bennett 	.has_msd_mode = 1,
714*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_GEN_3,
715*771ad4dfSGeoffrey D. Bennett 	.line_out_hw_vol = 1,
716*771ad4dfSGeoffrey D. Bennett 	.has_speaker_switching = 1,
717*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
718*771ad4dfSGeoffrey D. Bennett 	.pad_input_count = 4,
719*771ad4dfSGeoffrey D. Bennett 	.air_input_count = 4,
720*771ad4dfSGeoffrey D. Bennett 	.phantom_count = 2,
721*771ad4dfSGeoffrey D. Bennett 	.inputs_per_phantom = 2,
722*771ad4dfSGeoffrey D. Bennett 
723*771ad4dfSGeoffrey D. Bennett 	.line_out_remap_enable = 1,
724*771ad4dfSGeoffrey D. Bennett 	.line_out_remap = { 0, 1, 6, 7, 2, 3, 4, 5 },
725*771ad4dfSGeoffrey D. Bennett 
726*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
727*771ad4dfSGeoffrey D. Bennett 		"Monitor L",
728*771ad4dfSGeoffrey D. Bennett 		"Monitor R",
729*771ad4dfSGeoffrey D. Bennett 		"Alt Monitor L",
730*771ad4dfSGeoffrey D. Bennett 		"Alt Monitor R",
731*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 L",
732*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 R",
733*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 L",
734*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 R",
735*771ad4dfSGeoffrey D. Bennett 	},
736*771ad4dfSGeoffrey D. Bennett 
737*771ad4dfSGeoffrey D. Bennett 	.port_count = {
738*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
739*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = {  8,  8 },
740*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
741*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ADAT]     = {  8,  0 },
742*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 10, 20 },
743*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = {  8, 20 },
744*771ad4dfSGeoffrey D. Bennett 	},
745*771ad4dfSGeoffrey D. Bennett 
746*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
747*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,       0, 10 },
748*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      12,  8 },
749*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
750*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  6,  2 },
751*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  2,  4 },
752*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
753*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      10,  2 },
754*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,       0, 20 },
755*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,      0, 10 },
756*771ad4dfSGeoffrey D. Bennett 		{ 0,                             0,  0 },
757*771ad4dfSGeoffrey D. Bennett 	}, {
758*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,       0, 10 },
759*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      12,  4 },
760*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
761*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  6,  2 },
762*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  2,  4 },
763*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
764*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      10,  2 },
765*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,       0, 20 },
766*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,      0, 10 },
767*771ad4dfSGeoffrey D. Bennett 		{ 0,                             0,  0 },
768*771ad4dfSGeoffrey D. Bennett 	}, {
769*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,       0, 10 },
770*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
771*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  6,  2 },
772*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  2,  4 },
773*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
774*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,       0, 20 },
775*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,      0, 10 },
776*771ad4dfSGeoffrey D. Bennett 		{ 0,                             0,  0 },
777*771ad4dfSGeoffrey D. Bennett 	} },
778*771ad4dfSGeoffrey D. Bennett };
779*771ad4dfSGeoffrey D. Bennett 
780*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info s18i20_gen3_info = {
781*771ad4dfSGeoffrey D. Bennett 	.has_msd_mode = 1,
782*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_GEN_3,
783*771ad4dfSGeoffrey D. Bennett 	.line_out_hw_vol = 1,
784*771ad4dfSGeoffrey D. Bennett 	.has_speaker_switching = 1,
785*771ad4dfSGeoffrey D. Bennett 	.has_talkback = 1,
786*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
787*771ad4dfSGeoffrey D. Bennett 	.pad_input_count = 8,
788*771ad4dfSGeoffrey D. Bennett 	.air_input_count = 8,
789*771ad4dfSGeoffrey D. Bennett 	.phantom_count = 2,
790*771ad4dfSGeoffrey D. Bennett 	.inputs_per_phantom = 4,
791*771ad4dfSGeoffrey D. Bennett 
792*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
793*771ad4dfSGeoffrey D. Bennett 		"Monitor 1 L",
794*771ad4dfSGeoffrey D. Bennett 		"Monitor 1 R",
795*771ad4dfSGeoffrey D. Bennett 		"Monitor 2 L",
796*771ad4dfSGeoffrey D. Bennett 		"Monitor 2 R",
797*771ad4dfSGeoffrey D. Bennett 		NULL,
798*771ad4dfSGeoffrey D. Bennett 		NULL,
799*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 L",
800*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 R",
801*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 L",
802*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 R",
803*771ad4dfSGeoffrey D. Bennett 	},
804*771ad4dfSGeoffrey D. Bennett 
805*771ad4dfSGeoffrey D. Bennett 	.port_count = {
806*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
807*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = {  9, 10 },
808*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
809*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ADAT]     = {  8,  8 },
810*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 12, 25 },
811*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = { 20, 20 },
812*771ad4dfSGeoffrey D. Bennett 	},
813*771ad4dfSGeoffrey D. Bennett 
814*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
815*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,       0,  8 },
816*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      10, 10 },
817*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  0, 10 },
818*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
819*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ADAT,      0,  8 },
820*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,       8,  2 },
821*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,       0, 25 },
822*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,      0, 12 },
823*771ad4dfSGeoffrey D. Bennett 		{ 0,                             0,  0 },
824*771ad4dfSGeoffrey D. Bennett 	}, {
825*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,       0,  8 },
826*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      10,  8 },
827*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  0, 10 },
828*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
829*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ADAT,      0,  8 },
830*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,       8,  2 },
831*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,       0, 25 },
832*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,      0, 10 },
833*771ad4dfSGeoffrey D. Bennett 		{ 0,                             0,  0 },
834*771ad4dfSGeoffrey D. Bennett 	}, {
835*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,       0, 10 },
836*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE,  0, 10 },
837*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
838*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,      0, 24 },
839*771ad4dfSGeoffrey D. Bennett 		{ 0,                             0,  0 },
840*771ad4dfSGeoffrey D. Bennett 	} },
841*771ad4dfSGeoffrey D. Bennett };
842*771ad4dfSGeoffrey D. Bennett 
843*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info clarett_2pre_info = {
844*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_CLARETT,
845*771ad4dfSGeoffrey D. Bennett 	.line_out_hw_vol = 1,
846*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
847*771ad4dfSGeoffrey D. Bennett 	.air_input_count = 2,
848*771ad4dfSGeoffrey D. Bennett 
849*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
850*771ad4dfSGeoffrey D. Bennett 		"Monitor L",
851*771ad4dfSGeoffrey D. Bennett 		"Monitor R",
852*771ad4dfSGeoffrey D. Bennett 		"Headphones L",
853*771ad4dfSGeoffrey D. Bennett 		"Headphones R",
854*771ad4dfSGeoffrey D. Bennett 	},
855*771ad4dfSGeoffrey D. Bennett 
856*771ad4dfSGeoffrey D. Bennett 	.port_count = {
857*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
858*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = {  2,  4 },
859*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  0 },
860*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ADAT]     = {  8,  0 },
861*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
862*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = {  4, 12 },
863*771ad4dfSGeoffrey D. Bennett 	},
864*771ad4dfSGeoffrey D. Bennett 
865*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
866*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 12 },
867*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
868*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
869*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
870*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
871*771ad4dfSGeoffrey D. Bennett 	}, {
872*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  8 },
873*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
874*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
875*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
876*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
877*771ad4dfSGeoffrey D. Bennett 	}, {
878*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0,  2 },
879*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
880*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0, 26 },
881*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
882*771ad4dfSGeoffrey D. Bennett 	} },
883*771ad4dfSGeoffrey D. Bennett };
884*771ad4dfSGeoffrey D. Bennett 
885*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info clarett_4pre_info = {
886*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_CLARETT,
887*771ad4dfSGeoffrey D. Bennett 	.line_out_hw_vol = 1,
888*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
889*771ad4dfSGeoffrey D. Bennett 	.air_input_count = 4,
890*771ad4dfSGeoffrey D. Bennett 
891*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
892*771ad4dfSGeoffrey D. Bennett 		"Monitor L",
893*771ad4dfSGeoffrey D. Bennett 		"Monitor R",
894*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 L",
895*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 R",
896*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 L",
897*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 R",
898*771ad4dfSGeoffrey D. Bennett 	},
899*771ad4dfSGeoffrey D. Bennett 
900*771ad4dfSGeoffrey D. Bennett 	.port_count = {
901*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
902*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = {  8,  6 },
903*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
904*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ADAT]     = {  8,  0 },
905*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
906*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = {  8, 18 },
907*771ad4dfSGeoffrey D. Bennett 	},
908*771ad4dfSGeoffrey D. Bennett 
909*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
910*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 18 },
911*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
912*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
913*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
914*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
915*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
916*771ad4dfSGeoffrey D. Bennett 	}, {
917*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 14 },
918*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
919*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
920*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
921*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
922*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
923*771ad4dfSGeoffrey D. Bennett 	}, {
924*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 12 },
925*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
926*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
927*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0, 24 },
928*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
929*771ad4dfSGeoffrey D. Bennett 	} },
930*771ad4dfSGeoffrey D. Bennett };
931*771ad4dfSGeoffrey D. Bennett 
932*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_info clarett_8pre_info = {
933*771ad4dfSGeoffrey D. Bennett 	.config_set = SCARLETT2_CONFIG_SET_CLARETT,
934*771ad4dfSGeoffrey D. Bennett 	.line_out_hw_vol = 1,
935*771ad4dfSGeoffrey D. Bennett 	.level_input_count = 2,
936*771ad4dfSGeoffrey D. Bennett 	.air_input_count = 8,
937*771ad4dfSGeoffrey D. Bennett 
938*771ad4dfSGeoffrey D. Bennett 	.line_out_descrs = {
939*771ad4dfSGeoffrey D. Bennett 		"Monitor L",
940*771ad4dfSGeoffrey D. Bennett 		"Monitor R",
941*771ad4dfSGeoffrey D. Bennett 		NULL,
942*771ad4dfSGeoffrey D. Bennett 		NULL,
943*771ad4dfSGeoffrey D. Bennett 		NULL,
944*771ad4dfSGeoffrey D. Bennett 		NULL,
945*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 L",
946*771ad4dfSGeoffrey D. Bennett 		"Headphones 1 R",
947*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 L",
948*771ad4dfSGeoffrey D. Bennett 		"Headphones 2 R",
949*771ad4dfSGeoffrey D. Bennett 	},
950*771ad4dfSGeoffrey D. Bennett 
951*771ad4dfSGeoffrey D. Bennett 	.port_count = {
952*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
953*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ANALOGUE] = {  8, 10 },
954*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
955*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_ADAT]     = {  8,  8 },
956*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
957*771ad4dfSGeoffrey D. Bennett 		[SCARLETT2_PORT_TYPE_PCM]      = { 20, 18 },
958*771ad4dfSGeoffrey D. Bennett 	},
959*771ad4dfSGeoffrey D. Bennett 
960*771ad4dfSGeoffrey D. Bennett 	.mux_assignment = { {
961*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 18 },
962*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
963*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
964*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ADAT,     0,  8 },
965*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
966*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
967*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
968*771ad4dfSGeoffrey D. Bennett 	}, {
969*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 14 },
970*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
971*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
972*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ADAT,     0,  4 },
973*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_MIX,      0, 18 },
974*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0,  8 },
975*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
976*771ad4dfSGeoffrey D. Bennett 	}, {
977*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_PCM,      0, 12 },
978*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
979*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
980*771ad4dfSGeoffrey D. Bennett 		{ SCARLETT2_PORT_TYPE_NONE,     0, 22 },
981*771ad4dfSGeoffrey D. Bennett 		{ 0,                            0,  0 },
982*771ad4dfSGeoffrey D. Bennett 	} },
983*771ad4dfSGeoffrey D. Bennett };
984*771ad4dfSGeoffrey D. Bennett 
985*771ad4dfSGeoffrey D. Bennett struct scarlett2_device_entry {
986*771ad4dfSGeoffrey D. Bennett 	const u32 usb_id; /* USB device identifier */
987*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info;
988*771ad4dfSGeoffrey D. Bennett 	const char *series_name;
989*771ad4dfSGeoffrey D. Bennett };
990*771ad4dfSGeoffrey D. Bennett 
991*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_entry scarlett2_devices[] = {
992*771ad4dfSGeoffrey D. Bennett 	/* Supported Gen 2 devices */
993*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8203), &s6i6_gen2_info, "Scarlett Gen 2" },
994*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8204), &s18i8_gen2_info, "Scarlett Gen 2" },
995*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8201), &s18i20_gen2_info, "Scarlett Gen 2" },
996*771ad4dfSGeoffrey D. Bennett 
997*771ad4dfSGeoffrey D. Bennett 	/* Supported Gen 3 devices */
998*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8211), &solo_gen3_info, "Scarlett Gen 3" },
999*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8210), &s2i2_gen3_info, "Scarlett Gen 3" },
1000*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8212), &s4i4_gen3_info, "Scarlett Gen 3" },
1001*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8213), &s8i6_gen3_info, "Scarlett Gen 3" },
1002*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8214), &s18i8_gen3_info, "Scarlett Gen 3" },
1003*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8215), &s18i20_gen3_info, "Scarlett Gen 3" },
1004*771ad4dfSGeoffrey D. Bennett 
1005*771ad4dfSGeoffrey D. Bennett 	/* Supported Clarett USB/Clarett+ devices */
1006*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8206), &clarett_2pre_info, "Clarett USB" },
1007*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8207), &clarett_4pre_info, "Clarett USB" },
1008*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x8208), &clarett_8pre_info, "Clarett USB" },
1009*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x820a), &clarett_2pre_info, "Clarett+" },
1010*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x820b), &clarett_4pre_info, "Clarett+" },
1011*771ad4dfSGeoffrey D. Bennett 	{ USB_ID(0x1235, 0x820c), &clarett_8pre_info, "Clarett+" },
1012*771ad4dfSGeoffrey D. Bennett 
1013*771ad4dfSGeoffrey D. Bennett 	/* End of list */
1014*771ad4dfSGeoffrey D. Bennett 	{ 0, NULL },
1015*771ad4dfSGeoffrey D. Bennett };
1016*771ad4dfSGeoffrey D. Bennett 
1017*771ad4dfSGeoffrey D. Bennett /* get the starting port index number for a given port type/direction */
scarlett2_get_port_start_num(const int port_count[][SCARLETT2_PORT_DIRNS],int direction,int port_type)1018*771ad4dfSGeoffrey D. Bennett static int scarlett2_get_port_start_num(
1019*771ad4dfSGeoffrey D. Bennett 	const int port_count[][SCARLETT2_PORT_DIRNS],
1020*771ad4dfSGeoffrey D. Bennett 	int direction, int port_type)
1021*771ad4dfSGeoffrey D. Bennett {
1022*771ad4dfSGeoffrey D. Bennett 	int i, num = 0;
1023*771ad4dfSGeoffrey D. Bennett 
1024*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < port_type; i++)
1025*771ad4dfSGeoffrey D. Bennett 		num += port_count[i][direction];
1026*771ad4dfSGeoffrey D. Bennett 
1027*771ad4dfSGeoffrey D. Bennett 	return num;
1028*771ad4dfSGeoffrey D. Bennett }
1029*771ad4dfSGeoffrey D. Bennett 
1030*771ad4dfSGeoffrey D. Bennett /*** USB Interactions ***/
1031*771ad4dfSGeoffrey D. Bennett 
1032*771ad4dfSGeoffrey D. Bennett /* Notifications from the interface */
1033*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_NOTIFY_SYNC          0x00000008
1034*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_NOTIFY_DIM_MUTE      0x00200000
1035*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_NOTIFY_MONITOR       0x00400000
1036*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_NOTIFY_INPUT_OTHER   0x00800000
1037*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_NOTIFY_MONITOR_OTHER 0x01000000
1038*771ad4dfSGeoffrey D. Bennett 
1039*771ad4dfSGeoffrey D. Bennett /* Commands for sending/receiving requests/responses */
1040*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_CMD_INIT 0
1041*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_CMD_REQ  2
1042*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_CMD_RESP 3
1043*771ad4dfSGeoffrey D. Bennett 
1044*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_INIT_1    0x00000000
1045*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_INIT_2    0x00000002
1046*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_GET_METER 0x00001001
1047*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_GET_MIX   0x00002001
1048*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_SET_MIX   0x00002002
1049*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_GET_MUX   0x00003001
1050*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_SET_MUX   0x00003002
1051*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_GET_SYNC  0x00006004
1052*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_GET_DATA  0x00800000
1053*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_SET_DATA  0x00800001
1054*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_DATA_CMD  0x00800002
1055*771ad4dfSGeoffrey D. Bennett 
1056*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_CONFIG_SAVE 6
1057*771ad4dfSGeoffrey D. Bennett 
1058*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_VOLUME_STATUS_OFFSET 0x31
1059*771ad4dfSGeoffrey D. Bennett #define SCARLETT2_USB_METER_LEVELS_GET_MAGIC 1
1060*771ad4dfSGeoffrey D. Bennett 
1061*771ad4dfSGeoffrey D. Bennett /* volume status is read together (matches scarlett2_config_items[1]) */
1062*771ad4dfSGeoffrey D. Bennett struct scarlett2_usb_volume_status {
1063*771ad4dfSGeoffrey D. Bennett 	/* dim/mute buttons */
1064*771ad4dfSGeoffrey D. Bennett 	u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT];
1065*771ad4dfSGeoffrey D. Bennett 
1066*771ad4dfSGeoffrey D. Bennett 	u8 pad1;
1067*771ad4dfSGeoffrey D. Bennett 
1068*771ad4dfSGeoffrey D. Bennett 	/* software volume setting */
1069*771ad4dfSGeoffrey D. Bennett 	s16 sw_vol[SCARLETT2_ANALOGUE_MAX];
1070*771ad4dfSGeoffrey D. Bennett 
1071*771ad4dfSGeoffrey D. Bennett 	/* actual volume of output inc. dim (-18dB) */
1072*771ad4dfSGeoffrey D. Bennett 	s16 hw_vol[SCARLETT2_ANALOGUE_MAX];
1073*771ad4dfSGeoffrey D. Bennett 
1074*771ad4dfSGeoffrey D. Bennett 	/* internal mute buttons */
1075*771ad4dfSGeoffrey D. Bennett 	u8 mute_switch[SCARLETT2_ANALOGUE_MAX];
1076*771ad4dfSGeoffrey D. Bennett 
1077*771ad4dfSGeoffrey D. Bennett 	/* sw (0) or hw (1) controlled */
1078*771ad4dfSGeoffrey D. Bennett 	u8 sw_hw_switch[SCARLETT2_ANALOGUE_MAX];
1079*771ad4dfSGeoffrey D. Bennett 
1080*771ad4dfSGeoffrey D. Bennett 	u8 pad3[6];
1081*771ad4dfSGeoffrey D. Bennett 
1082*771ad4dfSGeoffrey D. Bennett 	/* front panel volume knob */
1083*771ad4dfSGeoffrey D. Bennett 	s16 master_vol;
1084*771ad4dfSGeoffrey D. Bennett } __packed;
1085*771ad4dfSGeoffrey D. Bennett 
1086*771ad4dfSGeoffrey D. Bennett /* Configuration parameters that can be read and written */
1087*771ad4dfSGeoffrey D. Bennett enum {
1088*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_DIM_MUTE = 0,
1089*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_LINE_OUT_VOLUME = 1,
1090*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_MUTE_SWITCH = 2,
1091*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_SW_HW_SWITCH = 3,
1092*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_LEVEL_SWITCH = 4,
1093*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_PAD_SWITCH = 5,
1094*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_MSD_SWITCH = 6,
1095*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_AIR_SWITCH = 7,
1096*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_STANDALONE_SWITCH = 8,
1097*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_PHANTOM_SWITCH = 9,
1098*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_PHANTOM_PERSISTENCE = 10,
1099*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_DIRECT_MONITOR = 11,
1100*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH = 12,
1101*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE = 13,
1102*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_TALKBACK_MAP = 14,
1103*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_CONFIG_COUNT = 15
1104*771ad4dfSGeoffrey D. Bennett };
1105*771ad4dfSGeoffrey D. Bennett 
1106*771ad4dfSGeoffrey D. Bennett /* Location, size, and activation command number for the configuration
1107*771ad4dfSGeoffrey D. Bennett  * parameters. Size is in bits and may be 1, 8, or 16.
1108*771ad4dfSGeoffrey D. Bennett  */
1109*771ad4dfSGeoffrey D. Bennett struct scarlett2_config {
1110*771ad4dfSGeoffrey D. Bennett 	u8 offset;
1111*771ad4dfSGeoffrey D. Bennett 	u8 size;
1112*771ad4dfSGeoffrey D. Bennett 	u8 activate;
1113*771ad4dfSGeoffrey D. Bennett };
1114*771ad4dfSGeoffrey D. Bennett 
1115*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_config
1116*771ad4dfSGeoffrey D. Bennett 	scarlett2_config_items[SCARLETT2_CONFIG_SET_COUNT]
1117*771ad4dfSGeoffrey D. Bennett 			      [SCARLETT2_CONFIG_COUNT] =
1118*771ad4dfSGeoffrey D. Bennett 
1119*771ad4dfSGeoffrey D. Bennett /* Devices without a mixer (Gen 3 Solo and 2i2) */
1120*771ad4dfSGeoffrey D. Bennett { {
1121*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_MSD_SWITCH] = {
1122*771ad4dfSGeoffrey D. Bennett 		.offset = 0x04, .size = 8, .activate = 6 },
1123*771ad4dfSGeoffrey D. Bennett 
1124*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = {
1125*771ad4dfSGeoffrey D. Bennett 		.offset = 0x05, .size = 8, .activate = 6 },
1126*771ad4dfSGeoffrey D. Bennett 
1127*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
1128*771ad4dfSGeoffrey D. Bennett 		.offset = 0x06, .size = 8, .activate = 3 },
1129*771ad4dfSGeoffrey D. Bennett 
1130*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_DIRECT_MONITOR] = {
1131*771ad4dfSGeoffrey D. Bennett 		.offset = 0x07, .size = 8, .activate = 4 },
1132*771ad4dfSGeoffrey D. Bennett 
1133*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_LEVEL_SWITCH] = {
1134*771ad4dfSGeoffrey D. Bennett 		.offset = 0x08, .size = 1, .activate = 7 },
1135*771ad4dfSGeoffrey D. Bennett 
1136*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_AIR_SWITCH] = {
1137*771ad4dfSGeoffrey D. Bennett 		.offset = 0x09, .size = 1, .activate = 8 },
1138*771ad4dfSGeoffrey D. Bennett 
1139*771ad4dfSGeoffrey D. Bennett /* Gen 2 devices: 6i6, 18i8, 18i20 */
1140*771ad4dfSGeoffrey D. Bennett }, {
1141*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_DIM_MUTE] = {
1142*771ad4dfSGeoffrey D. Bennett 		.offset = 0x31, .size = 8, .activate = 2 },
1143*771ad4dfSGeoffrey D. Bennett 
1144*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
1145*771ad4dfSGeoffrey D. Bennett 		.offset = 0x34, .size = 16, .activate = 1 },
1146*771ad4dfSGeoffrey D. Bennett 
1147*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_MUTE_SWITCH] = {
1148*771ad4dfSGeoffrey D. Bennett 		.offset = 0x5c, .size = 8, .activate = 1 },
1149*771ad4dfSGeoffrey D. Bennett 
1150*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_SW_HW_SWITCH] = {
1151*771ad4dfSGeoffrey D. Bennett 		.offset = 0x66, .size = 8, .activate = 3 },
1152*771ad4dfSGeoffrey D. Bennett 
1153*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_LEVEL_SWITCH] = {
1154*771ad4dfSGeoffrey D. Bennett 		.offset = 0x7c, .size = 8, .activate = 7 },
1155*771ad4dfSGeoffrey D. Bennett 
1156*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_PAD_SWITCH] = {
1157*771ad4dfSGeoffrey D. Bennett 		.offset = 0x84, .size = 8, .activate = 8 },
1158*771ad4dfSGeoffrey D. Bennett 
1159*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
1160*771ad4dfSGeoffrey D. Bennett 		.offset = 0x8d, .size = 8, .activate = 6 },
1161*771ad4dfSGeoffrey D. Bennett 
1162*771ad4dfSGeoffrey D. Bennett /* Gen 3 devices: 4i4, 8i6, 18i8, 18i20 */
1163*771ad4dfSGeoffrey D. Bennett }, {
1164*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_DIM_MUTE] = {
1165*771ad4dfSGeoffrey D. Bennett 		.offset = 0x31, .size = 8, .activate = 2 },
1166*771ad4dfSGeoffrey D. Bennett 
1167*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
1168*771ad4dfSGeoffrey D. Bennett 		.offset = 0x34, .size = 16, .activate = 1 },
1169*771ad4dfSGeoffrey D. Bennett 
1170*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_MUTE_SWITCH] = {
1171*771ad4dfSGeoffrey D. Bennett 		.offset = 0x5c, .size = 8, .activate = 1 },
1172*771ad4dfSGeoffrey D. Bennett 
1173*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_SW_HW_SWITCH] = {
1174*771ad4dfSGeoffrey D. Bennett 		.offset = 0x66, .size = 8, .activate = 3 },
1175*771ad4dfSGeoffrey D. Bennett 
1176*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_LEVEL_SWITCH] = {
1177*771ad4dfSGeoffrey D. Bennett 		.offset = 0x7c, .size = 8, .activate = 7 },
1178*771ad4dfSGeoffrey D. Bennett 
1179*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_PAD_SWITCH] = {
1180*771ad4dfSGeoffrey D. Bennett 		.offset = 0x84, .size = 8, .activate = 8 },
1181*771ad4dfSGeoffrey D. Bennett 
1182*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_AIR_SWITCH] = {
1183*771ad4dfSGeoffrey D. Bennett 		.offset = 0x8c, .size = 8, .activate = 8 },
1184*771ad4dfSGeoffrey D. Bennett 
1185*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
1186*771ad4dfSGeoffrey D. Bennett 		.offset = 0x95, .size = 8, .activate = 6 },
1187*771ad4dfSGeoffrey D. Bennett 
1188*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
1189*771ad4dfSGeoffrey D. Bennett 		.offset = 0x9c, .size = 1, .activate = 8 },
1190*771ad4dfSGeoffrey D. Bennett 
1191*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_MSD_SWITCH] = {
1192*771ad4dfSGeoffrey D. Bennett 		.offset = 0x9d, .size = 8, .activate = 6 },
1193*771ad4dfSGeoffrey D. Bennett 
1194*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = {
1195*771ad4dfSGeoffrey D. Bennett 		.offset = 0x9e, .size = 8, .activate = 6 },
1196*771ad4dfSGeoffrey D. Bennett 
1197*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH] = {
1198*771ad4dfSGeoffrey D. Bennett 		.offset = 0x9f, .size = 1, .activate = 10 },
1199*771ad4dfSGeoffrey D. Bennett 
1200*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE] = {
1201*771ad4dfSGeoffrey D. Bennett 		.offset = 0xa0, .size = 1, .activate = 10 },
1202*771ad4dfSGeoffrey D. Bennett 
1203*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_TALKBACK_MAP] = {
1204*771ad4dfSGeoffrey D. Bennett 		.offset = 0xb0, .size = 16, .activate = 10 },
1205*771ad4dfSGeoffrey D. Bennett 
1206*771ad4dfSGeoffrey D. Bennett /* Clarett USB and Clarett+ devices: 2Pre, 4Pre, 8Pre */
1207*771ad4dfSGeoffrey D. Bennett }, {
1208*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_DIM_MUTE] = {
1209*771ad4dfSGeoffrey D. Bennett 		.offset = 0x31, .size = 8, .activate = 2 },
1210*771ad4dfSGeoffrey D. Bennett 
1211*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
1212*771ad4dfSGeoffrey D. Bennett 		.offset = 0x34, .size = 16, .activate = 1 },
1213*771ad4dfSGeoffrey D. Bennett 
1214*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_MUTE_SWITCH] = {
1215*771ad4dfSGeoffrey D. Bennett 		.offset = 0x5c, .size = 8, .activate = 1 },
1216*771ad4dfSGeoffrey D. Bennett 
1217*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_SW_HW_SWITCH] = {
1218*771ad4dfSGeoffrey D. Bennett 		.offset = 0x66, .size = 8, .activate = 3 },
1219*771ad4dfSGeoffrey D. Bennett 
1220*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_LEVEL_SWITCH] = {
1221*771ad4dfSGeoffrey D. Bennett 		.offset = 0x7c, .size = 8, .activate = 7 },
1222*771ad4dfSGeoffrey D. Bennett 
1223*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_AIR_SWITCH] = {
1224*771ad4dfSGeoffrey D. Bennett 		.offset = 0x95, .size = 8, .activate = 8 },
1225*771ad4dfSGeoffrey D. Bennett 
1226*771ad4dfSGeoffrey D. Bennett 	[SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
1227*771ad4dfSGeoffrey D. Bennett 		.offset = 0x8d, .size = 8, .activate = 6 },
1228*771ad4dfSGeoffrey D. Bennett } };
1229*771ad4dfSGeoffrey D. Bennett 
1230*771ad4dfSGeoffrey D. Bennett /* proprietary request/response format */
1231*771ad4dfSGeoffrey D. Bennett struct scarlett2_usb_packet {
1232*771ad4dfSGeoffrey D. Bennett 	__le32 cmd;
1233*771ad4dfSGeoffrey D. Bennett 	__le16 size;
1234*771ad4dfSGeoffrey D. Bennett 	__le16 seq;
1235*771ad4dfSGeoffrey D. Bennett 	__le32 error;
1236*771ad4dfSGeoffrey D. Bennett 	__le32 pad;
1237*771ad4dfSGeoffrey D. Bennett 	u8 data[];
1238*771ad4dfSGeoffrey D. Bennett };
1239*771ad4dfSGeoffrey D. Bennett 
scarlett2_fill_request_header(struct scarlett2_data * private,struct scarlett2_usb_packet * req,u32 cmd,u16 req_size)1240*771ad4dfSGeoffrey D. Bennett static void scarlett2_fill_request_header(struct scarlett2_data *private,
1241*771ad4dfSGeoffrey D. Bennett 					  struct scarlett2_usb_packet *req,
1242*771ad4dfSGeoffrey D. Bennett 					  u32 cmd, u16 req_size)
1243*771ad4dfSGeoffrey D. Bennett {
1244*771ad4dfSGeoffrey D. Bennett 	/* sequence must go up by 1 for each request */
1245*771ad4dfSGeoffrey D. Bennett 	u16 seq = private->scarlett2_seq++;
1246*771ad4dfSGeoffrey D. Bennett 
1247*771ad4dfSGeoffrey D. Bennett 	req->cmd = cpu_to_le32(cmd);
1248*771ad4dfSGeoffrey D. Bennett 	req->size = cpu_to_le16(req_size);
1249*771ad4dfSGeoffrey D. Bennett 	req->seq = cpu_to_le16(seq);
1250*771ad4dfSGeoffrey D. Bennett 	req->error = 0;
1251*771ad4dfSGeoffrey D. Bennett 	req->pad = 0;
1252*771ad4dfSGeoffrey D. Bennett }
1253*771ad4dfSGeoffrey D. Bennett 
scarlett2_usb_tx(struct usb_device * dev,int interface,void * buf,u16 size)1254*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_tx(struct usb_device *dev, int interface,
1255*771ad4dfSGeoffrey D. Bennett 			    void *buf, u16 size)
1256*771ad4dfSGeoffrey D. Bennett {
1257*771ad4dfSGeoffrey D. Bennett 	return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1258*771ad4dfSGeoffrey D. Bennett 			SCARLETT2_USB_CMD_REQ,
1259*771ad4dfSGeoffrey D. Bennett 			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
1260*771ad4dfSGeoffrey D. Bennett 			0, interface, buf, size);
1261*771ad4dfSGeoffrey D. Bennett }
1262*771ad4dfSGeoffrey D. Bennett 
scarlett2_usb_rx(struct usb_device * dev,int interface,u32 usb_req,void * buf,u16 size)1263*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_rx(struct usb_device *dev, int interface,
1264*771ad4dfSGeoffrey D. Bennett 			    u32 usb_req, void *buf, u16 size)
1265*771ad4dfSGeoffrey D. Bennett {
1266*771ad4dfSGeoffrey D. Bennett 	return snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
1267*771ad4dfSGeoffrey D. Bennett 			usb_req,
1268*771ad4dfSGeoffrey D. Bennett 			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
1269*771ad4dfSGeoffrey D. Bennett 			0, interface, buf, size);
1270*771ad4dfSGeoffrey D. Bennett }
1271*771ad4dfSGeoffrey D. Bennett 
1272*771ad4dfSGeoffrey D. Bennett /* Send a proprietary format request to the Scarlett interface */
scarlett2_usb(struct usb_mixer_interface * mixer,u32 cmd,void * req_data,u16 req_size,void * resp_data,u16 resp_size)1273*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb(
1274*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer, u32 cmd,
1275*771ad4dfSGeoffrey D. Bennett 	void *req_data, u16 req_size, void *resp_data, u16 resp_size)
1276*771ad4dfSGeoffrey D. Bennett {
1277*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1278*771ad4dfSGeoffrey D. Bennett 	struct usb_device *dev = mixer->chip->dev;
1279*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_usb_packet *req, *resp = NULL;
1280*771ad4dfSGeoffrey D. Bennett 	size_t req_buf_size = struct_size(req, data, req_size);
1281*771ad4dfSGeoffrey D. Bennett 	size_t resp_buf_size = struct_size(resp, data, resp_size);
1282*771ad4dfSGeoffrey D. Bennett 	int err;
1283*771ad4dfSGeoffrey D. Bennett 
1284*771ad4dfSGeoffrey D. Bennett 	req = kmalloc(req_buf_size, GFP_KERNEL);
1285*771ad4dfSGeoffrey D. Bennett 	if (!req) {
1286*771ad4dfSGeoffrey D. Bennett 		err = -ENOMEM;
1287*771ad4dfSGeoffrey D. Bennett 		goto error;
1288*771ad4dfSGeoffrey D. Bennett 	}
1289*771ad4dfSGeoffrey D. Bennett 
1290*771ad4dfSGeoffrey D. Bennett 	resp = kmalloc(resp_buf_size, GFP_KERNEL);
1291*771ad4dfSGeoffrey D. Bennett 	if (!resp) {
1292*771ad4dfSGeoffrey D. Bennett 		err = -ENOMEM;
1293*771ad4dfSGeoffrey D. Bennett 		goto error;
1294*771ad4dfSGeoffrey D. Bennett 	}
1295*771ad4dfSGeoffrey D. Bennett 
1296*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->usb_mutex);
1297*771ad4dfSGeoffrey D. Bennett 
1298*771ad4dfSGeoffrey D. Bennett 	/* build request message and send it */
1299*771ad4dfSGeoffrey D. Bennett 
1300*771ad4dfSGeoffrey D. Bennett 	scarlett2_fill_request_header(private, req, cmd, req_size);
1301*771ad4dfSGeoffrey D. Bennett 
1302*771ad4dfSGeoffrey D. Bennett 	if (req_size)
1303*771ad4dfSGeoffrey D. Bennett 		memcpy(req->data, req_data, req_size);
1304*771ad4dfSGeoffrey D. Bennett 
1305*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_tx(dev, private->bInterfaceNumber,
1306*771ad4dfSGeoffrey D. Bennett 			       req, req_buf_size);
1307*771ad4dfSGeoffrey D. Bennett 
1308*771ad4dfSGeoffrey D. Bennett 	if (err != req_buf_size) {
1309*771ad4dfSGeoffrey D. Bennett 		usb_audio_err(
1310*771ad4dfSGeoffrey D. Bennett 			mixer->chip,
1311*771ad4dfSGeoffrey D. Bennett 			"%s USB request result cmd %x was %d\n",
1312*771ad4dfSGeoffrey D. Bennett 			private->series_name, cmd, err);
1313*771ad4dfSGeoffrey D. Bennett 		err = -EINVAL;
1314*771ad4dfSGeoffrey D. Bennett 		goto unlock;
1315*771ad4dfSGeoffrey D. Bennett 	}
1316*771ad4dfSGeoffrey D. Bennett 
1317*771ad4dfSGeoffrey D. Bennett 	/* send a second message to get the response */
1318*771ad4dfSGeoffrey D. Bennett 
1319*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_rx(dev, private->bInterfaceNumber,
1320*771ad4dfSGeoffrey D. Bennett 			       SCARLETT2_USB_CMD_RESP,
1321*771ad4dfSGeoffrey D. Bennett 			       resp, resp_buf_size);
1322*771ad4dfSGeoffrey D. Bennett 
1323*771ad4dfSGeoffrey D. Bennett 	/* validate the response */
1324*771ad4dfSGeoffrey D. Bennett 
1325*771ad4dfSGeoffrey D. Bennett 	if (err != resp_buf_size) {
1326*771ad4dfSGeoffrey D. Bennett 		usb_audio_err(
1327*771ad4dfSGeoffrey D. Bennett 			mixer->chip,
1328*771ad4dfSGeoffrey D. Bennett 			"%s USB response result cmd %x was %d expected %zu\n",
1329*771ad4dfSGeoffrey D. Bennett 			private->series_name, cmd, err, resp_buf_size);
1330*771ad4dfSGeoffrey D. Bennett 		err = -EINVAL;
1331*771ad4dfSGeoffrey D. Bennett 		goto unlock;
1332*771ad4dfSGeoffrey D. Bennett 	}
1333*771ad4dfSGeoffrey D. Bennett 
1334*771ad4dfSGeoffrey D. Bennett 	/* cmd/seq/size should match except when initialising
1335*771ad4dfSGeoffrey D. Bennett 	 * seq sent = 1, response = 0
1336*771ad4dfSGeoffrey D. Bennett 	 */
1337*771ad4dfSGeoffrey D. Bennett 	if (resp->cmd != req->cmd ||
1338*771ad4dfSGeoffrey D. Bennett 	    (resp->seq != req->seq &&
1339*771ad4dfSGeoffrey D. Bennett 		(le16_to_cpu(req->seq) != 1 || resp->seq != 0)) ||
1340*771ad4dfSGeoffrey D. Bennett 	    resp_size != le16_to_cpu(resp->size) ||
1341*771ad4dfSGeoffrey D. Bennett 	    resp->error ||
1342*771ad4dfSGeoffrey D. Bennett 	    resp->pad) {
1343*771ad4dfSGeoffrey D. Bennett 		usb_audio_err(
1344*771ad4dfSGeoffrey D. Bennett 			mixer->chip,
1345*771ad4dfSGeoffrey D. Bennett 			"%s USB invalid response; "
1346*771ad4dfSGeoffrey D. Bennett 			   "cmd tx/rx %d/%d seq %d/%d size %d/%d "
1347*771ad4dfSGeoffrey D. Bennett 			   "error %d pad %d\n",
1348*771ad4dfSGeoffrey D. Bennett 			private->series_name,
1349*771ad4dfSGeoffrey D. Bennett 			le32_to_cpu(req->cmd), le32_to_cpu(resp->cmd),
1350*771ad4dfSGeoffrey D. Bennett 			le16_to_cpu(req->seq), le16_to_cpu(resp->seq),
1351*771ad4dfSGeoffrey D. Bennett 			resp_size, le16_to_cpu(resp->size),
1352*771ad4dfSGeoffrey D. Bennett 			le32_to_cpu(resp->error),
1353*771ad4dfSGeoffrey D. Bennett 			le32_to_cpu(resp->pad));
1354*771ad4dfSGeoffrey D. Bennett 		err = -EINVAL;
1355*771ad4dfSGeoffrey D. Bennett 		goto unlock;
1356*771ad4dfSGeoffrey D. Bennett 	}
1357*771ad4dfSGeoffrey D. Bennett 
1358*771ad4dfSGeoffrey D. Bennett 	if (resp_data && resp_size > 0)
1359*771ad4dfSGeoffrey D. Bennett 		memcpy(resp_data, resp->data, resp_size);
1360*771ad4dfSGeoffrey D. Bennett 
1361*771ad4dfSGeoffrey D. Bennett unlock:
1362*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->usb_mutex);
1363*771ad4dfSGeoffrey D. Bennett error:
1364*771ad4dfSGeoffrey D. Bennett 	kfree(req);
1365*771ad4dfSGeoffrey D. Bennett 	kfree(resp);
1366*771ad4dfSGeoffrey D. Bennett 	return err;
1367*771ad4dfSGeoffrey D. Bennett }
1368*771ad4dfSGeoffrey D. Bennett 
1369*771ad4dfSGeoffrey D. Bennett /* Send a USB message to get data; result placed in *buf */
scarlett2_usb_get(struct usb_mixer_interface * mixer,int offset,void * buf,int size)1370*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_get(
1371*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer,
1372*771ad4dfSGeoffrey D. Bennett 	int offset, void *buf, int size)
1373*771ad4dfSGeoffrey D. Bennett {
1374*771ad4dfSGeoffrey D. Bennett 	struct {
1375*771ad4dfSGeoffrey D. Bennett 		__le32 offset;
1376*771ad4dfSGeoffrey D. Bennett 		__le32 size;
1377*771ad4dfSGeoffrey D. Bennett 	} __packed req;
1378*771ad4dfSGeoffrey D. Bennett 
1379*771ad4dfSGeoffrey D. Bennett 	req.offset = cpu_to_le32(offset);
1380*771ad4dfSGeoffrey D. Bennett 	req.size = cpu_to_le32(size);
1381*771ad4dfSGeoffrey D. Bennett 	return scarlett2_usb(mixer, SCARLETT2_USB_GET_DATA,
1382*771ad4dfSGeoffrey D. Bennett 			     &req, sizeof(req), buf, size);
1383*771ad4dfSGeoffrey D. Bennett }
1384*771ad4dfSGeoffrey D. Bennett 
1385*771ad4dfSGeoffrey D. Bennett /* Send a USB message to get configuration parameters; result placed in *buf */
scarlett2_usb_get_config(struct usb_mixer_interface * mixer,int config_item_num,int count,void * buf)1386*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_get_config(
1387*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer,
1388*771ad4dfSGeoffrey D. Bennett 	int config_item_num, int count, void *buf)
1389*771ad4dfSGeoffrey D. Bennett {
1390*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1391*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
1392*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_config *config_item =
1393*771ad4dfSGeoffrey D. Bennett 		&scarlett2_config_items[info->config_set][config_item_num];
1394*771ad4dfSGeoffrey D. Bennett 	int size, err, i;
1395*771ad4dfSGeoffrey D. Bennett 	u8 *buf_8;
1396*771ad4dfSGeoffrey D. Bennett 	u8 value;
1397*771ad4dfSGeoffrey D. Bennett 
1398*771ad4dfSGeoffrey D. Bennett 	/* For byte-sized parameters, retrieve directly into buf */
1399*771ad4dfSGeoffrey D. Bennett 	if (config_item->size >= 8) {
1400*771ad4dfSGeoffrey D. Bennett 		size = config_item->size / 8 * count;
1401*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_usb_get(mixer, config_item->offset, buf, size);
1402*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
1403*771ad4dfSGeoffrey D. Bennett 			return err;
1404*771ad4dfSGeoffrey D. Bennett 		if (size == 2) {
1405*771ad4dfSGeoffrey D. Bennett 			u16 *buf_16 = buf;
1406*771ad4dfSGeoffrey D. Bennett 
1407*771ad4dfSGeoffrey D. Bennett 			for (i = 0; i < count; i++, buf_16++)
1408*771ad4dfSGeoffrey D. Bennett 				*buf_16 = le16_to_cpu(*(__le16 *)buf_16);
1409*771ad4dfSGeoffrey D. Bennett 		}
1410*771ad4dfSGeoffrey D. Bennett 		return 0;
1411*771ad4dfSGeoffrey D. Bennett 	}
1412*771ad4dfSGeoffrey D. Bennett 
1413*771ad4dfSGeoffrey D. Bennett 	/* For bit-sized parameters, retrieve into value */
1414*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_get(mixer, config_item->offset, &value, 1);
1415*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1416*771ad4dfSGeoffrey D. Bennett 		return err;
1417*771ad4dfSGeoffrey D. Bennett 
1418*771ad4dfSGeoffrey D. Bennett 	/* then unpack from value into buf[] */
1419*771ad4dfSGeoffrey D. Bennett 	buf_8 = buf;
1420*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < 8 && i < count; i++, value >>= 1)
1421*771ad4dfSGeoffrey D. Bennett 		*buf_8++ = value & 1;
1422*771ad4dfSGeoffrey D. Bennett 
1423*771ad4dfSGeoffrey D. Bennett 	return 0;
1424*771ad4dfSGeoffrey D. Bennett }
1425*771ad4dfSGeoffrey D. Bennett 
1426*771ad4dfSGeoffrey D. Bennett /* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */
scarlett2_config_save(struct usb_mixer_interface * mixer)1427*771ad4dfSGeoffrey D. Bennett static void scarlett2_config_save(struct usb_mixer_interface *mixer)
1428*771ad4dfSGeoffrey D. Bennett {
1429*771ad4dfSGeoffrey D. Bennett 	__le32 req = cpu_to_le32(SCARLETT2_USB_CONFIG_SAVE);
1430*771ad4dfSGeoffrey D. Bennett 
1431*771ad4dfSGeoffrey D. Bennett 	int err = scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD,
1432*771ad4dfSGeoffrey D. Bennett 				&req, sizeof(u32),
1433*771ad4dfSGeoffrey D. Bennett 				NULL, 0);
1434*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1435*771ad4dfSGeoffrey D. Bennett 		usb_audio_err(mixer->chip, "config save failed: %d\n", err);
1436*771ad4dfSGeoffrey D. Bennett }
1437*771ad4dfSGeoffrey D. Bennett 
1438*771ad4dfSGeoffrey D. Bennett /* Delayed work to save config */
scarlett2_config_save_work(struct work_struct * work)1439*771ad4dfSGeoffrey D. Bennett static void scarlett2_config_save_work(struct work_struct *work)
1440*771ad4dfSGeoffrey D. Bennett {
1441*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private =
1442*771ad4dfSGeoffrey D. Bennett 		container_of(work, struct scarlett2_data, work.work);
1443*771ad4dfSGeoffrey D. Bennett 
1444*771ad4dfSGeoffrey D. Bennett 	scarlett2_config_save(private->mixer);
1445*771ad4dfSGeoffrey D. Bennett }
1446*771ad4dfSGeoffrey D. Bennett 
1447*771ad4dfSGeoffrey D. Bennett /* Send a USB message to set a SCARLETT2_CONFIG_* parameter */
scarlett2_usb_set_config(struct usb_mixer_interface * mixer,int config_item_num,int index,int value)1448*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_set_config(
1449*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer,
1450*771ad4dfSGeoffrey D. Bennett 	int config_item_num, int index, int value)
1451*771ad4dfSGeoffrey D. Bennett {
1452*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1453*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
1454*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_config *config_item =
1455*771ad4dfSGeoffrey D. Bennett 	       &scarlett2_config_items[info->config_set][config_item_num];
1456*771ad4dfSGeoffrey D. Bennett 	struct {
1457*771ad4dfSGeoffrey D. Bennett 		__le32 offset;
1458*771ad4dfSGeoffrey D. Bennett 		__le32 bytes;
1459*771ad4dfSGeoffrey D. Bennett 		__le32 value;
1460*771ad4dfSGeoffrey D. Bennett 	} __packed req;
1461*771ad4dfSGeoffrey D. Bennett 	__le32 req2;
1462*771ad4dfSGeoffrey D. Bennett 	int offset, size;
1463*771ad4dfSGeoffrey D. Bennett 	int err;
1464*771ad4dfSGeoffrey D. Bennett 
1465*771ad4dfSGeoffrey D. Bennett 	/* Cancel any pending NVRAM save */
1466*771ad4dfSGeoffrey D. Bennett 	cancel_delayed_work_sync(&private->work);
1467*771ad4dfSGeoffrey D. Bennett 
1468*771ad4dfSGeoffrey D. Bennett 	/* Convert config_item->size in bits to size in bytes and
1469*771ad4dfSGeoffrey D. Bennett 	 * calculate offset
1470*771ad4dfSGeoffrey D. Bennett 	 */
1471*771ad4dfSGeoffrey D. Bennett 	if (config_item->size >= 8) {
1472*771ad4dfSGeoffrey D. Bennett 		size = config_item->size / 8;
1473*771ad4dfSGeoffrey D. Bennett 		offset = config_item->offset + index * size;
1474*771ad4dfSGeoffrey D. Bennett 
1475*771ad4dfSGeoffrey D. Bennett 	/* If updating a bit, retrieve the old value, set/clear the
1476*771ad4dfSGeoffrey D. Bennett 	 * bit as needed, and update value
1477*771ad4dfSGeoffrey D. Bennett 	 */
1478*771ad4dfSGeoffrey D. Bennett 	} else {
1479*771ad4dfSGeoffrey D. Bennett 		u8 tmp;
1480*771ad4dfSGeoffrey D. Bennett 
1481*771ad4dfSGeoffrey D. Bennett 		size = 1;
1482*771ad4dfSGeoffrey D. Bennett 		offset = config_item->offset;
1483*771ad4dfSGeoffrey D. Bennett 
1484*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_usb_get(mixer, offset, &tmp, 1);
1485*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
1486*771ad4dfSGeoffrey D. Bennett 			return err;
1487*771ad4dfSGeoffrey D. Bennett 
1488*771ad4dfSGeoffrey D. Bennett 		if (value)
1489*771ad4dfSGeoffrey D. Bennett 			tmp |= (1 << index);
1490*771ad4dfSGeoffrey D. Bennett 		else
1491*771ad4dfSGeoffrey D. Bennett 			tmp &= ~(1 << index);
1492*771ad4dfSGeoffrey D. Bennett 
1493*771ad4dfSGeoffrey D. Bennett 		value = tmp;
1494*771ad4dfSGeoffrey D. Bennett 	}
1495*771ad4dfSGeoffrey D. Bennett 
1496*771ad4dfSGeoffrey D. Bennett 	/* Send the configuration parameter data */
1497*771ad4dfSGeoffrey D. Bennett 	req.offset = cpu_to_le32(offset);
1498*771ad4dfSGeoffrey D. Bennett 	req.bytes = cpu_to_le32(size);
1499*771ad4dfSGeoffrey D. Bennett 	req.value = cpu_to_le32(value);
1500*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb(mixer, SCARLETT2_USB_SET_DATA,
1501*771ad4dfSGeoffrey D. Bennett 			    &req, sizeof(u32) * 2 + size,
1502*771ad4dfSGeoffrey D. Bennett 			    NULL, 0);
1503*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1504*771ad4dfSGeoffrey D. Bennett 		return err;
1505*771ad4dfSGeoffrey D. Bennett 
1506*771ad4dfSGeoffrey D. Bennett 	/* Activate the change */
1507*771ad4dfSGeoffrey D. Bennett 	req2 = cpu_to_le32(config_item->activate);
1508*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD,
1509*771ad4dfSGeoffrey D. Bennett 			    &req2, sizeof(req2), NULL, 0);
1510*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1511*771ad4dfSGeoffrey D. Bennett 		return err;
1512*771ad4dfSGeoffrey D. Bennett 
1513*771ad4dfSGeoffrey D. Bennett 	/* Schedule the change to be written to NVRAM */
1514*771ad4dfSGeoffrey D. Bennett 	if (config_item->activate != SCARLETT2_USB_CONFIG_SAVE)
1515*771ad4dfSGeoffrey D. Bennett 		schedule_delayed_work(&private->work, msecs_to_jiffies(2000));
1516*771ad4dfSGeoffrey D. Bennett 
1517*771ad4dfSGeoffrey D. Bennett 	return 0;
1518*771ad4dfSGeoffrey D. Bennett }
1519*771ad4dfSGeoffrey D. Bennett 
1520*771ad4dfSGeoffrey D. Bennett /* Send a USB message to get sync status; result placed in *sync */
scarlett2_usb_get_sync_status(struct usb_mixer_interface * mixer,u8 * sync)1521*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_get_sync_status(
1522*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer,
1523*771ad4dfSGeoffrey D. Bennett 	u8 *sync)
1524*771ad4dfSGeoffrey D. Bennett {
1525*771ad4dfSGeoffrey D. Bennett 	__le32 data;
1526*771ad4dfSGeoffrey D. Bennett 	int err;
1527*771ad4dfSGeoffrey D. Bennett 
1528*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb(mixer, SCARLETT2_USB_GET_SYNC,
1529*771ad4dfSGeoffrey D. Bennett 			    NULL, 0, &data, sizeof(data));
1530*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1531*771ad4dfSGeoffrey D. Bennett 		return err;
1532*771ad4dfSGeoffrey D. Bennett 
1533*771ad4dfSGeoffrey D. Bennett 	*sync = !!data;
1534*771ad4dfSGeoffrey D. Bennett 	return 0;
1535*771ad4dfSGeoffrey D. Bennett }
1536*771ad4dfSGeoffrey D. Bennett 
1537*771ad4dfSGeoffrey D. Bennett /* Send a USB message to get volume status; result placed in *buf */
scarlett2_usb_get_volume_status(struct usb_mixer_interface * mixer,struct scarlett2_usb_volume_status * buf)1538*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_get_volume_status(
1539*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer,
1540*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_usb_volume_status *buf)
1541*771ad4dfSGeoffrey D. Bennett {
1542*771ad4dfSGeoffrey D. Bennett 	return scarlett2_usb_get(mixer, SCARLETT2_USB_VOLUME_STATUS_OFFSET,
1543*771ad4dfSGeoffrey D. Bennett 				 buf, sizeof(*buf));
1544*771ad4dfSGeoffrey D. Bennett }
1545*771ad4dfSGeoffrey D. Bennett 
1546*771ad4dfSGeoffrey D. Bennett /* Send a USB message to get the volumes for all inputs of one mix
1547*771ad4dfSGeoffrey D. Bennett  * and put the values into private->mix[]
1548*771ad4dfSGeoffrey D. Bennett  */
scarlett2_usb_get_mix(struct usb_mixer_interface * mixer,int mix_num)1549*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_get_mix(struct usb_mixer_interface *mixer,
1550*771ad4dfSGeoffrey D. Bennett 				 int mix_num)
1551*771ad4dfSGeoffrey D. Bennett {
1552*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1553*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
1554*771ad4dfSGeoffrey D. Bennett 
1555*771ad4dfSGeoffrey D. Bennett 	int num_mixer_in =
1556*771ad4dfSGeoffrey D. Bennett 		info->port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT];
1557*771ad4dfSGeoffrey D. Bennett 	int err, i, j, k;
1558*771ad4dfSGeoffrey D. Bennett 
1559*771ad4dfSGeoffrey D. Bennett 	struct {
1560*771ad4dfSGeoffrey D. Bennett 		__le16 mix_num;
1561*771ad4dfSGeoffrey D. Bennett 		__le16 count;
1562*771ad4dfSGeoffrey D. Bennett 	} __packed req;
1563*771ad4dfSGeoffrey D. Bennett 
1564*771ad4dfSGeoffrey D. Bennett 	__le16 data[SCARLETT2_INPUT_MIX_MAX];
1565*771ad4dfSGeoffrey D. Bennett 
1566*771ad4dfSGeoffrey D. Bennett 	req.mix_num = cpu_to_le16(mix_num);
1567*771ad4dfSGeoffrey D. Bennett 	req.count = cpu_to_le16(num_mixer_in);
1568*771ad4dfSGeoffrey D. Bennett 
1569*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb(mixer, SCARLETT2_USB_GET_MIX,
1570*771ad4dfSGeoffrey D. Bennett 			    &req, sizeof(req),
1571*771ad4dfSGeoffrey D. Bennett 			    data, num_mixer_in * sizeof(u16));
1572*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1573*771ad4dfSGeoffrey D. Bennett 		return err;
1574*771ad4dfSGeoffrey D. Bennett 
1575*771ad4dfSGeoffrey D. Bennett 	for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++) {
1576*771ad4dfSGeoffrey D. Bennett 		u16 mixer_value = le16_to_cpu(data[i]);
1577*771ad4dfSGeoffrey D. Bennett 
1578*771ad4dfSGeoffrey D. Bennett 		for (k = 0; k < SCARLETT2_MIXER_VALUE_COUNT; k++)
1579*771ad4dfSGeoffrey D. Bennett 			if (scarlett2_mixer_values[k] >= mixer_value)
1580*771ad4dfSGeoffrey D. Bennett 				break;
1581*771ad4dfSGeoffrey D. Bennett 		if (k == SCARLETT2_MIXER_VALUE_COUNT)
1582*771ad4dfSGeoffrey D. Bennett 			k = SCARLETT2_MIXER_MAX_VALUE;
1583*771ad4dfSGeoffrey D. Bennett 		private->mix[j] = k;
1584*771ad4dfSGeoffrey D. Bennett 	}
1585*771ad4dfSGeoffrey D. Bennett 
1586*771ad4dfSGeoffrey D. Bennett 	return 0;
1587*771ad4dfSGeoffrey D. Bennett }
1588*771ad4dfSGeoffrey D. Bennett 
1589*771ad4dfSGeoffrey D. Bennett /* Send a USB message to set the volumes for all inputs of one mix
1590*771ad4dfSGeoffrey D. Bennett  * (values obtained from private->mix[])
1591*771ad4dfSGeoffrey D. Bennett  */
scarlett2_usb_set_mix(struct usb_mixer_interface * mixer,int mix_num)1592*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer,
1593*771ad4dfSGeoffrey D. Bennett 				 int mix_num)
1594*771ad4dfSGeoffrey D. Bennett {
1595*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1596*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
1597*771ad4dfSGeoffrey D. Bennett 
1598*771ad4dfSGeoffrey D. Bennett 	struct {
1599*771ad4dfSGeoffrey D. Bennett 		__le16 mix_num;
1600*771ad4dfSGeoffrey D. Bennett 		__le16 data[SCARLETT2_INPUT_MIX_MAX];
1601*771ad4dfSGeoffrey D. Bennett 	} __packed req;
1602*771ad4dfSGeoffrey D. Bennett 
1603*771ad4dfSGeoffrey D. Bennett 	int i, j;
1604*771ad4dfSGeoffrey D. Bennett 	int num_mixer_in =
1605*771ad4dfSGeoffrey D. Bennett 		info->port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT];
1606*771ad4dfSGeoffrey D. Bennett 
1607*771ad4dfSGeoffrey D. Bennett 	req.mix_num = cpu_to_le16(mix_num);
1608*771ad4dfSGeoffrey D. Bennett 
1609*771ad4dfSGeoffrey D. Bennett 	for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++)
1610*771ad4dfSGeoffrey D. Bennett 		req.data[i] = cpu_to_le16(
1611*771ad4dfSGeoffrey D. Bennett 			scarlett2_mixer_values[private->mix[j]]
1612*771ad4dfSGeoffrey D. Bennett 		);
1613*771ad4dfSGeoffrey D. Bennett 
1614*771ad4dfSGeoffrey D. Bennett 	return scarlett2_usb(mixer, SCARLETT2_USB_SET_MIX,
1615*771ad4dfSGeoffrey D. Bennett 			     &req, (num_mixer_in + 1) * sizeof(u16),
1616*771ad4dfSGeoffrey D. Bennett 			     NULL, 0);
1617*771ad4dfSGeoffrey D. Bennett }
1618*771ad4dfSGeoffrey D. Bennett 
1619*771ad4dfSGeoffrey D. Bennett /* Convert a port number index (per info->port_count) to a hardware ID */
scarlett2_mux_src_num_to_id(const int port_count[][SCARLETT2_PORT_DIRNS],int num)1620*771ad4dfSGeoffrey D. Bennett static u32 scarlett2_mux_src_num_to_id(
1621*771ad4dfSGeoffrey D. Bennett 	const int port_count[][SCARLETT2_PORT_DIRNS], int num)
1622*771ad4dfSGeoffrey D. Bennett {
1623*771ad4dfSGeoffrey D. Bennett 	int port_type;
1624*771ad4dfSGeoffrey D. Bennett 
1625*771ad4dfSGeoffrey D. Bennett 	for (port_type = 0;
1626*771ad4dfSGeoffrey D. Bennett 	     port_type < SCARLETT2_PORT_TYPE_COUNT;
1627*771ad4dfSGeoffrey D. Bennett 	     port_type++) {
1628*771ad4dfSGeoffrey D. Bennett 		if (num < port_count[port_type][SCARLETT2_PORT_IN])
1629*771ad4dfSGeoffrey D. Bennett 			return scarlett2_ports[port_type].id | num;
1630*771ad4dfSGeoffrey D. Bennett 		num -= port_count[port_type][SCARLETT2_PORT_IN];
1631*771ad4dfSGeoffrey D. Bennett 	}
1632*771ad4dfSGeoffrey D. Bennett 
1633*771ad4dfSGeoffrey D. Bennett 	/* Oops */
1634*771ad4dfSGeoffrey D. Bennett 	return 0;
1635*771ad4dfSGeoffrey D. Bennett }
1636*771ad4dfSGeoffrey D. Bennett 
1637*771ad4dfSGeoffrey D. Bennett /* Convert a hardware ID to a port number index */
scarlett2_mux_id_to_num(const int port_count[][SCARLETT2_PORT_DIRNS],int direction,u32 id)1638*771ad4dfSGeoffrey D. Bennett static u32 scarlett2_mux_id_to_num(
1639*771ad4dfSGeoffrey D. Bennett 	const int port_count[][SCARLETT2_PORT_DIRNS], int direction, u32 id)
1640*771ad4dfSGeoffrey D. Bennett {
1641*771ad4dfSGeoffrey D. Bennett 	int port_type;
1642*771ad4dfSGeoffrey D. Bennett 	int port_num = 0;
1643*771ad4dfSGeoffrey D. Bennett 
1644*771ad4dfSGeoffrey D. Bennett 	for (port_type = 0;
1645*771ad4dfSGeoffrey D. Bennett 	     port_type < SCARLETT2_PORT_TYPE_COUNT;
1646*771ad4dfSGeoffrey D. Bennett 	     port_type++) {
1647*771ad4dfSGeoffrey D. Bennett 		int base = scarlett2_ports[port_type].id;
1648*771ad4dfSGeoffrey D. Bennett 		int count = port_count[port_type][direction];
1649*771ad4dfSGeoffrey D. Bennett 
1650*771ad4dfSGeoffrey D. Bennett 		if (id >= base && id < base + count)
1651*771ad4dfSGeoffrey D. Bennett 			return port_num + id - base;
1652*771ad4dfSGeoffrey D. Bennett 		port_num += count;
1653*771ad4dfSGeoffrey D. Bennett 	}
1654*771ad4dfSGeoffrey D. Bennett 
1655*771ad4dfSGeoffrey D. Bennett 	/* Oops */
1656*771ad4dfSGeoffrey D. Bennett 	return -1;
1657*771ad4dfSGeoffrey D. Bennett }
1658*771ad4dfSGeoffrey D. Bennett 
1659*771ad4dfSGeoffrey D. Bennett /* Convert one mux entry from the interface and load into private->mux[] */
scarlett2_usb_populate_mux(struct scarlett2_data * private,u32 mux_entry)1660*771ad4dfSGeoffrey D. Bennett static void scarlett2_usb_populate_mux(struct scarlett2_data *private,
1661*771ad4dfSGeoffrey D. Bennett 				       u32 mux_entry)
1662*771ad4dfSGeoffrey D. Bennett {
1663*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
1664*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
1665*771ad4dfSGeoffrey D. Bennett 
1666*771ad4dfSGeoffrey D. Bennett 	int dst_idx, src_idx;
1667*771ad4dfSGeoffrey D. Bennett 
1668*771ad4dfSGeoffrey D. Bennett 	dst_idx = scarlett2_mux_id_to_num(port_count, SCARLETT2_PORT_OUT,
1669*771ad4dfSGeoffrey D. Bennett 					  mux_entry & 0xFFF);
1670*771ad4dfSGeoffrey D. Bennett 	if (dst_idx < 0)
1671*771ad4dfSGeoffrey D. Bennett 		return;
1672*771ad4dfSGeoffrey D. Bennett 
1673*771ad4dfSGeoffrey D. Bennett 	if (dst_idx >= private->num_mux_dsts) {
1674*771ad4dfSGeoffrey D. Bennett 		usb_audio_err(private->mixer->chip,
1675*771ad4dfSGeoffrey D. Bennett 			"BUG: scarlett2_mux_id_to_num(%06x, OUT): %d >= %d",
1676*771ad4dfSGeoffrey D. Bennett 			mux_entry, dst_idx, private->num_mux_dsts);
1677*771ad4dfSGeoffrey D. Bennett 		return;
1678*771ad4dfSGeoffrey D. Bennett 	}
1679*771ad4dfSGeoffrey D. Bennett 
1680*771ad4dfSGeoffrey D. Bennett 	src_idx = scarlett2_mux_id_to_num(port_count, SCARLETT2_PORT_IN,
1681*771ad4dfSGeoffrey D. Bennett 					  mux_entry >> 12);
1682*771ad4dfSGeoffrey D. Bennett 	if (src_idx < 0)
1683*771ad4dfSGeoffrey D. Bennett 		return;
1684*771ad4dfSGeoffrey D. Bennett 
1685*771ad4dfSGeoffrey D. Bennett 	if (src_idx >= private->num_mux_srcs) {
1686*771ad4dfSGeoffrey D. Bennett 		usb_audio_err(private->mixer->chip,
1687*771ad4dfSGeoffrey D. Bennett 			"BUG: scarlett2_mux_id_to_num(%06x, IN): %d >= %d",
1688*771ad4dfSGeoffrey D. Bennett 			mux_entry, src_idx, private->num_mux_srcs);
1689*771ad4dfSGeoffrey D. Bennett 		return;
1690*771ad4dfSGeoffrey D. Bennett 	}
1691*771ad4dfSGeoffrey D. Bennett 
1692*771ad4dfSGeoffrey D. Bennett 	private->mux[dst_idx] = src_idx;
1693*771ad4dfSGeoffrey D. Bennett }
1694*771ad4dfSGeoffrey D. Bennett 
1695*771ad4dfSGeoffrey D. Bennett /* Send USB message to get mux inputs and then populate private->mux[] */
scarlett2_usb_get_mux(struct usb_mixer_interface * mixer)1696*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_get_mux(struct usb_mixer_interface *mixer)
1697*771ad4dfSGeoffrey D. Bennett {
1698*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1699*771ad4dfSGeoffrey D. Bennett 	int count = private->num_mux_dsts;
1700*771ad4dfSGeoffrey D. Bennett 	int err, i;
1701*771ad4dfSGeoffrey D. Bennett 
1702*771ad4dfSGeoffrey D. Bennett 	struct {
1703*771ad4dfSGeoffrey D. Bennett 		__le16 num;
1704*771ad4dfSGeoffrey D. Bennett 		__le16 count;
1705*771ad4dfSGeoffrey D. Bennett 	} __packed req;
1706*771ad4dfSGeoffrey D. Bennett 
1707*771ad4dfSGeoffrey D. Bennett 	__le32 data[SCARLETT2_MUX_MAX];
1708*771ad4dfSGeoffrey D. Bennett 
1709*771ad4dfSGeoffrey D. Bennett 	private->mux_updated = 0;
1710*771ad4dfSGeoffrey D. Bennett 
1711*771ad4dfSGeoffrey D. Bennett 	req.num = 0;
1712*771ad4dfSGeoffrey D. Bennett 	req.count = cpu_to_le16(count);
1713*771ad4dfSGeoffrey D. Bennett 
1714*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb(mixer, SCARLETT2_USB_GET_MUX,
1715*771ad4dfSGeoffrey D. Bennett 			    &req, sizeof(req),
1716*771ad4dfSGeoffrey D. Bennett 			    data, count * sizeof(u32));
1717*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1718*771ad4dfSGeoffrey D. Bennett 		return err;
1719*771ad4dfSGeoffrey D. Bennett 
1720*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < count; i++)
1721*771ad4dfSGeoffrey D. Bennett 		scarlett2_usb_populate_mux(private, le32_to_cpu(data[i]));
1722*771ad4dfSGeoffrey D. Bennett 
1723*771ad4dfSGeoffrey D. Bennett 	return 0;
1724*771ad4dfSGeoffrey D. Bennett }
1725*771ad4dfSGeoffrey D. Bennett 
1726*771ad4dfSGeoffrey D. Bennett /* Send USB messages to set mux inputs */
scarlett2_usb_set_mux(struct usb_mixer_interface * mixer)1727*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer)
1728*771ad4dfSGeoffrey D. Bennett {
1729*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1730*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
1731*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
1732*771ad4dfSGeoffrey D. Bennett 	int table;
1733*771ad4dfSGeoffrey D. Bennett 
1734*771ad4dfSGeoffrey D. Bennett 	struct {
1735*771ad4dfSGeoffrey D. Bennett 		__le16 pad;
1736*771ad4dfSGeoffrey D. Bennett 		__le16 num;
1737*771ad4dfSGeoffrey D. Bennett 		__le32 data[SCARLETT2_MUX_MAX];
1738*771ad4dfSGeoffrey D. Bennett 	} __packed req;
1739*771ad4dfSGeoffrey D. Bennett 
1740*771ad4dfSGeoffrey D. Bennett 	req.pad = 0;
1741*771ad4dfSGeoffrey D. Bennett 
1742*771ad4dfSGeoffrey D. Bennett 	/* set mux settings for each rate */
1743*771ad4dfSGeoffrey D. Bennett 	for (table = 0; table < SCARLETT2_MUX_TABLES; table++) {
1744*771ad4dfSGeoffrey D. Bennett 		const struct scarlett2_mux_entry *entry;
1745*771ad4dfSGeoffrey D. Bennett 
1746*771ad4dfSGeoffrey D. Bennett 		/* i counts over the output array */
1747*771ad4dfSGeoffrey D. Bennett 		int i = 0, err;
1748*771ad4dfSGeoffrey D. Bennett 
1749*771ad4dfSGeoffrey D. Bennett 		req.num = cpu_to_le16(table);
1750*771ad4dfSGeoffrey D. Bennett 
1751*771ad4dfSGeoffrey D. Bennett 		/* loop through each entry */
1752*771ad4dfSGeoffrey D. Bennett 		for (entry = info->mux_assignment[table];
1753*771ad4dfSGeoffrey D. Bennett 		     entry->count;
1754*771ad4dfSGeoffrey D. Bennett 		     entry++) {
1755*771ad4dfSGeoffrey D. Bennett 			int j;
1756*771ad4dfSGeoffrey D. Bennett 			int port_type = entry->port_type;
1757*771ad4dfSGeoffrey D. Bennett 			int port_idx = entry->start;
1758*771ad4dfSGeoffrey D. Bennett 			int mux_idx = scarlett2_get_port_start_num(port_count,
1759*771ad4dfSGeoffrey D. Bennett 				SCARLETT2_PORT_OUT, port_type) + port_idx;
1760*771ad4dfSGeoffrey D. Bennett 			int dst_id = scarlett2_ports[port_type].id + port_idx;
1761*771ad4dfSGeoffrey D. Bennett 
1762*771ad4dfSGeoffrey D. Bennett 			/* Empty slots */
1763*771ad4dfSGeoffrey D. Bennett 			if (!dst_id) {
1764*771ad4dfSGeoffrey D. Bennett 				for (j = 0; j < entry->count; j++)
1765*771ad4dfSGeoffrey D. Bennett 					req.data[i++] = 0;
1766*771ad4dfSGeoffrey D. Bennett 				continue;
1767*771ad4dfSGeoffrey D. Bennett 			}
1768*771ad4dfSGeoffrey D. Bennett 
1769*771ad4dfSGeoffrey D. Bennett 			/* Non-empty mux slots use the lower 12 bits
1770*771ad4dfSGeoffrey D. Bennett 			 * for the destination and next 12 bits for
1771*771ad4dfSGeoffrey D. Bennett 			 * the source
1772*771ad4dfSGeoffrey D. Bennett 			 */
1773*771ad4dfSGeoffrey D. Bennett 			for (j = 0; j < entry->count; j++) {
1774*771ad4dfSGeoffrey D. Bennett 				int src_id = scarlett2_mux_src_num_to_id(
1775*771ad4dfSGeoffrey D. Bennett 					port_count, private->mux[mux_idx++]);
1776*771ad4dfSGeoffrey D. Bennett 				req.data[i++] = cpu_to_le32(dst_id |
1777*771ad4dfSGeoffrey D. Bennett 							    src_id << 12);
1778*771ad4dfSGeoffrey D. Bennett 				dst_id++;
1779*771ad4dfSGeoffrey D. Bennett 			}
1780*771ad4dfSGeoffrey D. Bennett 		}
1781*771ad4dfSGeoffrey D. Bennett 
1782*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_usb(mixer, SCARLETT2_USB_SET_MUX,
1783*771ad4dfSGeoffrey D. Bennett 				    &req, (i + 1) * sizeof(u32),
1784*771ad4dfSGeoffrey D. Bennett 				    NULL, 0);
1785*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
1786*771ad4dfSGeoffrey D. Bennett 			return err;
1787*771ad4dfSGeoffrey D. Bennett 	}
1788*771ad4dfSGeoffrey D. Bennett 
1789*771ad4dfSGeoffrey D. Bennett 	return 0;
1790*771ad4dfSGeoffrey D. Bennett }
1791*771ad4dfSGeoffrey D. Bennett 
1792*771ad4dfSGeoffrey D. Bennett /* Send USB message to get meter levels */
scarlett2_usb_get_meter_levels(struct usb_mixer_interface * mixer,u16 num_meters,u16 * levels)1793*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_get_meter_levels(struct usb_mixer_interface *mixer,
1794*771ad4dfSGeoffrey D. Bennett 					  u16 num_meters, u16 *levels)
1795*771ad4dfSGeoffrey D. Bennett {
1796*771ad4dfSGeoffrey D. Bennett 	struct {
1797*771ad4dfSGeoffrey D. Bennett 		__le16 pad;
1798*771ad4dfSGeoffrey D. Bennett 		__le16 num_meters;
1799*771ad4dfSGeoffrey D. Bennett 		__le32 magic;
1800*771ad4dfSGeoffrey D. Bennett 	} __packed req;
1801*771ad4dfSGeoffrey D. Bennett 	u32 resp[SCARLETT2_MAX_METERS];
1802*771ad4dfSGeoffrey D. Bennett 	int i, err;
1803*771ad4dfSGeoffrey D. Bennett 
1804*771ad4dfSGeoffrey D. Bennett 	req.pad = 0;
1805*771ad4dfSGeoffrey D. Bennett 	req.num_meters = cpu_to_le16(num_meters);
1806*771ad4dfSGeoffrey D. Bennett 	req.magic = cpu_to_le32(SCARLETT2_USB_METER_LEVELS_GET_MAGIC);
1807*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb(mixer, SCARLETT2_USB_GET_METER,
1808*771ad4dfSGeoffrey D. Bennett 			    &req, sizeof(req), resp, num_meters * sizeof(u32));
1809*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1810*771ad4dfSGeoffrey D. Bennett 		return err;
1811*771ad4dfSGeoffrey D. Bennett 
1812*771ad4dfSGeoffrey D. Bennett 	/* copy, convert to u16 */
1813*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < num_meters; i++)
1814*771ad4dfSGeoffrey D. Bennett 		levels[i] = resp[i];
1815*771ad4dfSGeoffrey D. Bennett 
1816*771ad4dfSGeoffrey D. Bennett 	return 0;
1817*771ad4dfSGeoffrey D. Bennett }
1818*771ad4dfSGeoffrey D. Bennett 
1819*771ad4dfSGeoffrey D. Bennett /*** Control Functions ***/
1820*771ad4dfSGeoffrey D. Bennett 
1821*771ad4dfSGeoffrey D. Bennett /* helper function to create a new control */
scarlett2_add_new_ctl(struct usb_mixer_interface * mixer,const struct snd_kcontrol_new * ncontrol,int index,int channels,const char * name,struct snd_kcontrol ** kctl_return)1822*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer,
1823*771ad4dfSGeoffrey D. Bennett 				 const struct snd_kcontrol_new *ncontrol,
1824*771ad4dfSGeoffrey D. Bennett 				 int index, int channels, const char *name,
1825*771ad4dfSGeoffrey D. Bennett 				 struct snd_kcontrol **kctl_return)
1826*771ad4dfSGeoffrey D. Bennett {
1827*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl;
1828*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem;
1829*771ad4dfSGeoffrey D. Bennett 	int err;
1830*771ad4dfSGeoffrey D. Bennett 
1831*771ad4dfSGeoffrey D. Bennett 	elem = kzalloc(sizeof(*elem), GFP_KERNEL);
1832*771ad4dfSGeoffrey D. Bennett 	if (!elem)
1833*771ad4dfSGeoffrey D. Bennett 		return -ENOMEM;
1834*771ad4dfSGeoffrey D. Bennett 
1835*771ad4dfSGeoffrey D. Bennett 	/* We set USB_MIXER_BESPOKEN type, so that the core USB mixer code
1836*771ad4dfSGeoffrey D. Bennett 	 * ignores them for resume and other operations.
1837*771ad4dfSGeoffrey D. Bennett 	 * Also, the head.id field is set to 0, as we don't use this field.
1838*771ad4dfSGeoffrey D. Bennett 	 */
1839*771ad4dfSGeoffrey D. Bennett 	elem->head.mixer = mixer;
1840*771ad4dfSGeoffrey D. Bennett 	elem->control = index;
1841*771ad4dfSGeoffrey D. Bennett 	elem->head.id = 0;
1842*771ad4dfSGeoffrey D. Bennett 	elem->channels = channels;
1843*771ad4dfSGeoffrey D. Bennett 	elem->val_type = USB_MIXER_BESPOKEN;
1844*771ad4dfSGeoffrey D. Bennett 
1845*771ad4dfSGeoffrey D. Bennett 	kctl = snd_ctl_new1(ncontrol, elem);
1846*771ad4dfSGeoffrey D. Bennett 	if (!kctl) {
1847*771ad4dfSGeoffrey D. Bennett 		kfree(elem);
1848*771ad4dfSGeoffrey D. Bennett 		return -ENOMEM;
1849*771ad4dfSGeoffrey D. Bennett 	}
1850*771ad4dfSGeoffrey D. Bennett 	kctl->private_free = snd_usb_mixer_elem_free;
1851*771ad4dfSGeoffrey D. Bennett 
1852*771ad4dfSGeoffrey D. Bennett 	strscpy(kctl->id.name, name, sizeof(kctl->id.name));
1853*771ad4dfSGeoffrey D. Bennett 
1854*771ad4dfSGeoffrey D. Bennett 	err = snd_usb_mixer_add_control(&elem->head, kctl);
1855*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1856*771ad4dfSGeoffrey D. Bennett 		return err;
1857*771ad4dfSGeoffrey D. Bennett 
1858*771ad4dfSGeoffrey D. Bennett 	if (kctl_return)
1859*771ad4dfSGeoffrey D. Bennett 		*kctl_return = kctl;
1860*771ad4dfSGeoffrey D. Bennett 
1861*771ad4dfSGeoffrey D. Bennett 	return 0;
1862*771ad4dfSGeoffrey D. Bennett }
1863*771ad4dfSGeoffrey D. Bennett 
1864*771ad4dfSGeoffrey D. Bennett /*** Sync Control ***/
1865*771ad4dfSGeoffrey D. Bennett 
1866*771ad4dfSGeoffrey D. Bennett /* Update sync control after receiving notification that the status
1867*771ad4dfSGeoffrey D. Bennett  * has changed
1868*771ad4dfSGeoffrey D. Bennett  */
scarlett2_update_sync(struct usb_mixer_interface * mixer)1869*771ad4dfSGeoffrey D. Bennett static int scarlett2_update_sync(struct usb_mixer_interface *mixer)
1870*771ad4dfSGeoffrey D. Bennett {
1871*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1872*771ad4dfSGeoffrey D. Bennett 
1873*771ad4dfSGeoffrey D. Bennett 	private->sync_updated = 0;
1874*771ad4dfSGeoffrey D. Bennett 	return scarlett2_usb_get_sync_status(mixer, &private->sync);
1875*771ad4dfSGeoffrey D. Bennett }
1876*771ad4dfSGeoffrey D. Bennett 
scarlett2_sync_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)1877*771ad4dfSGeoffrey D. Bennett static int scarlett2_sync_ctl_info(struct snd_kcontrol *kctl,
1878*771ad4dfSGeoffrey D. Bennett 				   struct snd_ctl_elem_info *uinfo)
1879*771ad4dfSGeoffrey D. Bennett {
1880*771ad4dfSGeoffrey D. Bennett 	static const char *texts[2] = {
1881*771ad4dfSGeoffrey D. Bennett 		"Unlocked", "Locked"
1882*771ad4dfSGeoffrey D. Bennett 	};
1883*771ad4dfSGeoffrey D. Bennett 	return snd_ctl_enum_info(uinfo, 1, 2, texts);
1884*771ad4dfSGeoffrey D. Bennett }
1885*771ad4dfSGeoffrey D. Bennett 
scarlett2_sync_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)1886*771ad4dfSGeoffrey D. Bennett static int scarlett2_sync_ctl_get(struct snd_kcontrol *kctl,
1887*771ad4dfSGeoffrey D. Bennett 				  struct snd_ctl_elem_value *ucontrol)
1888*771ad4dfSGeoffrey D. Bennett {
1889*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
1890*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
1891*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1892*771ad4dfSGeoffrey D. Bennett 	int err = 0;
1893*771ad4dfSGeoffrey D. Bennett 
1894*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
1895*771ad4dfSGeoffrey D. Bennett 
1896*771ad4dfSGeoffrey D. Bennett 	if (private->sync_updated) {
1897*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_sync(mixer);
1898*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
1899*771ad4dfSGeoffrey D. Bennett 			goto unlock;
1900*771ad4dfSGeoffrey D. Bennett 	}
1901*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.enumerated.item[0] = private->sync;
1902*771ad4dfSGeoffrey D. Bennett 
1903*771ad4dfSGeoffrey D. Bennett unlock:
1904*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
1905*771ad4dfSGeoffrey D. Bennett 	return err;
1906*771ad4dfSGeoffrey D. Bennett }
1907*771ad4dfSGeoffrey D. Bennett 
1908*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_sync_ctl = {
1909*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1910*771ad4dfSGeoffrey D. Bennett 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
1911*771ad4dfSGeoffrey D. Bennett 	.name = "",
1912*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_sync_ctl_info,
1913*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_sync_ctl_get
1914*771ad4dfSGeoffrey D. Bennett };
1915*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_sync_ctl(struct usb_mixer_interface * mixer)1916*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_sync_ctl(struct usb_mixer_interface *mixer)
1917*771ad4dfSGeoffrey D. Bennett {
1918*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1919*771ad4dfSGeoffrey D. Bennett 
1920*771ad4dfSGeoffrey D. Bennett 	/* devices without a mixer also don't support reporting sync status */
1921*771ad4dfSGeoffrey D. Bennett 	if (private->info->config_set == SCARLETT2_CONFIG_SET_NO_MIXER)
1922*771ad4dfSGeoffrey D. Bennett 		return 0;
1923*771ad4dfSGeoffrey D. Bennett 
1924*771ad4dfSGeoffrey D. Bennett 	return scarlett2_add_new_ctl(mixer, &scarlett2_sync_ctl,
1925*771ad4dfSGeoffrey D. Bennett 				     0, 1, "Sync Status", &private->sync_ctl);
1926*771ad4dfSGeoffrey D. Bennett }
1927*771ad4dfSGeoffrey D. Bennett 
1928*771ad4dfSGeoffrey D. Bennett /*** Analogue Line Out Volume Controls ***/
1929*771ad4dfSGeoffrey D. Bennett 
1930*771ad4dfSGeoffrey D. Bennett /* Update hardware volume controls after receiving notification that
1931*771ad4dfSGeoffrey D. Bennett  * they have changed
1932*771ad4dfSGeoffrey D. Bennett  */
scarlett2_update_volumes(struct usb_mixer_interface * mixer)1933*771ad4dfSGeoffrey D. Bennett static int scarlett2_update_volumes(struct usb_mixer_interface *mixer)
1934*771ad4dfSGeoffrey D. Bennett {
1935*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1936*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
1937*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
1938*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_usb_volume_status volume_status;
1939*771ad4dfSGeoffrey D. Bennett 	int num_line_out =
1940*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
1941*771ad4dfSGeoffrey D. Bennett 	int err, i;
1942*771ad4dfSGeoffrey D. Bennett 	int mute;
1943*771ad4dfSGeoffrey D. Bennett 
1944*771ad4dfSGeoffrey D. Bennett 	private->vol_updated = 0;
1945*771ad4dfSGeoffrey D. Bennett 
1946*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_get_volume_status(mixer, &volume_status);
1947*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
1948*771ad4dfSGeoffrey D. Bennett 		return err;
1949*771ad4dfSGeoffrey D. Bennett 
1950*771ad4dfSGeoffrey D. Bennett 	private->master_vol = clamp(
1951*771ad4dfSGeoffrey D. Bennett 		volume_status.master_vol + SCARLETT2_VOLUME_BIAS,
1952*771ad4dfSGeoffrey D. Bennett 		0, SCARLETT2_VOLUME_BIAS);
1953*771ad4dfSGeoffrey D. Bennett 
1954*771ad4dfSGeoffrey D. Bennett 	if (info->line_out_hw_vol)
1955*771ad4dfSGeoffrey D. Bennett 		for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++)
1956*771ad4dfSGeoffrey D. Bennett 			private->dim_mute[i] = !!volume_status.dim_mute[i];
1957*771ad4dfSGeoffrey D. Bennett 
1958*771ad4dfSGeoffrey D. Bennett 	mute = private->dim_mute[SCARLETT2_BUTTON_MUTE];
1959*771ad4dfSGeoffrey D. Bennett 
1960*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < num_line_out; i++)
1961*771ad4dfSGeoffrey D. Bennett 		if (private->vol_sw_hw_switch[i]) {
1962*771ad4dfSGeoffrey D. Bennett 			private->vol[i] = private->master_vol;
1963*771ad4dfSGeoffrey D. Bennett 			private->mute_switch[i] = mute;
1964*771ad4dfSGeoffrey D. Bennett 		}
1965*771ad4dfSGeoffrey D. Bennett 
1966*771ad4dfSGeoffrey D. Bennett 	return 0;
1967*771ad4dfSGeoffrey D. Bennett }
1968*771ad4dfSGeoffrey D. Bennett 
scarlett2_volume_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)1969*771ad4dfSGeoffrey D. Bennett static int scarlett2_volume_ctl_info(struct snd_kcontrol *kctl,
1970*771ad4dfSGeoffrey D. Bennett 				     struct snd_ctl_elem_info *uinfo)
1971*771ad4dfSGeoffrey D. Bennett {
1972*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
1973*771ad4dfSGeoffrey D. Bennett 
1974*771ad4dfSGeoffrey D. Bennett 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1975*771ad4dfSGeoffrey D. Bennett 	uinfo->count = elem->channels;
1976*771ad4dfSGeoffrey D. Bennett 	uinfo->value.integer.min = 0;
1977*771ad4dfSGeoffrey D. Bennett 	uinfo->value.integer.max = SCARLETT2_VOLUME_BIAS;
1978*771ad4dfSGeoffrey D. Bennett 	uinfo->value.integer.step = 1;
1979*771ad4dfSGeoffrey D. Bennett 	return 0;
1980*771ad4dfSGeoffrey D. Bennett }
1981*771ad4dfSGeoffrey D. Bennett 
scarlett2_master_volume_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)1982*771ad4dfSGeoffrey D. Bennett static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl,
1983*771ad4dfSGeoffrey D. Bennett 					   struct snd_ctl_elem_value *ucontrol)
1984*771ad4dfSGeoffrey D. Bennett {
1985*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
1986*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
1987*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
1988*771ad4dfSGeoffrey D. Bennett 	int err = 0;
1989*771ad4dfSGeoffrey D. Bennett 
1990*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
1991*771ad4dfSGeoffrey D. Bennett 
1992*771ad4dfSGeoffrey D. Bennett 	if (private->vol_updated) {
1993*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_volumes(mixer);
1994*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
1995*771ad4dfSGeoffrey D. Bennett 			goto unlock;
1996*771ad4dfSGeoffrey D. Bennett 	}
1997*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->master_vol;
1998*771ad4dfSGeoffrey D. Bennett 
1999*771ad4dfSGeoffrey D. Bennett unlock:
2000*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2001*771ad4dfSGeoffrey D. Bennett 	return err;
2002*771ad4dfSGeoffrey D. Bennett }
2003*771ad4dfSGeoffrey D. Bennett 
line_out_remap(struct scarlett2_data * private,int index)2004*771ad4dfSGeoffrey D. Bennett static int line_out_remap(struct scarlett2_data *private, int index)
2005*771ad4dfSGeoffrey D. Bennett {
2006*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
2007*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
2008*771ad4dfSGeoffrey D. Bennett 	int line_out_count =
2009*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
2010*771ad4dfSGeoffrey D. Bennett 
2011*771ad4dfSGeoffrey D. Bennett 	if (!info->line_out_remap_enable)
2012*771ad4dfSGeoffrey D. Bennett 		return index;
2013*771ad4dfSGeoffrey D. Bennett 
2014*771ad4dfSGeoffrey D. Bennett 	if (index >= line_out_count)
2015*771ad4dfSGeoffrey D. Bennett 		return index;
2016*771ad4dfSGeoffrey D. Bennett 
2017*771ad4dfSGeoffrey D. Bennett 	return info->line_out_remap[index];
2018*771ad4dfSGeoffrey D. Bennett }
2019*771ad4dfSGeoffrey D. Bennett 
scarlett2_volume_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2020*771ad4dfSGeoffrey D. Bennett static int scarlett2_volume_ctl_get(struct snd_kcontrol *kctl,
2021*771ad4dfSGeoffrey D. Bennett 				    struct snd_ctl_elem_value *ucontrol)
2022*771ad4dfSGeoffrey D. Bennett {
2023*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2024*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2025*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2026*771ad4dfSGeoffrey D. Bennett 	int index = line_out_remap(private, elem->control);
2027*771ad4dfSGeoffrey D. Bennett 	int err = 0;
2028*771ad4dfSGeoffrey D. Bennett 
2029*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2030*771ad4dfSGeoffrey D. Bennett 
2031*771ad4dfSGeoffrey D. Bennett 	if (private->vol_updated) {
2032*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_volumes(mixer);
2033*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2034*771ad4dfSGeoffrey D. Bennett 			goto unlock;
2035*771ad4dfSGeoffrey D. Bennett 	}
2036*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->vol[index];
2037*771ad4dfSGeoffrey D. Bennett 
2038*771ad4dfSGeoffrey D. Bennett unlock:
2039*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2040*771ad4dfSGeoffrey D. Bennett 	return err;
2041*771ad4dfSGeoffrey D. Bennett }
2042*771ad4dfSGeoffrey D. Bennett 
scarlett2_volume_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2043*771ad4dfSGeoffrey D. Bennett static int scarlett2_volume_ctl_put(struct snd_kcontrol *kctl,
2044*771ad4dfSGeoffrey D. Bennett 				    struct snd_ctl_elem_value *ucontrol)
2045*771ad4dfSGeoffrey D. Bennett {
2046*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2047*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2048*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2049*771ad4dfSGeoffrey D. Bennett 	int index = line_out_remap(private, elem->control);
2050*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2051*771ad4dfSGeoffrey D. Bennett 
2052*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2053*771ad4dfSGeoffrey D. Bennett 
2054*771ad4dfSGeoffrey D. Bennett 	oval = private->vol[index];
2055*771ad4dfSGeoffrey D. Bennett 	val = ucontrol->value.integer.value[0];
2056*771ad4dfSGeoffrey D. Bennett 
2057*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2058*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2059*771ad4dfSGeoffrey D. Bennett 
2060*771ad4dfSGeoffrey D. Bennett 	private->vol[index] = val;
2061*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME,
2062*771ad4dfSGeoffrey D. Bennett 				       index, val - SCARLETT2_VOLUME_BIAS);
2063*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2064*771ad4dfSGeoffrey D. Bennett 		err = 1;
2065*771ad4dfSGeoffrey D. Bennett 
2066*771ad4dfSGeoffrey D. Bennett unlock:
2067*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2068*771ad4dfSGeoffrey D. Bennett 	return err;
2069*771ad4dfSGeoffrey D. Bennett }
2070*771ad4dfSGeoffrey D. Bennett 
2071*771ad4dfSGeoffrey D. Bennett static const DECLARE_TLV_DB_MINMAX(
2072*771ad4dfSGeoffrey D. Bennett 	db_scale_scarlett2_gain, -SCARLETT2_VOLUME_BIAS * 100, 0
2073*771ad4dfSGeoffrey D. Bennett );
2074*771ad4dfSGeoffrey D. Bennett 
2075*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_master_volume_ctl = {
2076*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2077*771ad4dfSGeoffrey D. Bennett 	.access = SNDRV_CTL_ELEM_ACCESS_READ |
2078*771ad4dfSGeoffrey D. Bennett 		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
2079*771ad4dfSGeoffrey D. Bennett 	.name = "",
2080*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_volume_ctl_info,
2081*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_master_volume_ctl_get,
2082*771ad4dfSGeoffrey D. Bennett 	.private_value = 0, /* max value */
2083*771ad4dfSGeoffrey D. Bennett 	.tlv = { .p = db_scale_scarlett2_gain }
2084*771ad4dfSGeoffrey D. Bennett };
2085*771ad4dfSGeoffrey D. Bennett 
2086*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_line_out_volume_ctl = {
2087*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2088*771ad4dfSGeoffrey D. Bennett 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
2089*771ad4dfSGeoffrey D. Bennett 		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
2090*771ad4dfSGeoffrey D. Bennett 	.name = "",
2091*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_volume_ctl_info,
2092*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_volume_ctl_get,
2093*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_volume_ctl_put,
2094*771ad4dfSGeoffrey D. Bennett 	.private_value = 0, /* max value */
2095*771ad4dfSGeoffrey D. Bennett 	.tlv = { .p = db_scale_scarlett2_gain }
2096*771ad4dfSGeoffrey D. Bennett };
2097*771ad4dfSGeoffrey D. Bennett 
2098*771ad4dfSGeoffrey D. Bennett /*** Mute Switch Controls ***/
2099*771ad4dfSGeoffrey D. Bennett 
scarlett2_mute_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2100*771ad4dfSGeoffrey D. Bennett static int scarlett2_mute_ctl_get(struct snd_kcontrol *kctl,
2101*771ad4dfSGeoffrey D. Bennett 					struct snd_ctl_elem_value *ucontrol)
2102*771ad4dfSGeoffrey D. Bennett {
2103*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2104*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2105*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2106*771ad4dfSGeoffrey D. Bennett 	int index = line_out_remap(private, elem->control);
2107*771ad4dfSGeoffrey D. Bennett 	int err = 0;
2108*771ad4dfSGeoffrey D. Bennett 
2109*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2110*771ad4dfSGeoffrey D. Bennett 
2111*771ad4dfSGeoffrey D. Bennett 	if (private->vol_updated) {
2112*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_volumes(mixer);
2113*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2114*771ad4dfSGeoffrey D. Bennett 			goto unlock;
2115*771ad4dfSGeoffrey D. Bennett 	}
2116*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->mute_switch[index];
2117*771ad4dfSGeoffrey D. Bennett 
2118*771ad4dfSGeoffrey D. Bennett unlock:
2119*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2120*771ad4dfSGeoffrey D. Bennett 	return err;
2121*771ad4dfSGeoffrey D. Bennett }
2122*771ad4dfSGeoffrey D. Bennett 
scarlett2_mute_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2123*771ad4dfSGeoffrey D. Bennett static int scarlett2_mute_ctl_put(struct snd_kcontrol *kctl,
2124*771ad4dfSGeoffrey D. Bennett 					struct snd_ctl_elem_value *ucontrol)
2125*771ad4dfSGeoffrey D. Bennett {
2126*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2127*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2128*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2129*771ad4dfSGeoffrey D. Bennett 	int index = line_out_remap(private, elem->control);
2130*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2131*771ad4dfSGeoffrey D. Bennett 
2132*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2133*771ad4dfSGeoffrey D. Bennett 
2134*771ad4dfSGeoffrey D. Bennett 	oval = private->mute_switch[index];
2135*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.integer.value[0];
2136*771ad4dfSGeoffrey D. Bennett 
2137*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2138*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2139*771ad4dfSGeoffrey D. Bennett 
2140*771ad4dfSGeoffrey D. Bennett 	private->mute_switch[index] = val;
2141*771ad4dfSGeoffrey D. Bennett 
2142*771ad4dfSGeoffrey D. Bennett 	/* Send mute change to the device */
2143*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MUTE_SWITCH,
2144*771ad4dfSGeoffrey D. Bennett 				       index, val);
2145*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2146*771ad4dfSGeoffrey D. Bennett 		err = 1;
2147*771ad4dfSGeoffrey D. Bennett 
2148*771ad4dfSGeoffrey D. Bennett unlock:
2149*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2150*771ad4dfSGeoffrey D. Bennett 	return err;
2151*771ad4dfSGeoffrey D. Bennett }
2152*771ad4dfSGeoffrey D. Bennett 
2153*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_mute_ctl = {
2154*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2155*771ad4dfSGeoffrey D. Bennett 	.name = "",
2156*771ad4dfSGeoffrey D. Bennett 	.info = snd_ctl_boolean_mono_info,
2157*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_mute_ctl_get,
2158*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_mute_ctl_put,
2159*771ad4dfSGeoffrey D. Bennett };
2160*771ad4dfSGeoffrey D. Bennett 
2161*771ad4dfSGeoffrey D. Bennett /*** HW/SW Volume Switch Controls ***/
2162*771ad4dfSGeoffrey D. Bennett 
scarlett2_sw_hw_ctl_ro(struct scarlett2_data * private,int index)2163*771ad4dfSGeoffrey D. Bennett static void scarlett2_sw_hw_ctl_ro(struct scarlett2_data *private, int index)
2164*771ad4dfSGeoffrey D. Bennett {
2165*771ad4dfSGeoffrey D. Bennett 	private->sw_hw_ctls[index]->vd[0].access &=
2166*771ad4dfSGeoffrey D. Bennett 		~SNDRV_CTL_ELEM_ACCESS_WRITE;
2167*771ad4dfSGeoffrey D. Bennett }
2168*771ad4dfSGeoffrey D. Bennett 
scarlett2_sw_hw_ctl_rw(struct scarlett2_data * private,int index)2169*771ad4dfSGeoffrey D. Bennett static void scarlett2_sw_hw_ctl_rw(struct scarlett2_data *private, int index)
2170*771ad4dfSGeoffrey D. Bennett {
2171*771ad4dfSGeoffrey D. Bennett 	private->sw_hw_ctls[index]->vd[0].access |=
2172*771ad4dfSGeoffrey D. Bennett 		SNDRV_CTL_ELEM_ACCESS_WRITE;
2173*771ad4dfSGeoffrey D. Bennett }
2174*771ad4dfSGeoffrey D. Bennett 
scarlett2_sw_hw_enum_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)2175*771ad4dfSGeoffrey D. Bennett static int scarlett2_sw_hw_enum_ctl_info(struct snd_kcontrol *kctl,
2176*771ad4dfSGeoffrey D. Bennett 					 struct snd_ctl_elem_info *uinfo)
2177*771ad4dfSGeoffrey D. Bennett {
2178*771ad4dfSGeoffrey D. Bennett 	static const char *const values[2] = {
2179*771ad4dfSGeoffrey D. Bennett 		"SW", "HW"
2180*771ad4dfSGeoffrey D. Bennett 	};
2181*771ad4dfSGeoffrey D. Bennett 
2182*771ad4dfSGeoffrey D. Bennett 	return snd_ctl_enum_info(uinfo, 1, 2, values);
2183*771ad4dfSGeoffrey D. Bennett }
2184*771ad4dfSGeoffrey D. Bennett 
scarlett2_sw_hw_enum_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2185*771ad4dfSGeoffrey D. Bennett static int scarlett2_sw_hw_enum_ctl_get(struct snd_kcontrol *kctl,
2186*771ad4dfSGeoffrey D. Bennett 					struct snd_ctl_elem_value *ucontrol)
2187*771ad4dfSGeoffrey D. Bennett {
2188*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2189*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = elem->head.mixer->private_data;
2190*771ad4dfSGeoffrey D. Bennett 	int index = line_out_remap(private, elem->control);
2191*771ad4dfSGeoffrey D. Bennett 
2192*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.enumerated.item[0] = private->vol_sw_hw_switch[index];
2193*771ad4dfSGeoffrey D. Bennett 	return 0;
2194*771ad4dfSGeoffrey D. Bennett }
2195*771ad4dfSGeoffrey D. Bennett 
scarlett2_vol_ctl_set_writable(struct usb_mixer_interface * mixer,int index,int value)2196*771ad4dfSGeoffrey D. Bennett static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer,
2197*771ad4dfSGeoffrey D. Bennett 					   int index, int value)
2198*771ad4dfSGeoffrey D. Bennett {
2199*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2200*771ad4dfSGeoffrey D. Bennett 	struct snd_card *card = mixer->chip->card;
2201*771ad4dfSGeoffrey D. Bennett 
2202*771ad4dfSGeoffrey D. Bennett 	/* Set/Clear write bits */
2203*771ad4dfSGeoffrey D. Bennett 	if (value) {
2204*771ad4dfSGeoffrey D. Bennett 		private->vol_ctls[index]->vd[0].access |=
2205*771ad4dfSGeoffrey D. Bennett 			SNDRV_CTL_ELEM_ACCESS_WRITE;
2206*771ad4dfSGeoffrey D. Bennett 		private->mute_ctls[index]->vd[0].access |=
2207*771ad4dfSGeoffrey D. Bennett 			SNDRV_CTL_ELEM_ACCESS_WRITE;
2208*771ad4dfSGeoffrey D. Bennett 	} else {
2209*771ad4dfSGeoffrey D. Bennett 		private->vol_ctls[index]->vd[0].access &=
2210*771ad4dfSGeoffrey D. Bennett 			~SNDRV_CTL_ELEM_ACCESS_WRITE;
2211*771ad4dfSGeoffrey D. Bennett 		private->mute_ctls[index]->vd[0].access &=
2212*771ad4dfSGeoffrey D. Bennett 			~SNDRV_CTL_ELEM_ACCESS_WRITE;
2213*771ad4dfSGeoffrey D. Bennett 	}
2214*771ad4dfSGeoffrey D. Bennett 
2215*771ad4dfSGeoffrey D. Bennett 	/* Notify of write bit and possible value change */
2216*771ad4dfSGeoffrey D. Bennett 	snd_ctl_notify(card,
2217*771ad4dfSGeoffrey D. Bennett 		       SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
2218*771ad4dfSGeoffrey D. Bennett 		       &private->vol_ctls[index]->id);
2219*771ad4dfSGeoffrey D. Bennett 	snd_ctl_notify(card,
2220*771ad4dfSGeoffrey D. Bennett 		       SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
2221*771ad4dfSGeoffrey D. Bennett 		       &private->mute_ctls[index]->id);
2222*771ad4dfSGeoffrey D. Bennett }
2223*771ad4dfSGeoffrey D. Bennett 
scarlett2_sw_hw_change(struct usb_mixer_interface * mixer,int ctl_index,int val)2224*771ad4dfSGeoffrey D. Bennett static int scarlett2_sw_hw_change(struct usb_mixer_interface *mixer,
2225*771ad4dfSGeoffrey D. Bennett 				  int ctl_index, int val)
2226*771ad4dfSGeoffrey D. Bennett {
2227*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2228*771ad4dfSGeoffrey D. Bennett 	int index = line_out_remap(private, ctl_index);
2229*771ad4dfSGeoffrey D. Bennett 	int err;
2230*771ad4dfSGeoffrey D. Bennett 
2231*771ad4dfSGeoffrey D. Bennett 	private->vol_sw_hw_switch[index] = val;
2232*771ad4dfSGeoffrey D. Bennett 
2233*771ad4dfSGeoffrey D. Bennett 	/* Change access mode to RO (hardware controlled volume)
2234*771ad4dfSGeoffrey D. Bennett 	 * or RW (software controlled volume)
2235*771ad4dfSGeoffrey D. Bennett 	 */
2236*771ad4dfSGeoffrey D. Bennett 	scarlett2_vol_ctl_set_writable(mixer, ctl_index, !val);
2237*771ad4dfSGeoffrey D. Bennett 
2238*771ad4dfSGeoffrey D. Bennett 	/* Reset volume/mute to master volume/mute */
2239*771ad4dfSGeoffrey D. Bennett 	private->vol[index] = private->master_vol;
2240*771ad4dfSGeoffrey D. Bennett 	private->mute_switch[index] = private->dim_mute[SCARLETT2_BUTTON_MUTE];
2241*771ad4dfSGeoffrey D. Bennett 
2242*771ad4dfSGeoffrey D. Bennett 	/* Set SW volume to current HW volume */
2243*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(
2244*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME,
2245*771ad4dfSGeoffrey D. Bennett 		index, private->master_vol - SCARLETT2_VOLUME_BIAS);
2246*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
2247*771ad4dfSGeoffrey D. Bennett 		return err;
2248*771ad4dfSGeoffrey D. Bennett 
2249*771ad4dfSGeoffrey D. Bennett 	/* Set SW mute to current HW mute */
2250*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(
2251*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_MUTE_SWITCH,
2252*771ad4dfSGeoffrey D. Bennett 		index, private->dim_mute[SCARLETT2_BUTTON_MUTE]);
2253*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
2254*771ad4dfSGeoffrey D. Bennett 		return err;
2255*771ad4dfSGeoffrey D. Bennett 
2256*771ad4dfSGeoffrey D. Bennett 	/* Send SW/HW switch change to the device */
2257*771ad4dfSGeoffrey D. Bennett 	return scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH,
2258*771ad4dfSGeoffrey D. Bennett 					index, val);
2259*771ad4dfSGeoffrey D. Bennett }
2260*771ad4dfSGeoffrey D. Bennett 
scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2261*771ad4dfSGeoffrey D. Bennett static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl,
2262*771ad4dfSGeoffrey D. Bennett 					struct snd_ctl_elem_value *ucontrol)
2263*771ad4dfSGeoffrey D. Bennett {
2264*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2265*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2266*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2267*771ad4dfSGeoffrey D. Bennett 	int ctl_index = elem->control;
2268*771ad4dfSGeoffrey D. Bennett 	int index = line_out_remap(private, ctl_index);
2269*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2270*771ad4dfSGeoffrey D. Bennett 
2271*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2272*771ad4dfSGeoffrey D. Bennett 
2273*771ad4dfSGeoffrey D. Bennett 	oval = private->vol_sw_hw_switch[index];
2274*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.enumerated.item[0];
2275*771ad4dfSGeoffrey D. Bennett 
2276*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2277*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2278*771ad4dfSGeoffrey D. Bennett 
2279*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_sw_hw_change(mixer, ctl_index, val);
2280*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2281*771ad4dfSGeoffrey D. Bennett 		err = 1;
2282*771ad4dfSGeoffrey D. Bennett 
2283*771ad4dfSGeoffrey D. Bennett unlock:
2284*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2285*771ad4dfSGeoffrey D. Bennett 	return err;
2286*771ad4dfSGeoffrey D. Bennett }
2287*771ad4dfSGeoffrey D. Bennett 
2288*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_sw_hw_enum_ctl = {
2289*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2290*771ad4dfSGeoffrey D. Bennett 	.name = "",
2291*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_sw_hw_enum_ctl_info,
2292*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_sw_hw_enum_ctl_get,
2293*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_sw_hw_enum_ctl_put,
2294*771ad4dfSGeoffrey D. Bennett };
2295*771ad4dfSGeoffrey D. Bennett 
2296*771ad4dfSGeoffrey D. Bennett /*** Line Level/Instrument Level Switch Controls ***/
2297*771ad4dfSGeoffrey D. Bennett 
scarlett2_update_input_other(struct usb_mixer_interface * mixer)2298*771ad4dfSGeoffrey D. Bennett static int scarlett2_update_input_other(struct usb_mixer_interface *mixer)
2299*771ad4dfSGeoffrey D. Bennett {
2300*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2301*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
2302*771ad4dfSGeoffrey D. Bennett 
2303*771ad4dfSGeoffrey D. Bennett 	private->input_other_updated = 0;
2304*771ad4dfSGeoffrey D. Bennett 
2305*771ad4dfSGeoffrey D. Bennett 	if (info->level_input_count) {
2306*771ad4dfSGeoffrey D. Bennett 		int err = scarlett2_usb_get_config(
2307*771ad4dfSGeoffrey D. Bennett 			mixer, SCARLETT2_CONFIG_LEVEL_SWITCH,
2308*771ad4dfSGeoffrey D. Bennett 			info->level_input_count + info->level_input_first,
2309*771ad4dfSGeoffrey D. Bennett 			private->level_switch);
2310*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2311*771ad4dfSGeoffrey D. Bennett 			return err;
2312*771ad4dfSGeoffrey D. Bennett 	}
2313*771ad4dfSGeoffrey D. Bennett 
2314*771ad4dfSGeoffrey D. Bennett 	if (info->pad_input_count) {
2315*771ad4dfSGeoffrey D. Bennett 		int err = scarlett2_usb_get_config(
2316*771ad4dfSGeoffrey D. Bennett 			mixer, SCARLETT2_CONFIG_PAD_SWITCH,
2317*771ad4dfSGeoffrey D. Bennett 			info->pad_input_count, private->pad_switch);
2318*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2319*771ad4dfSGeoffrey D. Bennett 			return err;
2320*771ad4dfSGeoffrey D. Bennett 	}
2321*771ad4dfSGeoffrey D. Bennett 
2322*771ad4dfSGeoffrey D. Bennett 	if (info->air_input_count) {
2323*771ad4dfSGeoffrey D. Bennett 		int err = scarlett2_usb_get_config(
2324*771ad4dfSGeoffrey D. Bennett 			mixer, SCARLETT2_CONFIG_AIR_SWITCH,
2325*771ad4dfSGeoffrey D. Bennett 			info->air_input_count, private->air_switch);
2326*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2327*771ad4dfSGeoffrey D. Bennett 			return err;
2328*771ad4dfSGeoffrey D. Bennett 	}
2329*771ad4dfSGeoffrey D. Bennett 
2330*771ad4dfSGeoffrey D. Bennett 	if (info->phantom_count) {
2331*771ad4dfSGeoffrey D. Bennett 		int err = scarlett2_usb_get_config(
2332*771ad4dfSGeoffrey D. Bennett 			mixer, SCARLETT2_CONFIG_PHANTOM_SWITCH,
2333*771ad4dfSGeoffrey D. Bennett 			info->phantom_count, private->phantom_switch);
2334*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2335*771ad4dfSGeoffrey D. Bennett 			return err;
2336*771ad4dfSGeoffrey D. Bennett 
2337*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_usb_get_config(
2338*771ad4dfSGeoffrey D. Bennett 			mixer, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE,
2339*771ad4dfSGeoffrey D. Bennett 			1, &private->phantom_persistence);
2340*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2341*771ad4dfSGeoffrey D. Bennett 			return err;
2342*771ad4dfSGeoffrey D. Bennett 	}
2343*771ad4dfSGeoffrey D. Bennett 
2344*771ad4dfSGeoffrey D. Bennett 	return 0;
2345*771ad4dfSGeoffrey D. Bennett }
2346*771ad4dfSGeoffrey D. Bennett 
scarlett2_level_enum_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)2347*771ad4dfSGeoffrey D. Bennett static int scarlett2_level_enum_ctl_info(struct snd_kcontrol *kctl,
2348*771ad4dfSGeoffrey D. Bennett 					 struct snd_ctl_elem_info *uinfo)
2349*771ad4dfSGeoffrey D. Bennett {
2350*771ad4dfSGeoffrey D. Bennett 	static const char *const values[2] = {
2351*771ad4dfSGeoffrey D. Bennett 		"Line", "Inst"
2352*771ad4dfSGeoffrey D. Bennett 	};
2353*771ad4dfSGeoffrey D. Bennett 
2354*771ad4dfSGeoffrey D. Bennett 	return snd_ctl_enum_info(uinfo, 1, 2, values);
2355*771ad4dfSGeoffrey D. Bennett }
2356*771ad4dfSGeoffrey D. Bennett 
scarlett2_level_enum_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2357*771ad4dfSGeoffrey D. Bennett static int scarlett2_level_enum_ctl_get(struct snd_kcontrol *kctl,
2358*771ad4dfSGeoffrey D. Bennett 					struct snd_ctl_elem_value *ucontrol)
2359*771ad4dfSGeoffrey D. Bennett {
2360*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2361*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2362*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2363*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
2364*771ad4dfSGeoffrey D. Bennett 
2365*771ad4dfSGeoffrey D. Bennett 	int index = elem->control + info->level_input_first;
2366*771ad4dfSGeoffrey D. Bennett 	int err = 0;
2367*771ad4dfSGeoffrey D. Bennett 
2368*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2369*771ad4dfSGeoffrey D. Bennett 
2370*771ad4dfSGeoffrey D. Bennett 	if (private->input_other_updated) {
2371*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_input_other(mixer);
2372*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2373*771ad4dfSGeoffrey D. Bennett 			goto unlock;
2374*771ad4dfSGeoffrey D. Bennett 	}
2375*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.enumerated.item[0] = private->level_switch[index];
2376*771ad4dfSGeoffrey D. Bennett 
2377*771ad4dfSGeoffrey D. Bennett unlock:
2378*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2379*771ad4dfSGeoffrey D. Bennett 	return err;
2380*771ad4dfSGeoffrey D. Bennett }
2381*771ad4dfSGeoffrey D. Bennett 
scarlett2_level_enum_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2382*771ad4dfSGeoffrey D. Bennett static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl,
2383*771ad4dfSGeoffrey D. Bennett 					struct snd_ctl_elem_value *ucontrol)
2384*771ad4dfSGeoffrey D. Bennett {
2385*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2386*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2387*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2388*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
2389*771ad4dfSGeoffrey D. Bennett 
2390*771ad4dfSGeoffrey D. Bennett 	int index = elem->control + info->level_input_first;
2391*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2392*771ad4dfSGeoffrey D. Bennett 
2393*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2394*771ad4dfSGeoffrey D. Bennett 
2395*771ad4dfSGeoffrey D. Bennett 	oval = private->level_switch[index];
2396*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.enumerated.item[0];
2397*771ad4dfSGeoffrey D. Bennett 
2398*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2399*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2400*771ad4dfSGeoffrey D. Bennett 
2401*771ad4dfSGeoffrey D. Bennett 	private->level_switch[index] = val;
2402*771ad4dfSGeoffrey D. Bennett 
2403*771ad4dfSGeoffrey D. Bennett 	/* Send switch change to the device */
2404*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LEVEL_SWITCH,
2405*771ad4dfSGeoffrey D. Bennett 				       index, val);
2406*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2407*771ad4dfSGeoffrey D. Bennett 		err = 1;
2408*771ad4dfSGeoffrey D. Bennett 
2409*771ad4dfSGeoffrey D. Bennett unlock:
2410*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2411*771ad4dfSGeoffrey D. Bennett 	return err;
2412*771ad4dfSGeoffrey D. Bennett }
2413*771ad4dfSGeoffrey D. Bennett 
2414*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_level_enum_ctl = {
2415*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2416*771ad4dfSGeoffrey D. Bennett 	.name = "",
2417*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_level_enum_ctl_info,
2418*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_level_enum_ctl_get,
2419*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_level_enum_ctl_put,
2420*771ad4dfSGeoffrey D. Bennett };
2421*771ad4dfSGeoffrey D. Bennett 
2422*771ad4dfSGeoffrey D. Bennett /*** Pad Switch Controls ***/
2423*771ad4dfSGeoffrey D. Bennett 
scarlett2_pad_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2424*771ad4dfSGeoffrey D. Bennett static int scarlett2_pad_ctl_get(struct snd_kcontrol *kctl,
2425*771ad4dfSGeoffrey D. Bennett 				 struct snd_ctl_elem_value *ucontrol)
2426*771ad4dfSGeoffrey D. Bennett {
2427*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2428*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2429*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2430*771ad4dfSGeoffrey D. Bennett 	int err = 0;
2431*771ad4dfSGeoffrey D. Bennett 
2432*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2433*771ad4dfSGeoffrey D. Bennett 
2434*771ad4dfSGeoffrey D. Bennett 	if (private->input_other_updated) {
2435*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_input_other(mixer);
2436*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2437*771ad4dfSGeoffrey D. Bennett 			goto unlock;
2438*771ad4dfSGeoffrey D. Bennett 	}
2439*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] =
2440*771ad4dfSGeoffrey D. Bennett 		private->pad_switch[elem->control];
2441*771ad4dfSGeoffrey D. Bennett 
2442*771ad4dfSGeoffrey D. Bennett unlock:
2443*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2444*771ad4dfSGeoffrey D. Bennett 	return err;
2445*771ad4dfSGeoffrey D. Bennett }
2446*771ad4dfSGeoffrey D. Bennett 
scarlett2_pad_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2447*771ad4dfSGeoffrey D. Bennett static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl,
2448*771ad4dfSGeoffrey D. Bennett 				 struct snd_ctl_elem_value *ucontrol)
2449*771ad4dfSGeoffrey D. Bennett {
2450*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2451*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2452*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2453*771ad4dfSGeoffrey D. Bennett 
2454*771ad4dfSGeoffrey D. Bennett 	int index = elem->control;
2455*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2456*771ad4dfSGeoffrey D. Bennett 
2457*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2458*771ad4dfSGeoffrey D. Bennett 
2459*771ad4dfSGeoffrey D. Bennett 	oval = private->pad_switch[index];
2460*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.integer.value[0];
2461*771ad4dfSGeoffrey D. Bennett 
2462*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2463*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2464*771ad4dfSGeoffrey D. Bennett 
2465*771ad4dfSGeoffrey D. Bennett 	private->pad_switch[index] = val;
2466*771ad4dfSGeoffrey D. Bennett 
2467*771ad4dfSGeoffrey D. Bennett 	/* Send switch change to the device */
2468*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PAD_SWITCH,
2469*771ad4dfSGeoffrey D. Bennett 				       index, val);
2470*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2471*771ad4dfSGeoffrey D. Bennett 		err = 1;
2472*771ad4dfSGeoffrey D. Bennett 
2473*771ad4dfSGeoffrey D. Bennett unlock:
2474*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2475*771ad4dfSGeoffrey D. Bennett 	return err;
2476*771ad4dfSGeoffrey D. Bennett }
2477*771ad4dfSGeoffrey D. Bennett 
2478*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_pad_ctl = {
2479*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2480*771ad4dfSGeoffrey D. Bennett 	.name = "",
2481*771ad4dfSGeoffrey D. Bennett 	.info = snd_ctl_boolean_mono_info,
2482*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_pad_ctl_get,
2483*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_pad_ctl_put,
2484*771ad4dfSGeoffrey D. Bennett };
2485*771ad4dfSGeoffrey D. Bennett 
2486*771ad4dfSGeoffrey D. Bennett /*** Air Switch Controls ***/
2487*771ad4dfSGeoffrey D. Bennett 
scarlett2_air_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2488*771ad4dfSGeoffrey D. Bennett static int scarlett2_air_ctl_get(struct snd_kcontrol *kctl,
2489*771ad4dfSGeoffrey D. Bennett 				 struct snd_ctl_elem_value *ucontrol)
2490*771ad4dfSGeoffrey D. Bennett {
2491*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2492*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2493*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2494*771ad4dfSGeoffrey D. Bennett 	int err = 0;
2495*771ad4dfSGeoffrey D. Bennett 
2496*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2497*771ad4dfSGeoffrey D. Bennett 
2498*771ad4dfSGeoffrey D. Bennett 	if (private->input_other_updated) {
2499*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_input_other(mixer);
2500*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2501*771ad4dfSGeoffrey D. Bennett 			goto unlock;
2502*771ad4dfSGeoffrey D. Bennett 	}
2503*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->air_switch[elem->control];
2504*771ad4dfSGeoffrey D. Bennett 
2505*771ad4dfSGeoffrey D. Bennett unlock:
2506*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2507*771ad4dfSGeoffrey D. Bennett 	return err;
2508*771ad4dfSGeoffrey D. Bennett }
2509*771ad4dfSGeoffrey D. Bennett 
scarlett2_air_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2510*771ad4dfSGeoffrey D. Bennett static int scarlett2_air_ctl_put(struct snd_kcontrol *kctl,
2511*771ad4dfSGeoffrey D. Bennett 				 struct snd_ctl_elem_value *ucontrol)
2512*771ad4dfSGeoffrey D. Bennett {
2513*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2514*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2515*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2516*771ad4dfSGeoffrey D. Bennett 
2517*771ad4dfSGeoffrey D. Bennett 	int index = elem->control;
2518*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2519*771ad4dfSGeoffrey D. Bennett 
2520*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2521*771ad4dfSGeoffrey D. Bennett 
2522*771ad4dfSGeoffrey D. Bennett 	oval = private->air_switch[index];
2523*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.integer.value[0];
2524*771ad4dfSGeoffrey D. Bennett 
2525*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2526*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2527*771ad4dfSGeoffrey D. Bennett 
2528*771ad4dfSGeoffrey D. Bennett 	private->air_switch[index] = val;
2529*771ad4dfSGeoffrey D. Bennett 
2530*771ad4dfSGeoffrey D. Bennett 	/* Send switch change to the device */
2531*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_AIR_SWITCH,
2532*771ad4dfSGeoffrey D. Bennett 				       index, val);
2533*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2534*771ad4dfSGeoffrey D. Bennett 		err = 1;
2535*771ad4dfSGeoffrey D. Bennett 
2536*771ad4dfSGeoffrey D. Bennett unlock:
2537*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2538*771ad4dfSGeoffrey D. Bennett 	return err;
2539*771ad4dfSGeoffrey D. Bennett }
2540*771ad4dfSGeoffrey D. Bennett 
2541*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_air_ctl = {
2542*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2543*771ad4dfSGeoffrey D. Bennett 	.name = "",
2544*771ad4dfSGeoffrey D. Bennett 	.info = snd_ctl_boolean_mono_info,
2545*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_air_ctl_get,
2546*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_air_ctl_put,
2547*771ad4dfSGeoffrey D. Bennett };
2548*771ad4dfSGeoffrey D. Bennett 
2549*771ad4dfSGeoffrey D. Bennett /*** Phantom Switch Controls ***/
2550*771ad4dfSGeoffrey D. Bennett 
scarlett2_phantom_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2551*771ad4dfSGeoffrey D. Bennett static int scarlett2_phantom_ctl_get(struct snd_kcontrol *kctl,
2552*771ad4dfSGeoffrey D. Bennett 				     struct snd_ctl_elem_value *ucontrol)
2553*771ad4dfSGeoffrey D. Bennett {
2554*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2555*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2556*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2557*771ad4dfSGeoffrey D. Bennett 	int err = 0;
2558*771ad4dfSGeoffrey D. Bennett 
2559*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2560*771ad4dfSGeoffrey D. Bennett 
2561*771ad4dfSGeoffrey D. Bennett 	if (private->input_other_updated) {
2562*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_input_other(mixer);
2563*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2564*771ad4dfSGeoffrey D. Bennett 			goto unlock;
2565*771ad4dfSGeoffrey D. Bennett 	}
2566*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] =
2567*771ad4dfSGeoffrey D. Bennett 		private->phantom_switch[elem->control];
2568*771ad4dfSGeoffrey D. Bennett 
2569*771ad4dfSGeoffrey D. Bennett unlock:
2570*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2571*771ad4dfSGeoffrey D. Bennett 	return err;
2572*771ad4dfSGeoffrey D. Bennett }
2573*771ad4dfSGeoffrey D. Bennett 
scarlett2_phantom_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2574*771ad4dfSGeoffrey D. Bennett static int scarlett2_phantom_ctl_put(struct snd_kcontrol *kctl,
2575*771ad4dfSGeoffrey D. Bennett 				     struct snd_ctl_elem_value *ucontrol)
2576*771ad4dfSGeoffrey D. Bennett {
2577*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2578*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2579*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2580*771ad4dfSGeoffrey D. Bennett 
2581*771ad4dfSGeoffrey D. Bennett 	int index = elem->control;
2582*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2583*771ad4dfSGeoffrey D. Bennett 
2584*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2585*771ad4dfSGeoffrey D. Bennett 
2586*771ad4dfSGeoffrey D. Bennett 	oval = private->phantom_switch[index];
2587*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.integer.value[0];
2588*771ad4dfSGeoffrey D. Bennett 
2589*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2590*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2591*771ad4dfSGeoffrey D. Bennett 
2592*771ad4dfSGeoffrey D. Bennett 	private->phantom_switch[index] = val;
2593*771ad4dfSGeoffrey D. Bennett 
2594*771ad4dfSGeoffrey D. Bennett 	/* Send switch change to the device */
2595*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PHANTOM_SWITCH,
2596*771ad4dfSGeoffrey D. Bennett 				       index, val);
2597*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2598*771ad4dfSGeoffrey D. Bennett 		err = 1;
2599*771ad4dfSGeoffrey D. Bennett 
2600*771ad4dfSGeoffrey D. Bennett unlock:
2601*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2602*771ad4dfSGeoffrey D. Bennett 	return err;
2603*771ad4dfSGeoffrey D. Bennett }
2604*771ad4dfSGeoffrey D. Bennett 
2605*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_phantom_ctl = {
2606*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2607*771ad4dfSGeoffrey D. Bennett 	.name = "",
2608*771ad4dfSGeoffrey D. Bennett 	.info = snd_ctl_boolean_mono_info,
2609*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_phantom_ctl_get,
2610*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_phantom_ctl_put,
2611*771ad4dfSGeoffrey D. Bennett };
2612*771ad4dfSGeoffrey D. Bennett 
2613*771ad4dfSGeoffrey D. Bennett /*** Phantom Persistence Control ***/
2614*771ad4dfSGeoffrey D. Bennett 
scarlett2_phantom_persistence_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2615*771ad4dfSGeoffrey D. Bennett static int scarlett2_phantom_persistence_ctl_get(
2616*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2617*771ad4dfSGeoffrey D. Bennett {
2618*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2619*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = elem->head.mixer->private_data;
2620*771ad4dfSGeoffrey D. Bennett 
2621*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->phantom_persistence;
2622*771ad4dfSGeoffrey D. Bennett 	return 0;
2623*771ad4dfSGeoffrey D. Bennett }
2624*771ad4dfSGeoffrey D. Bennett 
scarlett2_phantom_persistence_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2625*771ad4dfSGeoffrey D. Bennett static int scarlett2_phantom_persistence_ctl_put(
2626*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2627*771ad4dfSGeoffrey D. Bennett {
2628*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2629*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2630*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2631*771ad4dfSGeoffrey D. Bennett 
2632*771ad4dfSGeoffrey D. Bennett 	int index = elem->control;
2633*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2634*771ad4dfSGeoffrey D. Bennett 
2635*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2636*771ad4dfSGeoffrey D. Bennett 
2637*771ad4dfSGeoffrey D. Bennett 	oval = private->phantom_persistence;
2638*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.integer.value[0];
2639*771ad4dfSGeoffrey D. Bennett 
2640*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2641*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2642*771ad4dfSGeoffrey D. Bennett 
2643*771ad4dfSGeoffrey D. Bennett 	private->phantom_persistence = val;
2644*771ad4dfSGeoffrey D. Bennett 
2645*771ad4dfSGeoffrey D. Bennett 	/* Send switch change to the device */
2646*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(
2647*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE, index, val);
2648*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2649*771ad4dfSGeoffrey D. Bennett 		err = 1;
2650*771ad4dfSGeoffrey D. Bennett 
2651*771ad4dfSGeoffrey D. Bennett unlock:
2652*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2653*771ad4dfSGeoffrey D. Bennett 	return err;
2654*771ad4dfSGeoffrey D. Bennett }
2655*771ad4dfSGeoffrey D. Bennett 
2656*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_phantom_persistence_ctl = {
2657*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2658*771ad4dfSGeoffrey D. Bennett 	.name = "",
2659*771ad4dfSGeoffrey D. Bennett 	.info = snd_ctl_boolean_mono_info,
2660*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_phantom_persistence_ctl_get,
2661*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_phantom_persistence_ctl_put,
2662*771ad4dfSGeoffrey D. Bennett };
2663*771ad4dfSGeoffrey D. Bennett 
2664*771ad4dfSGeoffrey D. Bennett /*** Direct Monitor Control ***/
2665*771ad4dfSGeoffrey D. Bennett 
scarlett2_update_monitor_other(struct usb_mixer_interface * mixer)2666*771ad4dfSGeoffrey D. Bennett static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer)
2667*771ad4dfSGeoffrey D. Bennett {
2668*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2669*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
2670*771ad4dfSGeoffrey D. Bennett 	int err;
2671*771ad4dfSGeoffrey D. Bennett 
2672*771ad4dfSGeoffrey D. Bennett 	/* monitor_other_enable[0] enables speaker switching
2673*771ad4dfSGeoffrey D. Bennett 	 * monitor_other_enable[1] enables talkback
2674*771ad4dfSGeoffrey D. Bennett 	 */
2675*771ad4dfSGeoffrey D. Bennett 	u8 monitor_other_enable[2];
2676*771ad4dfSGeoffrey D. Bennett 
2677*771ad4dfSGeoffrey D. Bennett 	/* monitor_other_switch[0] activates the alternate speakers
2678*771ad4dfSGeoffrey D. Bennett 	 * monitor_other_switch[1] activates talkback
2679*771ad4dfSGeoffrey D. Bennett 	 */
2680*771ad4dfSGeoffrey D. Bennett 	u8 monitor_other_switch[2];
2681*771ad4dfSGeoffrey D. Bennett 
2682*771ad4dfSGeoffrey D. Bennett 	private->monitor_other_updated = 0;
2683*771ad4dfSGeoffrey D. Bennett 
2684*771ad4dfSGeoffrey D. Bennett 	if (info->direct_monitor)
2685*771ad4dfSGeoffrey D. Bennett 		return scarlett2_usb_get_config(
2686*771ad4dfSGeoffrey D. Bennett 			mixer, SCARLETT2_CONFIG_DIRECT_MONITOR,
2687*771ad4dfSGeoffrey D. Bennett 			1, &private->direct_monitor_switch);
2688*771ad4dfSGeoffrey D. Bennett 
2689*771ad4dfSGeoffrey D. Bennett 	/* if it doesn't do speaker switching then it also doesn't do
2690*771ad4dfSGeoffrey D. Bennett 	 * talkback
2691*771ad4dfSGeoffrey D. Bennett 	 */
2692*771ad4dfSGeoffrey D. Bennett 	if (!info->has_speaker_switching)
2693*771ad4dfSGeoffrey D. Bennett 		return 0;
2694*771ad4dfSGeoffrey D. Bennett 
2695*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_get_config(
2696*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE,
2697*771ad4dfSGeoffrey D. Bennett 		2, monitor_other_enable);
2698*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
2699*771ad4dfSGeoffrey D. Bennett 		return err;
2700*771ad4dfSGeoffrey D. Bennett 
2701*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_get_config(
2702*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH,
2703*771ad4dfSGeoffrey D. Bennett 		2, monitor_other_switch);
2704*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
2705*771ad4dfSGeoffrey D. Bennett 		return err;
2706*771ad4dfSGeoffrey D. Bennett 
2707*771ad4dfSGeoffrey D. Bennett 	if (!monitor_other_enable[0])
2708*771ad4dfSGeoffrey D. Bennett 		private->speaker_switching_switch = 0;
2709*771ad4dfSGeoffrey D. Bennett 	else
2710*771ad4dfSGeoffrey D. Bennett 		private->speaker_switching_switch = monitor_other_switch[0] + 1;
2711*771ad4dfSGeoffrey D. Bennett 
2712*771ad4dfSGeoffrey D. Bennett 	if (info->has_talkback) {
2713*771ad4dfSGeoffrey D. Bennett 		const int (*port_count)[SCARLETT2_PORT_DIRNS] =
2714*771ad4dfSGeoffrey D. Bennett 			info->port_count;
2715*771ad4dfSGeoffrey D. Bennett 		int num_mixes =
2716*771ad4dfSGeoffrey D. Bennett 			port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
2717*771ad4dfSGeoffrey D. Bennett 		u16 bitmap;
2718*771ad4dfSGeoffrey D. Bennett 		int i;
2719*771ad4dfSGeoffrey D. Bennett 
2720*771ad4dfSGeoffrey D. Bennett 		if (!monitor_other_enable[1])
2721*771ad4dfSGeoffrey D. Bennett 			private->talkback_switch = 0;
2722*771ad4dfSGeoffrey D. Bennett 		else
2723*771ad4dfSGeoffrey D. Bennett 			private->talkback_switch = monitor_other_switch[1] + 1;
2724*771ad4dfSGeoffrey D. Bennett 
2725*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_usb_get_config(mixer,
2726*771ad4dfSGeoffrey D. Bennett 					       SCARLETT2_CONFIG_TALKBACK_MAP,
2727*771ad4dfSGeoffrey D. Bennett 					       1, &bitmap);
2728*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2729*771ad4dfSGeoffrey D. Bennett 			return err;
2730*771ad4dfSGeoffrey D. Bennett 		for (i = 0; i < num_mixes; i++, bitmap >>= 1)
2731*771ad4dfSGeoffrey D. Bennett 			private->talkback_map[i] = bitmap & 1;
2732*771ad4dfSGeoffrey D. Bennett 	}
2733*771ad4dfSGeoffrey D. Bennett 
2734*771ad4dfSGeoffrey D. Bennett 	return 0;
2735*771ad4dfSGeoffrey D. Bennett }
2736*771ad4dfSGeoffrey D. Bennett 
scarlett2_direct_monitor_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2737*771ad4dfSGeoffrey D. Bennett static int scarlett2_direct_monitor_ctl_get(
2738*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2739*771ad4dfSGeoffrey D. Bennett {
2740*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2741*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2742*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = elem->head.mixer->private_data;
2743*771ad4dfSGeoffrey D. Bennett 	int err = 0;
2744*771ad4dfSGeoffrey D. Bennett 
2745*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2746*771ad4dfSGeoffrey D. Bennett 
2747*771ad4dfSGeoffrey D. Bennett 	if (private->monitor_other_updated) {
2748*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_monitor_other(mixer);
2749*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2750*771ad4dfSGeoffrey D. Bennett 			goto unlock;
2751*771ad4dfSGeoffrey D. Bennett 	}
2752*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.enumerated.item[0] = private->direct_monitor_switch;
2753*771ad4dfSGeoffrey D. Bennett 
2754*771ad4dfSGeoffrey D. Bennett unlock:
2755*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2756*771ad4dfSGeoffrey D. Bennett 	return err;
2757*771ad4dfSGeoffrey D. Bennett }
2758*771ad4dfSGeoffrey D. Bennett 
scarlett2_direct_monitor_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2759*771ad4dfSGeoffrey D. Bennett static int scarlett2_direct_monitor_ctl_put(
2760*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2761*771ad4dfSGeoffrey D. Bennett {
2762*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2763*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2764*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2765*771ad4dfSGeoffrey D. Bennett 
2766*771ad4dfSGeoffrey D. Bennett 	int index = elem->control;
2767*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2768*771ad4dfSGeoffrey D. Bennett 
2769*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2770*771ad4dfSGeoffrey D. Bennett 
2771*771ad4dfSGeoffrey D. Bennett 	oval = private->direct_monitor_switch;
2772*771ad4dfSGeoffrey D. Bennett 	val = min(ucontrol->value.enumerated.item[0], 2U);
2773*771ad4dfSGeoffrey D. Bennett 
2774*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2775*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2776*771ad4dfSGeoffrey D. Bennett 
2777*771ad4dfSGeoffrey D. Bennett 	private->direct_monitor_switch = val;
2778*771ad4dfSGeoffrey D. Bennett 
2779*771ad4dfSGeoffrey D. Bennett 	/* Send switch change to the device */
2780*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(
2781*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_DIRECT_MONITOR, index, val);
2782*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2783*771ad4dfSGeoffrey D. Bennett 		err = 1;
2784*771ad4dfSGeoffrey D. Bennett 
2785*771ad4dfSGeoffrey D. Bennett unlock:
2786*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2787*771ad4dfSGeoffrey D. Bennett 	return err;
2788*771ad4dfSGeoffrey D. Bennett }
2789*771ad4dfSGeoffrey D. Bennett 
scarlett2_direct_monitor_stereo_enum_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)2790*771ad4dfSGeoffrey D. Bennett static int scarlett2_direct_monitor_stereo_enum_ctl_info(
2791*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
2792*771ad4dfSGeoffrey D. Bennett {
2793*771ad4dfSGeoffrey D. Bennett 	static const char *const values[3] = {
2794*771ad4dfSGeoffrey D. Bennett 		"Off", "Mono", "Stereo"
2795*771ad4dfSGeoffrey D. Bennett 	};
2796*771ad4dfSGeoffrey D. Bennett 
2797*771ad4dfSGeoffrey D. Bennett 	return snd_ctl_enum_info(uinfo, 1, 3, values);
2798*771ad4dfSGeoffrey D. Bennett }
2799*771ad4dfSGeoffrey D. Bennett 
2800*771ad4dfSGeoffrey D. Bennett /* Direct Monitor for Solo is mono-only and only needs a boolean control
2801*771ad4dfSGeoffrey D. Bennett  * Direct Monitor for 2i2 is selectable between Off/Mono/Stereo
2802*771ad4dfSGeoffrey D. Bennett  */
2803*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_direct_monitor_ctl[2] = {
2804*771ad4dfSGeoffrey D. Bennett 	{
2805*771ad4dfSGeoffrey D. Bennett 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2806*771ad4dfSGeoffrey D. Bennett 		.name = "",
2807*771ad4dfSGeoffrey D. Bennett 		.info = snd_ctl_boolean_mono_info,
2808*771ad4dfSGeoffrey D. Bennett 		.get  = scarlett2_direct_monitor_ctl_get,
2809*771ad4dfSGeoffrey D. Bennett 		.put  = scarlett2_direct_monitor_ctl_put,
2810*771ad4dfSGeoffrey D. Bennett 	},
2811*771ad4dfSGeoffrey D. Bennett 	{
2812*771ad4dfSGeoffrey D. Bennett 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2813*771ad4dfSGeoffrey D. Bennett 		.name = "",
2814*771ad4dfSGeoffrey D. Bennett 		.info = scarlett2_direct_monitor_stereo_enum_ctl_info,
2815*771ad4dfSGeoffrey D. Bennett 		.get  = scarlett2_direct_monitor_ctl_get,
2816*771ad4dfSGeoffrey D. Bennett 		.put  = scarlett2_direct_monitor_ctl_put,
2817*771ad4dfSGeoffrey D. Bennett 	}
2818*771ad4dfSGeoffrey D. Bennett };
2819*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface * mixer)2820*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface *mixer)
2821*771ad4dfSGeoffrey D. Bennett {
2822*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2823*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
2824*771ad4dfSGeoffrey D. Bennett 	const char *s;
2825*771ad4dfSGeoffrey D. Bennett 
2826*771ad4dfSGeoffrey D. Bennett 	if (!info->direct_monitor)
2827*771ad4dfSGeoffrey D. Bennett 		return 0;
2828*771ad4dfSGeoffrey D. Bennett 
2829*771ad4dfSGeoffrey D. Bennett 	s = info->direct_monitor == 1
2830*771ad4dfSGeoffrey D. Bennett 	      ? "Direct Monitor Playback Switch"
2831*771ad4dfSGeoffrey D. Bennett 	      : "Direct Monitor Playback Enum";
2832*771ad4dfSGeoffrey D. Bennett 
2833*771ad4dfSGeoffrey D. Bennett 	return scarlett2_add_new_ctl(
2834*771ad4dfSGeoffrey D. Bennett 		mixer, &scarlett2_direct_monitor_ctl[info->direct_monitor - 1],
2835*771ad4dfSGeoffrey D. Bennett 		0, 1, s, &private->direct_monitor_ctl);
2836*771ad4dfSGeoffrey D. Bennett }
2837*771ad4dfSGeoffrey D. Bennett 
2838*771ad4dfSGeoffrey D. Bennett /*** Speaker Switching Control ***/
2839*771ad4dfSGeoffrey D. Bennett 
scarlett2_speaker_switch_enum_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)2840*771ad4dfSGeoffrey D. Bennett static int scarlett2_speaker_switch_enum_ctl_info(
2841*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
2842*771ad4dfSGeoffrey D. Bennett {
2843*771ad4dfSGeoffrey D. Bennett 	static const char *const values[3] = {
2844*771ad4dfSGeoffrey D. Bennett 		"Off", "Main", "Alt"
2845*771ad4dfSGeoffrey D. Bennett 	};
2846*771ad4dfSGeoffrey D. Bennett 
2847*771ad4dfSGeoffrey D. Bennett 	return snd_ctl_enum_info(uinfo, 1, 3, values);
2848*771ad4dfSGeoffrey D. Bennett }
2849*771ad4dfSGeoffrey D. Bennett 
scarlett2_speaker_switch_enum_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2850*771ad4dfSGeoffrey D. Bennett static int scarlett2_speaker_switch_enum_ctl_get(
2851*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2852*771ad4dfSGeoffrey D. Bennett {
2853*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2854*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2855*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2856*771ad4dfSGeoffrey D. Bennett 	int err = 0;
2857*771ad4dfSGeoffrey D. Bennett 
2858*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2859*771ad4dfSGeoffrey D. Bennett 
2860*771ad4dfSGeoffrey D. Bennett 	if (private->monitor_other_updated) {
2861*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_monitor_other(mixer);
2862*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
2863*771ad4dfSGeoffrey D. Bennett 			goto unlock;
2864*771ad4dfSGeoffrey D. Bennett 	}
2865*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.enumerated.item[0] = private->speaker_switching_switch;
2866*771ad4dfSGeoffrey D. Bennett 
2867*771ad4dfSGeoffrey D. Bennett unlock:
2868*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2869*771ad4dfSGeoffrey D. Bennett 	return err;
2870*771ad4dfSGeoffrey D. Bennett }
2871*771ad4dfSGeoffrey D. Bennett 
2872*771ad4dfSGeoffrey D. Bennett /* when speaker switching gets enabled, switch the main/alt speakers
2873*771ad4dfSGeoffrey D. Bennett  * to HW volume and disable those controls
2874*771ad4dfSGeoffrey D. Bennett  */
scarlett2_speaker_switch_enable(struct usb_mixer_interface * mixer)2875*771ad4dfSGeoffrey D. Bennett static int scarlett2_speaker_switch_enable(struct usb_mixer_interface *mixer)
2876*771ad4dfSGeoffrey D. Bennett {
2877*771ad4dfSGeoffrey D. Bennett 	struct snd_card *card = mixer->chip->card;
2878*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2879*771ad4dfSGeoffrey D. Bennett 	int i, err;
2880*771ad4dfSGeoffrey D. Bennett 
2881*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < 4; i++) {
2882*771ad4dfSGeoffrey D. Bennett 		int index = line_out_remap(private, i);
2883*771ad4dfSGeoffrey D. Bennett 
2884*771ad4dfSGeoffrey D. Bennett 		/* switch the main/alt speakers to HW volume */
2885*771ad4dfSGeoffrey D. Bennett 		if (!private->vol_sw_hw_switch[index]) {
2886*771ad4dfSGeoffrey D. Bennett 			err = scarlett2_sw_hw_change(private->mixer, i, 1);
2887*771ad4dfSGeoffrey D. Bennett 			if (err < 0)
2888*771ad4dfSGeoffrey D. Bennett 				return err;
2889*771ad4dfSGeoffrey D. Bennett 		}
2890*771ad4dfSGeoffrey D. Bennett 
2891*771ad4dfSGeoffrey D. Bennett 		/* disable the line out SW/HW switch */
2892*771ad4dfSGeoffrey D. Bennett 		scarlett2_sw_hw_ctl_ro(private, i);
2893*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card,
2894*771ad4dfSGeoffrey D. Bennett 			       SNDRV_CTL_EVENT_MASK_VALUE |
2895*771ad4dfSGeoffrey D. Bennett 				 SNDRV_CTL_EVENT_MASK_INFO,
2896*771ad4dfSGeoffrey D. Bennett 			       &private->sw_hw_ctls[i]->id);
2897*771ad4dfSGeoffrey D. Bennett 	}
2898*771ad4dfSGeoffrey D. Bennett 
2899*771ad4dfSGeoffrey D. Bennett 	/* when the next monitor-other notify comes in, update the mux
2900*771ad4dfSGeoffrey D. Bennett 	 * configuration
2901*771ad4dfSGeoffrey D. Bennett 	 */
2902*771ad4dfSGeoffrey D. Bennett 	private->speaker_switching_switched = 1;
2903*771ad4dfSGeoffrey D. Bennett 
2904*771ad4dfSGeoffrey D. Bennett 	return 0;
2905*771ad4dfSGeoffrey D. Bennett }
2906*771ad4dfSGeoffrey D. Bennett 
2907*771ad4dfSGeoffrey D. Bennett /* when speaker switching gets disabled, reenable the hw/sw controls
2908*771ad4dfSGeoffrey D. Bennett  * and invalidate the routing
2909*771ad4dfSGeoffrey D. Bennett  */
scarlett2_speaker_switch_disable(struct usb_mixer_interface * mixer)2910*771ad4dfSGeoffrey D. Bennett static void scarlett2_speaker_switch_disable(struct usb_mixer_interface *mixer)
2911*771ad4dfSGeoffrey D. Bennett {
2912*771ad4dfSGeoffrey D. Bennett 	struct snd_card *card = mixer->chip->card;
2913*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2914*771ad4dfSGeoffrey D. Bennett 	int i;
2915*771ad4dfSGeoffrey D. Bennett 
2916*771ad4dfSGeoffrey D. Bennett 	/* enable the line out SW/HW switch */
2917*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < 4; i++) {
2918*771ad4dfSGeoffrey D. Bennett 		scarlett2_sw_hw_ctl_rw(private, i);
2919*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
2920*771ad4dfSGeoffrey D. Bennett 			       &private->sw_hw_ctls[i]->id);
2921*771ad4dfSGeoffrey D. Bennett 	}
2922*771ad4dfSGeoffrey D. Bennett 
2923*771ad4dfSGeoffrey D. Bennett 	/* when the next monitor-other notify comes in, update the mux
2924*771ad4dfSGeoffrey D. Bennett 	 * configuration
2925*771ad4dfSGeoffrey D. Bennett 	 */
2926*771ad4dfSGeoffrey D. Bennett 	private->speaker_switching_switched = 1;
2927*771ad4dfSGeoffrey D. Bennett }
2928*771ad4dfSGeoffrey D. Bennett 
scarlett2_speaker_switch_enum_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)2929*771ad4dfSGeoffrey D. Bennett static int scarlett2_speaker_switch_enum_ctl_put(
2930*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2931*771ad4dfSGeoffrey D. Bennett {
2932*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
2933*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
2934*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2935*771ad4dfSGeoffrey D. Bennett 
2936*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
2937*771ad4dfSGeoffrey D. Bennett 
2938*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
2939*771ad4dfSGeoffrey D. Bennett 
2940*771ad4dfSGeoffrey D. Bennett 	oval = private->speaker_switching_switch;
2941*771ad4dfSGeoffrey D. Bennett 	val = min(ucontrol->value.enumerated.item[0], 2U);
2942*771ad4dfSGeoffrey D. Bennett 
2943*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
2944*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2945*771ad4dfSGeoffrey D. Bennett 
2946*771ad4dfSGeoffrey D. Bennett 	private->speaker_switching_switch = val;
2947*771ad4dfSGeoffrey D. Bennett 
2948*771ad4dfSGeoffrey D. Bennett 	/* enable/disable speaker switching */
2949*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(
2950*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE,
2951*771ad4dfSGeoffrey D. Bennett 		0, !!val);
2952*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
2953*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2954*771ad4dfSGeoffrey D. Bennett 
2955*771ad4dfSGeoffrey D. Bennett 	/* if speaker switching is enabled, select main or alt */
2956*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(
2957*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH,
2958*771ad4dfSGeoffrey D. Bennett 		0, val == 2);
2959*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
2960*771ad4dfSGeoffrey D. Bennett 		goto unlock;
2961*771ad4dfSGeoffrey D. Bennett 
2962*771ad4dfSGeoffrey D. Bennett 	/* update controls if speaker switching gets enabled or disabled */
2963*771ad4dfSGeoffrey D. Bennett 	if (!oval && val)
2964*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_speaker_switch_enable(mixer);
2965*771ad4dfSGeoffrey D. Bennett 	else if (oval && !val)
2966*771ad4dfSGeoffrey D. Bennett 		scarlett2_speaker_switch_disable(mixer);
2967*771ad4dfSGeoffrey D. Bennett 
2968*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
2969*771ad4dfSGeoffrey D. Bennett 		err = 1;
2970*771ad4dfSGeoffrey D. Bennett 
2971*771ad4dfSGeoffrey D. Bennett unlock:
2972*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
2973*771ad4dfSGeoffrey D. Bennett 	return err;
2974*771ad4dfSGeoffrey D. Bennett }
2975*771ad4dfSGeoffrey D. Bennett 
2976*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_speaker_switch_enum_ctl = {
2977*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2978*771ad4dfSGeoffrey D. Bennett 	.name = "",
2979*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_speaker_switch_enum_ctl_info,
2980*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_speaker_switch_enum_ctl_get,
2981*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_speaker_switch_enum_ctl_put,
2982*771ad4dfSGeoffrey D. Bennett };
2983*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_speaker_switch_ctl(struct usb_mixer_interface * mixer)2984*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_speaker_switch_ctl(
2985*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer)
2986*771ad4dfSGeoffrey D. Bennett {
2987*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
2988*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
2989*771ad4dfSGeoffrey D. Bennett 
2990*771ad4dfSGeoffrey D. Bennett 	if (!info->has_speaker_switching)
2991*771ad4dfSGeoffrey D. Bennett 		return 0;
2992*771ad4dfSGeoffrey D. Bennett 
2993*771ad4dfSGeoffrey D. Bennett 	return scarlett2_add_new_ctl(
2994*771ad4dfSGeoffrey D. Bennett 		mixer, &scarlett2_speaker_switch_enum_ctl,
2995*771ad4dfSGeoffrey D. Bennett 		0, 1, "Speaker Switching Playback Enum",
2996*771ad4dfSGeoffrey D. Bennett 		&private->speaker_switching_ctl);
2997*771ad4dfSGeoffrey D. Bennett }
2998*771ad4dfSGeoffrey D. Bennett 
2999*771ad4dfSGeoffrey D. Bennett /*** Talkback and Talkback Map Controls ***/
3000*771ad4dfSGeoffrey D. Bennett 
scarlett2_talkback_enum_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)3001*771ad4dfSGeoffrey D. Bennett static int scarlett2_talkback_enum_ctl_info(
3002*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
3003*771ad4dfSGeoffrey D. Bennett {
3004*771ad4dfSGeoffrey D. Bennett 	static const char *const values[3] = {
3005*771ad4dfSGeoffrey D. Bennett 		"Disabled", "Off", "On"
3006*771ad4dfSGeoffrey D. Bennett 	};
3007*771ad4dfSGeoffrey D. Bennett 
3008*771ad4dfSGeoffrey D. Bennett 	return snd_ctl_enum_info(uinfo, 1, 3, values);
3009*771ad4dfSGeoffrey D. Bennett }
3010*771ad4dfSGeoffrey D. Bennett 
scarlett2_talkback_enum_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3011*771ad4dfSGeoffrey D. Bennett static int scarlett2_talkback_enum_ctl_get(
3012*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
3013*771ad4dfSGeoffrey D. Bennett {
3014*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3015*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3016*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3017*771ad4dfSGeoffrey D. Bennett 	int err = 0;
3018*771ad4dfSGeoffrey D. Bennett 
3019*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3020*771ad4dfSGeoffrey D. Bennett 
3021*771ad4dfSGeoffrey D. Bennett 	if (private->monitor_other_updated) {
3022*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_monitor_other(mixer);
3023*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3024*771ad4dfSGeoffrey D. Bennett 			goto unlock;
3025*771ad4dfSGeoffrey D. Bennett 	}
3026*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.enumerated.item[0] = private->talkback_switch;
3027*771ad4dfSGeoffrey D. Bennett 
3028*771ad4dfSGeoffrey D. Bennett unlock:
3029*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3030*771ad4dfSGeoffrey D. Bennett 	return err;
3031*771ad4dfSGeoffrey D. Bennett }
3032*771ad4dfSGeoffrey D. Bennett 
scarlett2_talkback_enum_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3033*771ad4dfSGeoffrey D. Bennett static int scarlett2_talkback_enum_ctl_put(
3034*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
3035*771ad4dfSGeoffrey D. Bennett {
3036*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3037*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3038*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3039*771ad4dfSGeoffrey D. Bennett 
3040*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
3041*771ad4dfSGeoffrey D. Bennett 
3042*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3043*771ad4dfSGeoffrey D. Bennett 
3044*771ad4dfSGeoffrey D. Bennett 	oval = private->talkback_switch;
3045*771ad4dfSGeoffrey D. Bennett 	val = min(ucontrol->value.enumerated.item[0], 2U);
3046*771ad4dfSGeoffrey D. Bennett 
3047*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
3048*771ad4dfSGeoffrey D. Bennett 		goto unlock;
3049*771ad4dfSGeoffrey D. Bennett 
3050*771ad4dfSGeoffrey D. Bennett 	private->talkback_switch = val;
3051*771ad4dfSGeoffrey D. Bennett 
3052*771ad4dfSGeoffrey D. Bennett 	/* enable/disable talkback */
3053*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(
3054*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE,
3055*771ad4dfSGeoffrey D. Bennett 		1, !!val);
3056*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
3057*771ad4dfSGeoffrey D. Bennett 		goto unlock;
3058*771ad4dfSGeoffrey D. Bennett 
3059*771ad4dfSGeoffrey D. Bennett 	/* if talkback is enabled, select main or alt */
3060*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(
3061*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH,
3062*771ad4dfSGeoffrey D. Bennett 		1, val == 2);
3063*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
3064*771ad4dfSGeoffrey D. Bennett 		err = 1;
3065*771ad4dfSGeoffrey D. Bennett 
3066*771ad4dfSGeoffrey D. Bennett unlock:
3067*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3068*771ad4dfSGeoffrey D. Bennett 	return err;
3069*771ad4dfSGeoffrey D. Bennett }
3070*771ad4dfSGeoffrey D. Bennett 
3071*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_talkback_enum_ctl = {
3072*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3073*771ad4dfSGeoffrey D. Bennett 	.name = "",
3074*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_talkback_enum_ctl_info,
3075*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_talkback_enum_ctl_get,
3076*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_talkback_enum_ctl_put,
3077*771ad4dfSGeoffrey D. Bennett };
3078*771ad4dfSGeoffrey D. Bennett 
scarlett2_talkback_map_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3079*771ad4dfSGeoffrey D. Bennett static int scarlett2_talkback_map_ctl_get(
3080*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
3081*771ad4dfSGeoffrey D. Bennett {
3082*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3083*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3084*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3085*771ad4dfSGeoffrey D. Bennett 	int index = elem->control;
3086*771ad4dfSGeoffrey D. Bennett 
3087*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->talkback_map[index];
3088*771ad4dfSGeoffrey D. Bennett 
3089*771ad4dfSGeoffrey D. Bennett 	return 0;
3090*771ad4dfSGeoffrey D. Bennett }
3091*771ad4dfSGeoffrey D. Bennett 
scarlett2_talkback_map_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3092*771ad4dfSGeoffrey D. Bennett static int scarlett2_talkback_map_ctl_put(
3093*771ad4dfSGeoffrey D. Bennett 	struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
3094*771ad4dfSGeoffrey D. Bennett {
3095*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3096*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3097*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3098*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] =
3099*771ad4dfSGeoffrey D. Bennett 		private->info->port_count;
3100*771ad4dfSGeoffrey D. Bennett 	int num_mixes = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
3101*771ad4dfSGeoffrey D. Bennett 
3102*771ad4dfSGeoffrey D. Bennett 	int index = elem->control;
3103*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0, i;
3104*771ad4dfSGeoffrey D. Bennett 	u16 bitmap = 0;
3105*771ad4dfSGeoffrey D. Bennett 
3106*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3107*771ad4dfSGeoffrey D. Bennett 
3108*771ad4dfSGeoffrey D. Bennett 	oval = private->talkback_map[index];
3109*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.integer.value[0];
3110*771ad4dfSGeoffrey D. Bennett 
3111*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
3112*771ad4dfSGeoffrey D. Bennett 		goto unlock;
3113*771ad4dfSGeoffrey D. Bennett 
3114*771ad4dfSGeoffrey D. Bennett 	private->talkback_map[index] = val;
3115*771ad4dfSGeoffrey D. Bennett 
3116*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < num_mixes; i++)
3117*771ad4dfSGeoffrey D. Bennett 		bitmap |= private->talkback_map[i] << i;
3118*771ad4dfSGeoffrey D. Bennett 
3119*771ad4dfSGeoffrey D. Bennett 	/* Send updated bitmap to the device */
3120*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_TALKBACK_MAP,
3121*771ad4dfSGeoffrey D. Bennett 				       0, bitmap);
3122*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
3123*771ad4dfSGeoffrey D. Bennett 		err = 1;
3124*771ad4dfSGeoffrey D. Bennett 
3125*771ad4dfSGeoffrey D. Bennett unlock:
3126*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3127*771ad4dfSGeoffrey D. Bennett 	return err;
3128*771ad4dfSGeoffrey D. Bennett }
3129*771ad4dfSGeoffrey D. Bennett 
3130*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_talkback_map_ctl = {
3131*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3132*771ad4dfSGeoffrey D. Bennett 	.name = "",
3133*771ad4dfSGeoffrey D. Bennett 	.info = snd_ctl_boolean_mono_info,
3134*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_talkback_map_ctl_get,
3135*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_talkback_map_ctl_put,
3136*771ad4dfSGeoffrey D. Bennett };
3137*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_talkback_ctls(struct usb_mixer_interface * mixer)3138*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_talkback_ctls(
3139*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer)
3140*771ad4dfSGeoffrey D. Bennett {
3141*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3142*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3143*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3144*771ad4dfSGeoffrey D. Bennett 	int num_mixes = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
3145*771ad4dfSGeoffrey D. Bennett 	int err, i;
3146*771ad4dfSGeoffrey D. Bennett 	char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3147*771ad4dfSGeoffrey D. Bennett 
3148*771ad4dfSGeoffrey D. Bennett 	if (!info->has_talkback)
3149*771ad4dfSGeoffrey D. Bennett 		return 0;
3150*771ad4dfSGeoffrey D. Bennett 
3151*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_new_ctl(
3152*771ad4dfSGeoffrey D. Bennett 		mixer, &scarlett2_talkback_enum_ctl,
3153*771ad4dfSGeoffrey D. Bennett 		0, 1, "Talkback Playback Enum",
3154*771ad4dfSGeoffrey D. Bennett 		&private->talkback_ctl);
3155*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
3156*771ad4dfSGeoffrey D. Bennett 		return err;
3157*771ad4dfSGeoffrey D. Bennett 
3158*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < num_mixes; i++) {
3159*771ad4dfSGeoffrey D. Bennett 		snprintf(s, sizeof(s),
3160*771ad4dfSGeoffrey D. Bennett 			 "Talkback Mix %c Playback Switch", i + 'A');
3161*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_add_new_ctl(mixer, &scarlett2_talkback_map_ctl,
3162*771ad4dfSGeoffrey D. Bennett 					    i, 1, s, NULL);
3163*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3164*771ad4dfSGeoffrey D. Bennett 			return err;
3165*771ad4dfSGeoffrey D. Bennett 	}
3166*771ad4dfSGeoffrey D. Bennett 
3167*771ad4dfSGeoffrey D. Bennett 	return 0;
3168*771ad4dfSGeoffrey D. Bennett }
3169*771ad4dfSGeoffrey D. Bennett 
3170*771ad4dfSGeoffrey D. Bennett /*** Dim/Mute Controls ***/
3171*771ad4dfSGeoffrey D. Bennett 
scarlett2_dim_mute_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3172*771ad4dfSGeoffrey D. Bennett static int scarlett2_dim_mute_ctl_get(struct snd_kcontrol *kctl,
3173*771ad4dfSGeoffrey D. Bennett 				      struct snd_ctl_elem_value *ucontrol)
3174*771ad4dfSGeoffrey D. Bennett {
3175*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3176*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3177*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3178*771ad4dfSGeoffrey D. Bennett 	int err = 0;
3179*771ad4dfSGeoffrey D. Bennett 
3180*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3181*771ad4dfSGeoffrey D. Bennett 
3182*771ad4dfSGeoffrey D. Bennett 	if (private->vol_updated) {
3183*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_update_volumes(mixer);
3184*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3185*771ad4dfSGeoffrey D. Bennett 			goto unlock;
3186*771ad4dfSGeoffrey D. Bennett 	}
3187*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->dim_mute[elem->control];
3188*771ad4dfSGeoffrey D. Bennett 
3189*771ad4dfSGeoffrey D. Bennett unlock:
3190*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3191*771ad4dfSGeoffrey D. Bennett 	return err;
3192*771ad4dfSGeoffrey D. Bennett }
3193*771ad4dfSGeoffrey D. Bennett 
scarlett2_dim_mute_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3194*771ad4dfSGeoffrey D. Bennett static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl,
3195*771ad4dfSGeoffrey D. Bennett 				      struct snd_ctl_elem_value *ucontrol)
3196*771ad4dfSGeoffrey D. Bennett {
3197*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3198*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3199*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3200*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3201*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3202*771ad4dfSGeoffrey D. Bennett 	int num_line_out =
3203*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
3204*771ad4dfSGeoffrey D. Bennett 
3205*771ad4dfSGeoffrey D. Bennett 	int index = elem->control;
3206*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0, i;
3207*771ad4dfSGeoffrey D. Bennett 
3208*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3209*771ad4dfSGeoffrey D. Bennett 
3210*771ad4dfSGeoffrey D. Bennett 	oval = private->dim_mute[index];
3211*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.integer.value[0];
3212*771ad4dfSGeoffrey D. Bennett 
3213*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
3214*771ad4dfSGeoffrey D. Bennett 		goto unlock;
3215*771ad4dfSGeoffrey D. Bennett 
3216*771ad4dfSGeoffrey D. Bennett 	private->dim_mute[index] = val;
3217*771ad4dfSGeoffrey D. Bennett 
3218*771ad4dfSGeoffrey D. Bennett 	/* Send switch change to the device */
3219*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_DIM_MUTE,
3220*771ad4dfSGeoffrey D. Bennett 				       index, val);
3221*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
3222*771ad4dfSGeoffrey D. Bennett 		err = 1;
3223*771ad4dfSGeoffrey D. Bennett 
3224*771ad4dfSGeoffrey D. Bennett 	if (index == SCARLETT2_BUTTON_MUTE)
3225*771ad4dfSGeoffrey D. Bennett 		for (i = 0; i < num_line_out; i++) {
3226*771ad4dfSGeoffrey D. Bennett 			int line_index = line_out_remap(private, i);
3227*771ad4dfSGeoffrey D. Bennett 
3228*771ad4dfSGeoffrey D. Bennett 			if (private->vol_sw_hw_switch[line_index]) {
3229*771ad4dfSGeoffrey D. Bennett 				private->mute_switch[line_index] = val;
3230*771ad4dfSGeoffrey D. Bennett 				snd_ctl_notify(mixer->chip->card,
3231*771ad4dfSGeoffrey D. Bennett 					       SNDRV_CTL_EVENT_MASK_VALUE,
3232*771ad4dfSGeoffrey D. Bennett 					       &private->mute_ctls[i]->id);
3233*771ad4dfSGeoffrey D. Bennett 			}
3234*771ad4dfSGeoffrey D. Bennett 		}
3235*771ad4dfSGeoffrey D. Bennett 
3236*771ad4dfSGeoffrey D. Bennett unlock:
3237*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3238*771ad4dfSGeoffrey D. Bennett 	return err;
3239*771ad4dfSGeoffrey D. Bennett }
3240*771ad4dfSGeoffrey D. Bennett 
3241*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_dim_mute_ctl = {
3242*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3243*771ad4dfSGeoffrey D. Bennett 	.name = "",
3244*771ad4dfSGeoffrey D. Bennett 	.info = snd_ctl_boolean_mono_info,
3245*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_dim_mute_ctl_get,
3246*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_dim_mute_ctl_put
3247*771ad4dfSGeoffrey D. Bennett };
3248*771ad4dfSGeoffrey D. Bennett 
3249*771ad4dfSGeoffrey D. Bennett /*** Create the analogue output controls ***/
3250*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_line_out_ctls(struct usb_mixer_interface * mixer)3251*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer)
3252*771ad4dfSGeoffrey D. Bennett {
3253*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3254*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3255*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3256*771ad4dfSGeoffrey D. Bennett 	int num_line_out =
3257*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
3258*771ad4dfSGeoffrey D. Bennett 	int err, i;
3259*771ad4dfSGeoffrey D. Bennett 	char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3260*771ad4dfSGeoffrey D. Bennett 
3261*771ad4dfSGeoffrey D. Bennett 	/* Add R/O HW volume control */
3262*771ad4dfSGeoffrey D. Bennett 	if (info->line_out_hw_vol) {
3263*771ad4dfSGeoffrey D. Bennett 		snprintf(s, sizeof(s), "Master HW Playback Volume");
3264*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_add_new_ctl(mixer,
3265*771ad4dfSGeoffrey D. Bennett 					    &scarlett2_master_volume_ctl,
3266*771ad4dfSGeoffrey D. Bennett 					    0, 1, s, &private->master_vol_ctl);
3267*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3268*771ad4dfSGeoffrey D. Bennett 			return err;
3269*771ad4dfSGeoffrey D. Bennett 	}
3270*771ad4dfSGeoffrey D. Bennett 
3271*771ad4dfSGeoffrey D. Bennett 	/* Add volume controls */
3272*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < num_line_out; i++) {
3273*771ad4dfSGeoffrey D. Bennett 		int index = line_out_remap(private, i);
3274*771ad4dfSGeoffrey D. Bennett 
3275*771ad4dfSGeoffrey D. Bennett 		/* Fader */
3276*771ad4dfSGeoffrey D. Bennett 		if (info->line_out_descrs[i])
3277*771ad4dfSGeoffrey D. Bennett 			snprintf(s, sizeof(s),
3278*771ad4dfSGeoffrey D. Bennett 				 "Line %02d (%s) Playback Volume",
3279*771ad4dfSGeoffrey D. Bennett 				 i + 1, info->line_out_descrs[i]);
3280*771ad4dfSGeoffrey D. Bennett 		else
3281*771ad4dfSGeoffrey D. Bennett 			snprintf(s, sizeof(s),
3282*771ad4dfSGeoffrey D. Bennett 				 "Line %02d Playback Volume",
3283*771ad4dfSGeoffrey D. Bennett 				 i + 1);
3284*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_add_new_ctl(mixer,
3285*771ad4dfSGeoffrey D. Bennett 					    &scarlett2_line_out_volume_ctl,
3286*771ad4dfSGeoffrey D. Bennett 					    i, 1, s, &private->vol_ctls[i]);
3287*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3288*771ad4dfSGeoffrey D. Bennett 			return err;
3289*771ad4dfSGeoffrey D. Bennett 
3290*771ad4dfSGeoffrey D. Bennett 		/* Mute Switch */
3291*771ad4dfSGeoffrey D. Bennett 		snprintf(s, sizeof(s),
3292*771ad4dfSGeoffrey D. Bennett 			 "Line %02d Mute Playback Switch",
3293*771ad4dfSGeoffrey D. Bennett 			 i + 1);
3294*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_add_new_ctl(mixer,
3295*771ad4dfSGeoffrey D. Bennett 					    &scarlett2_mute_ctl,
3296*771ad4dfSGeoffrey D. Bennett 					    i, 1, s,
3297*771ad4dfSGeoffrey D. Bennett 					    &private->mute_ctls[i]);
3298*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3299*771ad4dfSGeoffrey D. Bennett 			return err;
3300*771ad4dfSGeoffrey D. Bennett 
3301*771ad4dfSGeoffrey D. Bennett 		/* Make the fader and mute controls read-only if the
3302*771ad4dfSGeoffrey D. Bennett 		 * SW/HW switch is set to HW
3303*771ad4dfSGeoffrey D. Bennett 		 */
3304*771ad4dfSGeoffrey D. Bennett 		if (private->vol_sw_hw_switch[index])
3305*771ad4dfSGeoffrey D. Bennett 			scarlett2_vol_ctl_set_writable(mixer, i, 0);
3306*771ad4dfSGeoffrey D. Bennett 
3307*771ad4dfSGeoffrey D. Bennett 		/* SW/HW Switch */
3308*771ad4dfSGeoffrey D. Bennett 		if (info->line_out_hw_vol) {
3309*771ad4dfSGeoffrey D. Bennett 			snprintf(s, sizeof(s),
3310*771ad4dfSGeoffrey D. Bennett 				 "Line Out %02d Volume Control Playback Enum",
3311*771ad4dfSGeoffrey D. Bennett 				 i + 1);
3312*771ad4dfSGeoffrey D. Bennett 			err = scarlett2_add_new_ctl(mixer,
3313*771ad4dfSGeoffrey D. Bennett 						    &scarlett2_sw_hw_enum_ctl,
3314*771ad4dfSGeoffrey D. Bennett 						    i, 1, s,
3315*771ad4dfSGeoffrey D. Bennett 						    &private->sw_hw_ctls[i]);
3316*771ad4dfSGeoffrey D. Bennett 			if (err < 0)
3317*771ad4dfSGeoffrey D. Bennett 				return err;
3318*771ad4dfSGeoffrey D. Bennett 
3319*771ad4dfSGeoffrey D. Bennett 			/* Make the switch read-only if the line is
3320*771ad4dfSGeoffrey D. Bennett 			 * involved in speaker switching
3321*771ad4dfSGeoffrey D. Bennett 			 */
3322*771ad4dfSGeoffrey D. Bennett 			if (private->speaker_switching_switch && i < 4)
3323*771ad4dfSGeoffrey D. Bennett 				scarlett2_sw_hw_ctl_ro(private, i);
3324*771ad4dfSGeoffrey D. Bennett 		}
3325*771ad4dfSGeoffrey D. Bennett 	}
3326*771ad4dfSGeoffrey D. Bennett 
3327*771ad4dfSGeoffrey D. Bennett 	/* Add dim/mute controls */
3328*771ad4dfSGeoffrey D. Bennett 	if (info->line_out_hw_vol)
3329*771ad4dfSGeoffrey D. Bennett 		for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) {
3330*771ad4dfSGeoffrey D. Bennett 			err = scarlett2_add_new_ctl(
3331*771ad4dfSGeoffrey D. Bennett 				mixer, &scarlett2_dim_mute_ctl,
3332*771ad4dfSGeoffrey D. Bennett 				i, 1, scarlett2_dim_mute_names[i],
3333*771ad4dfSGeoffrey D. Bennett 				&private->dim_mute_ctls[i]);
3334*771ad4dfSGeoffrey D. Bennett 			if (err < 0)
3335*771ad4dfSGeoffrey D. Bennett 				return err;
3336*771ad4dfSGeoffrey D. Bennett 		}
3337*771ad4dfSGeoffrey D. Bennett 
3338*771ad4dfSGeoffrey D. Bennett 	return 0;
3339*771ad4dfSGeoffrey D. Bennett }
3340*771ad4dfSGeoffrey D. Bennett 
3341*771ad4dfSGeoffrey D. Bennett /*** Create the analogue input controls ***/
3342*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_line_in_ctls(struct usb_mixer_interface * mixer)3343*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer)
3344*771ad4dfSGeoffrey D. Bennett {
3345*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3346*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3347*771ad4dfSGeoffrey D. Bennett 	int err, i;
3348*771ad4dfSGeoffrey D. Bennett 	char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3349*771ad4dfSGeoffrey D. Bennett 	const char *fmt = "Line In %d %s Capture %s";
3350*771ad4dfSGeoffrey D. Bennett 	const char *fmt2 = "Line In %d-%d %s Capture %s";
3351*771ad4dfSGeoffrey D. Bennett 
3352*771ad4dfSGeoffrey D. Bennett 	/* Add input level (line/inst) controls */
3353*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < info->level_input_count; i++) {
3354*771ad4dfSGeoffrey D. Bennett 		snprintf(s, sizeof(s), fmt, i + 1 + info->level_input_first,
3355*771ad4dfSGeoffrey D. Bennett 			 "Level", "Enum");
3356*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_add_new_ctl(mixer, &scarlett2_level_enum_ctl,
3357*771ad4dfSGeoffrey D. Bennett 					    i, 1, s, &private->level_ctls[i]);
3358*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3359*771ad4dfSGeoffrey D. Bennett 			return err;
3360*771ad4dfSGeoffrey D. Bennett 	}
3361*771ad4dfSGeoffrey D. Bennett 
3362*771ad4dfSGeoffrey D. Bennett 	/* Add input pad controls */
3363*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < info->pad_input_count; i++) {
3364*771ad4dfSGeoffrey D. Bennett 		snprintf(s, sizeof(s), fmt, i + 1, "Pad", "Switch");
3365*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_add_new_ctl(mixer, &scarlett2_pad_ctl,
3366*771ad4dfSGeoffrey D. Bennett 					    i, 1, s, &private->pad_ctls[i]);
3367*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3368*771ad4dfSGeoffrey D. Bennett 			return err;
3369*771ad4dfSGeoffrey D. Bennett 	}
3370*771ad4dfSGeoffrey D. Bennett 
3371*771ad4dfSGeoffrey D. Bennett 	/* Add input air controls */
3372*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < info->air_input_count; i++) {
3373*771ad4dfSGeoffrey D. Bennett 		snprintf(s, sizeof(s), fmt, i + 1, "Air", "Switch");
3374*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_add_new_ctl(mixer, &scarlett2_air_ctl,
3375*771ad4dfSGeoffrey D. Bennett 					    i, 1, s, &private->air_ctls[i]);
3376*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3377*771ad4dfSGeoffrey D. Bennett 			return err;
3378*771ad4dfSGeoffrey D. Bennett 	}
3379*771ad4dfSGeoffrey D. Bennett 
3380*771ad4dfSGeoffrey D. Bennett 	/* Add input phantom controls */
3381*771ad4dfSGeoffrey D. Bennett 	if (info->inputs_per_phantom == 1) {
3382*771ad4dfSGeoffrey D. Bennett 		for (i = 0; i < info->phantom_count; i++) {
3383*771ad4dfSGeoffrey D. Bennett 			scnprintf(s, sizeof(s), fmt, i + 1,
3384*771ad4dfSGeoffrey D. Bennett 				  "Phantom Power", "Switch");
3385*771ad4dfSGeoffrey D. Bennett 			err = scarlett2_add_new_ctl(
3386*771ad4dfSGeoffrey D. Bennett 				mixer, &scarlett2_phantom_ctl,
3387*771ad4dfSGeoffrey D. Bennett 				i, 1, s, &private->phantom_ctls[i]);
3388*771ad4dfSGeoffrey D. Bennett 			if (err < 0)
3389*771ad4dfSGeoffrey D. Bennett 				return err;
3390*771ad4dfSGeoffrey D. Bennett 		}
3391*771ad4dfSGeoffrey D. Bennett 	} else if (info->inputs_per_phantom > 1) {
3392*771ad4dfSGeoffrey D. Bennett 		for (i = 0; i < info->phantom_count; i++) {
3393*771ad4dfSGeoffrey D. Bennett 			int from = i * info->inputs_per_phantom + 1;
3394*771ad4dfSGeoffrey D. Bennett 			int to = (i + 1) * info->inputs_per_phantom;
3395*771ad4dfSGeoffrey D. Bennett 
3396*771ad4dfSGeoffrey D. Bennett 			scnprintf(s, sizeof(s), fmt2, from, to,
3397*771ad4dfSGeoffrey D. Bennett 				  "Phantom Power", "Switch");
3398*771ad4dfSGeoffrey D. Bennett 			err = scarlett2_add_new_ctl(
3399*771ad4dfSGeoffrey D. Bennett 				mixer, &scarlett2_phantom_ctl,
3400*771ad4dfSGeoffrey D. Bennett 				i, 1, s, &private->phantom_ctls[i]);
3401*771ad4dfSGeoffrey D. Bennett 			if (err < 0)
3402*771ad4dfSGeoffrey D. Bennett 				return err;
3403*771ad4dfSGeoffrey D. Bennett 		}
3404*771ad4dfSGeoffrey D. Bennett 	}
3405*771ad4dfSGeoffrey D. Bennett 	if (info->phantom_count) {
3406*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_add_new_ctl(
3407*771ad4dfSGeoffrey D. Bennett 			mixer, &scarlett2_phantom_persistence_ctl, 0, 1,
3408*771ad4dfSGeoffrey D. Bennett 			"Phantom Power Persistence Capture Switch", NULL);
3409*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3410*771ad4dfSGeoffrey D. Bennett 			return err;
3411*771ad4dfSGeoffrey D. Bennett 	}
3412*771ad4dfSGeoffrey D. Bennett 
3413*771ad4dfSGeoffrey D. Bennett 	return 0;
3414*771ad4dfSGeoffrey D. Bennett }
3415*771ad4dfSGeoffrey D. Bennett 
3416*771ad4dfSGeoffrey D. Bennett /*** Mixer Volume Controls ***/
3417*771ad4dfSGeoffrey D. Bennett 
scarlett2_mixer_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)3418*771ad4dfSGeoffrey D. Bennett static int scarlett2_mixer_ctl_info(struct snd_kcontrol *kctl,
3419*771ad4dfSGeoffrey D. Bennett 				    struct snd_ctl_elem_info *uinfo)
3420*771ad4dfSGeoffrey D. Bennett {
3421*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3422*771ad4dfSGeoffrey D. Bennett 
3423*771ad4dfSGeoffrey D. Bennett 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3424*771ad4dfSGeoffrey D. Bennett 	uinfo->count = elem->channels;
3425*771ad4dfSGeoffrey D. Bennett 	uinfo->value.integer.min = 0;
3426*771ad4dfSGeoffrey D. Bennett 	uinfo->value.integer.max = SCARLETT2_MIXER_MAX_VALUE;
3427*771ad4dfSGeoffrey D. Bennett 	uinfo->value.integer.step = 1;
3428*771ad4dfSGeoffrey D. Bennett 	return 0;
3429*771ad4dfSGeoffrey D. Bennett }
3430*771ad4dfSGeoffrey D. Bennett 
scarlett2_mixer_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3431*771ad4dfSGeoffrey D. Bennett static int scarlett2_mixer_ctl_get(struct snd_kcontrol *kctl,
3432*771ad4dfSGeoffrey D. Bennett 				   struct snd_ctl_elem_value *ucontrol)
3433*771ad4dfSGeoffrey D. Bennett {
3434*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3435*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = elem->head.mixer->private_data;
3436*771ad4dfSGeoffrey D. Bennett 
3437*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->mix[elem->control];
3438*771ad4dfSGeoffrey D. Bennett 	return 0;
3439*771ad4dfSGeoffrey D. Bennett }
3440*771ad4dfSGeoffrey D. Bennett 
scarlett2_mixer_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3441*771ad4dfSGeoffrey D. Bennett static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl,
3442*771ad4dfSGeoffrey D. Bennett 				   struct snd_ctl_elem_value *ucontrol)
3443*771ad4dfSGeoffrey D. Bennett {
3444*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3445*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3446*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3447*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3448*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3449*771ad4dfSGeoffrey D. Bennett 	int oval, val, num_mixer_in, mix_num, err = 0;
3450*771ad4dfSGeoffrey D. Bennett 	int index = elem->control;
3451*771ad4dfSGeoffrey D. Bennett 
3452*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3453*771ad4dfSGeoffrey D. Bennett 
3454*771ad4dfSGeoffrey D. Bennett 	oval = private->mix[index];
3455*771ad4dfSGeoffrey D. Bennett 	val = clamp(ucontrol->value.integer.value[0],
3456*771ad4dfSGeoffrey D. Bennett 		    0L, (long)SCARLETT2_MIXER_MAX_VALUE);
3457*771ad4dfSGeoffrey D. Bennett 	num_mixer_in = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT];
3458*771ad4dfSGeoffrey D. Bennett 	mix_num = index / num_mixer_in;
3459*771ad4dfSGeoffrey D. Bennett 
3460*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
3461*771ad4dfSGeoffrey D. Bennett 		goto unlock;
3462*771ad4dfSGeoffrey D. Bennett 
3463*771ad4dfSGeoffrey D. Bennett 	private->mix[index] = val;
3464*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_mix(mixer, mix_num);
3465*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
3466*771ad4dfSGeoffrey D. Bennett 		err = 1;
3467*771ad4dfSGeoffrey D. Bennett 
3468*771ad4dfSGeoffrey D. Bennett unlock:
3469*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3470*771ad4dfSGeoffrey D. Bennett 	return err;
3471*771ad4dfSGeoffrey D. Bennett }
3472*771ad4dfSGeoffrey D. Bennett 
3473*771ad4dfSGeoffrey D. Bennett static const DECLARE_TLV_DB_MINMAX(
3474*771ad4dfSGeoffrey D. Bennett 	db_scale_scarlett2_mixer,
3475*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_MIXER_MIN_DB * 100,
3476*771ad4dfSGeoffrey D. Bennett 	SCARLETT2_MIXER_MAX_DB * 100
3477*771ad4dfSGeoffrey D. Bennett );
3478*771ad4dfSGeoffrey D. Bennett 
3479*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_mixer_ctl = {
3480*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3481*771ad4dfSGeoffrey D. Bennett 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
3482*771ad4dfSGeoffrey D. Bennett 		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
3483*771ad4dfSGeoffrey D. Bennett 	.name = "",
3484*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_mixer_ctl_info,
3485*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_mixer_ctl_get,
3486*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_mixer_ctl_put,
3487*771ad4dfSGeoffrey D. Bennett 	.private_value = SCARLETT2_MIXER_MAX_DB, /* max value */
3488*771ad4dfSGeoffrey D. Bennett 	.tlv = { .p = db_scale_scarlett2_mixer }
3489*771ad4dfSGeoffrey D. Bennett };
3490*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_mixer_ctls(struct usb_mixer_interface * mixer)3491*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_mixer_ctls(struct usb_mixer_interface *mixer)
3492*771ad4dfSGeoffrey D. Bennett {
3493*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3494*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3495*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3496*771ad4dfSGeoffrey D. Bennett 	int err, i, j;
3497*771ad4dfSGeoffrey D. Bennett 	int index;
3498*771ad4dfSGeoffrey D. Bennett 	char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3499*771ad4dfSGeoffrey D. Bennett 
3500*771ad4dfSGeoffrey D. Bennett 	int num_inputs =
3501*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT];
3502*771ad4dfSGeoffrey D. Bennett 	int num_outputs =
3503*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
3504*771ad4dfSGeoffrey D. Bennett 
3505*771ad4dfSGeoffrey D. Bennett 	for (i = 0, index = 0; i < num_outputs; i++)
3506*771ad4dfSGeoffrey D. Bennett 		for (j = 0; j < num_inputs; j++, index++) {
3507*771ad4dfSGeoffrey D. Bennett 			snprintf(s, sizeof(s),
3508*771ad4dfSGeoffrey D. Bennett 				 "Mix %c Input %02d Playback Volume",
3509*771ad4dfSGeoffrey D. Bennett 				 'A' + i, j + 1);
3510*771ad4dfSGeoffrey D. Bennett 			err = scarlett2_add_new_ctl(mixer, &scarlett2_mixer_ctl,
3511*771ad4dfSGeoffrey D. Bennett 						    index, 1, s, NULL);
3512*771ad4dfSGeoffrey D. Bennett 			if (err < 0)
3513*771ad4dfSGeoffrey D. Bennett 				return err;
3514*771ad4dfSGeoffrey D. Bennett 		}
3515*771ad4dfSGeoffrey D. Bennett 
3516*771ad4dfSGeoffrey D. Bennett 	return 0;
3517*771ad4dfSGeoffrey D. Bennett }
3518*771ad4dfSGeoffrey D. Bennett 
3519*771ad4dfSGeoffrey D. Bennett /*** Mux Source Selection Controls ***/
3520*771ad4dfSGeoffrey D. Bennett 
scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)3521*771ad4dfSGeoffrey D. Bennett static int scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol *kctl,
3522*771ad4dfSGeoffrey D. Bennett 					   struct snd_ctl_elem_info *uinfo)
3523*771ad4dfSGeoffrey D. Bennett {
3524*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3525*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = elem->head.mixer->private_data;
3526*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3527*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3528*771ad4dfSGeoffrey D. Bennett 	unsigned int item = uinfo->value.enumerated.item;
3529*771ad4dfSGeoffrey D. Bennett 	int items = private->num_mux_srcs;
3530*771ad4dfSGeoffrey D. Bennett 	int port_type;
3531*771ad4dfSGeoffrey D. Bennett 
3532*771ad4dfSGeoffrey D. Bennett 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3533*771ad4dfSGeoffrey D. Bennett 	uinfo->count = elem->channels;
3534*771ad4dfSGeoffrey D. Bennett 	uinfo->value.enumerated.items = items;
3535*771ad4dfSGeoffrey D. Bennett 
3536*771ad4dfSGeoffrey D. Bennett 	if (item >= items)
3537*771ad4dfSGeoffrey D. Bennett 		item = uinfo->value.enumerated.item = items - 1;
3538*771ad4dfSGeoffrey D. Bennett 
3539*771ad4dfSGeoffrey D. Bennett 	for (port_type = 0;
3540*771ad4dfSGeoffrey D. Bennett 	     port_type < SCARLETT2_PORT_TYPE_COUNT;
3541*771ad4dfSGeoffrey D. Bennett 	     port_type++) {
3542*771ad4dfSGeoffrey D. Bennett 		if (item < port_count[port_type][SCARLETT2_PORT_IN]) {
3543*771ad4dfSGeoffrey D. Bennett 			const struct scarlett2_port *port =
3544*771ad4dfSGeoffrey D. Bennett 				&scarlett2_ports[port_type];
3545*771ad4dfSGeoffrey D. Bennett 
3546*771ad4dfSGeoffrey D. Bennett 			sprintf(uinfo->value.enumerated.name,
3547*771ad4dfSGeoffrey D. Bennett 				port->src_descr, item + port->src_num_offset);
3548*771ad4dfSGeoffrey D. Bennett 			return 0;
3549*771ad4dfSGeoffrey D. Bennett 		}
3550*771ad4dfSGeoffrey D. Bennett 		item -= port_count[port_type][SCARLETT2_PORT_IN];
3551*771ad4dfSGeoffrey D. Bennett 	}
3552*771ad4dfSGeoffrey D. Bennett 
3553*771ad4dfSGeoffrey D. Bennett 	return -EINVAL;
3554*771ad4dfSGeoffrey D. Bennett }
3555*771ad4dfSGeoffrey D. Bennett 
scarlett2_mux_src_enum_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3556*771ad4dfSGeoffrey D. Bennett static int scarlett2_mux_src_enum_ctl_get(struct snd_kcontrol *kctl,
3557*771ad4dfSGeoffrey D. Bennett 					  struct snd_ctl_elem_value *ucontrol)
3558*771ad4dfSGeoffrey D. Bennett {
3559*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3560*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3561*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3562*771ad4dfSGeoffrey D. Bennett 	int index = line_out_remap(private, elem->control);
3563*771ad4dfSGeoffrey D. Bennett 	int err = 0;
3564*771ad4dfSGeoffrey D. Bennett 
3565*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3566*771ad4dfSGeoffrey D. Bennett 
3567*771ad4dfSGeoffrey D. Bennett 	if (private->mux_updated) {
3568*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_usb_get_mux(mixer);
3569*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3570*771ad4dfSGeoffrey D. Bennett 			goto unlock;
3571*771ad4dfSGeoffrey D. Bennett 	}
3572*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.enumerated.item[0] = private->mux[index];
3573*771ad4dfSGeoffrey D. Bennett 
3574*771ad4dfSGeoffrey D. Bennett unlock:
3575*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3576*771ad4dfSGeoffrey D. Bennett 	return err;
3577*771ad4dfSGeoffrey D. Bennett }
3578*771ad4dfSGeoffrey D. Bennett 
scarlett2_mux_src_enum_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3579*771ad4dfSGeoffrey D. Bennett static int scarlett2_mux_src_enum_ctl_put(struct snd_kcontrol *kctl,
3580*771ad4dfSGeoffrey D. Bennett 					  struct snd_ctl_elem_value *ucontrol)
3581*771ad4dfSGeoffrey D. Bennett {
3582*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3583*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3584*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3585*771ad4dfSGeoffrey D. Bennett 	int index = line_out_remap(private, elem->control);
3586*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
3587*771ad4dfSGeoffrey D. Bennett 
3588*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3589*771ad4dfSGeoffrey D. Bennett 
3590*771ad4dfSGeoffrey D. Bennett 	oval = private->mux[index];
3591*771ad4dfSGeoffrey D. Bennett 	val = min(ucontrol->value.enumerated.item[0],
3592*771ad4dfSGeoffrey D. Bennett 		  private->num_mux_srcs - 1U);
3593*771ad4dfSGeoffrey D. Bennett 
3594*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
3595*771ad4dfSGeoffrey D. Bennett 		goto unlock;
3596*771ad4dfSGeoffrey D. Bennett 
3597*771ad4dfSGeoffrey D. Bennett 	private->mux[index] = val;
3598*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_mux(mixer);
3599*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
3600*771ad4dfSGeoffrey D. Bennett 		err = 1;
3601*771ad4dfSGeoffrey D. Bennett 
3602*771ad4dfSGeoffrey D. Bennett unlock:
3603*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3604*771ad4dfSGeoffrey D. Bennett 	return err;
3605*771ad4dfSGeoffrey D. Bennett }
3606*771ad4dfSGeoffrey D. Bennett 
3607*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_mux_src_enum_ctl = {
3608*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3609*771ad4dfSGeoffrey D. Bennett 	.name = "",
3610*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_mux_src_enum_ctl_info,
3611*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_mux_src_enum_ctl_get,
3612*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_mux_src_enum_ctl_put,
3613*771ad4dfSGeoffrey D. Bennett };
3614*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_mux_enums(struct usb_mixer_interface * mixer)3615*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_mux_enums(struct usb_mixer_interface *mixer)
3616*771ad4dfSGeoffrey D. Bennett {
3617*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3618*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3619*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3620*771ad4dfSGeoffrey D. Bennett 	int port_type, channel, i;
3621*771ad4dfSGeoffrey D. Bennett 
3622*771ad4dfSGeoffrey D. Bennett 	for (i = 0, port_type = 0;
3623*771ad4dfSGeoffrey D. Bennett 	     port_type < SCARLETT2_PORT_TYPE_COUNT;
3624*771ad4dfSGeoffrey D. Bennett 	     port_type++) {
3625*771ad4dfSGeoffrey D. Bennett 		for (channel = 0;
3626*771ad4dfSGeoffrey D. Bennett 		     channel < port_count[port_type][SCARLETT2_PORT_OUT];
3627*771ad4dfSGeoffrey D. Bennett 		     channel++, i++) {
3628*771ad4dfSGeoffrey D. Bennett 			int err;
3629*771ad4dfSGeoffrey D. Bennett 			char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3630*771ad4dfSGeoffrey D. Bennett 			const char *const descr =
3631*771ad4dfSGeoffrey D. Bennett 				scarlett2_ports[port_type].dst_descr;
3632*771ad4dfSGeoffrey D. Bennett 
3633*771ad4dfSGeoffrey D. Bennett 			snprintf(s, sizeof(s) - 5, descr, channel + 1);
3634*771ad4dfSGeoffrey D. Bennett 			strcat(s, " Enum");
3635*771ad4dfSGeoffrey D. Bennett 
3636*771ad4dfSGeoffrey D. Bennett 			err = scarlett2_add_new_ctl(mixer,
3637*771ad4dfSGeoffrey D. Bennett 						    &scarlett2_mux_src_enum_ctl,
3638*771ad4dfSGeoffrey D. Bennett 						    i, 1, s,
3639*771ad4dfSGeoffrey D. Bennett 						    &private->mux_ctls[i]);
3640*771ad4dfSGeoffrey D. Bennett 			if (err < 0)
3641*771ad4dfSGeoffrey D. Bennett 				return err;
3642*771ad4dfSGeoffrey D. Bennett 		}
3643*771ad4dfSGeoffrey D. Bennett 	}
3644*771ad4dfSGeoffrey D. Bennett 
3645*771ad4dfSGeoffrey D. Bennett 	return 0;
3646*771ad4dfSGeoffrey D. Bennett }
3647*771ad4dfSGeoffrey D. Bennett 
3648*771ad4dfSGeoffrey D. Bennett /*** Meter Controls ***/
3649*771ad4dfSGeoffrey D. Bennett 
scarlett2_meter_ctl_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)3650*771ad4dfSGeoffrey D. Bennett static int scarlett2_meter_ctl_info(struct snd_kcontrol *kctl,
3651*771ad4dfSGeoffrey D. Bennett 				    struct snd_ctl_elem_info *uinfo)
3652*771ad4dfSGeoffrey D. Bennett {
3653*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3654*771ad4dfSGeoffrey D. Bennett 
3655*771ad4dfSGeoffrey D. Bennett 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3656*771ad4dfSGeoffrey D. Bennett 	uinfo->count = elem->channels;
3657*771ad4dfSGeoffrey D. Bennett 	uinfo->value.integer.min = 0;
3658*771ad4dfSGeoffrey D. Bennett 	uinfo->value.integer.max = 4095;
3659*771ad4dfSGeoffrey D. Bennett 	uinfo->value.integer.step = 1;
3660*771ad4dfSGeoffrey D. Bennett 	return 0;
3661*771ad4dfSGeoffrey D. Bennett }
3662*771ad4dfSGeoffrey D. Bennett 
scarlett2_meter_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3663*771ad4dfSGeoffrey D. Bennett static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl,
3664*771ad4dfSGeoffrey D. Bennett 				   struct snd_ctl_elem_value *ucontrol)
3665*771ad4dfSGeoffrey D. Bennett {
3666*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3667*771ad4dfSGeoffrey D. Bennett 	u16 meter_levels[SCARLETT2_MAX_METERS];
3668*771ad4dfSGeoffrey D. Bennett 	int i, err;
3669*771ad4dfSGeoffrey D. Bennett 
3670*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_get_meter_levels(elem->head.mixer, elem->channels,
3671*771ad4dfSGeoffrey D. Bennett 					     meter_levels);
3672*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
3673*771ad4dfSGeoffrey D. Bennett 		return err;
3674*771ad4dfSGeoffrey D. Bennett 
3675*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < elem->channels; i++)
3676*771ad4dfSGeoffrey D. Bennett 		ucontrol->value.integer.value[i] = meter_levels[i];
3677*771ad4dfSGeoffrey D. Bennett 
3678*771ad4dfSGeoffrey D. Bennett 	return 0;
3679*771ad4dfSGeoffrey D. Bennett }
3680*771ad4dfSGeoffrey D. Bennett 
3681*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_meter_ctl = {
3682*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
3683*771ad4dfSGeoffrey D. Bennett 	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
3684*771ad4dfSGeoffrey D. Bennett 	.name = "",
3685*771ad4dfSGeoffrey D. Bennett 	.info = scarlett2_meter_ctl_info,
3686*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_meter_ctl_get
3687*771ad4dfSGeoffrey D. Bennett };
3688*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_meter_ctl(struct usb_mixer_interface * mixer)3689*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_meter_ctl(struct usb_mixer_interface *mixer)
3690*771ad4dfSGeoffrey D. Bennett {
3691*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3692*771ad4dfSGeoffrey D. Bennett 
3693*771ad4dfSGeoffrey D. Bennett 	/* devices without a mixer also don't support reporting levels */
3694*771ad4dfSGeoffrey D. Bennett 	if (private->info->config_set == SCARLETT2_CONFIG_SET_NO_MIXER)
3695*771ad4dfSGeoffrey D. Bennett 		return 0;
3696*771ad4dfSGeoffrey D. Bennett 
3697*771ad4dfSGeoffrey D. Bennett 	return scarlett2_add_new_ctl(mixer, &scarlett2_meter_ctl,
3698*771ad4dfSGeoffrey D. Bennett 				     0, private->num_mux_dsts,
3699*771ad4dfSGeoffrey D. Bennett 				     "Level Meter", NULL);
3700*771ad4dfSGeoffrey D. Bennett }
3701*771ad4dfSGeoffrey D. Bennett 
3702*771ad4dfSGeoffrey D. Bennett /*** MSD Controls ***/
3703*771ad4dfSGeoffrey D. Bennett 
scarlett2_msd_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3704*771ad4dfSGeoffrey D. Bennett static int scarlett2_msd_ctl_get(struct snd_kcontrol *kctl,
3705*771ad4dfSGeoffrey D. Bennett 				 struct snd_ctl_elem_value *ucontrol)
3706*771ad4dfSGeoffrey D. Bennett {
3707*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3708*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = elem->head.mixer->private_data;
3709*771ad4dfSGeoffrey D. Bennett 
3710*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->msd_switch;
3711*771ad4dfSGeoffrey D. Bennett 	return 0;
3712*771ad4dfSGeoffrey D. Bennett }
3713*771ad4dfSGeoffrey D. Bennett 
scarlett2_msd_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3714*771ad4dfSGeoffrey D. Bennett static int scarlett2_msd_ctl_put(struct snd_kcontrol *kctl,
3715*771ad4dfSGeoffrey D. Bennett 				 struct snd_ctl_elem_value *ucontrol)
3716*771ad4dfSGeoffrey D. Bennett {
3717*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3718*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3719*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3720*771ad4dfSGeoffrey D. Bennett 
3721*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
3722*771ad4dfSGeoffrey D. Bennett 
3723*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3724*771ad4dfSGeoffrey D. Bennett 
3725*771ad4dfSGeoffrey D. Bennett 	oval = private->msd_switch;
3726*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.integer.value[0];
3727*771ad4dfSGeoffrey D. Bennett 
3728*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
3729*771ad4dfSGeoffrey D. Bennett 		goto unlock;
3730*771ad4dfSGeoffrey D. Bennett 
3731*771ad4dfSGeoffrey D. Bennett 	private->msd_switch = val;
3732*771ad4dfSGeoffrey D. Bennett 
3733*771ad4dfSGeoffrey D. Bennett 	/* Send switch change to the device */
3734*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MSD_SWITCH,
3735*771ad4dfSGeoffrey D. Bennett 				       0, val);
3736*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
3737*771ad4dfSGeoffrey D. Bennett 		err = 1;
3738*771ad4dfSGeoffrey D. Bennett 
3739*771ad4dfSGeoffrey D. Bennett unlock:
3740*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3741*771ad4dfSGeoffrey D. Bennett 	return err;
3742*771ad4dfSGeoffrey D. Bennett }
3743*771ad4dfSGeoffrey D. Bennett 
3744*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_msd_ctl = {
3745*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3746*771ad4dfSGeoffrey D. Bennett 	.name = "",
3747*771ad4dfSGeoffrey D. Bennett 	.info = snd_ctl_boolean_mono_info,
3748*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_msd_ctl_get,
3749*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_msd_ctl_put,
3750*771ad4dfSGeoffrey D. Bennett };
3751*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_msd_ctl(struct usb_mixer_interface * mixer)3752*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_msd_ctl(struct usb_mixer_interface *mixer)
3753*771ad4dfSGeoffrey D. Bennett {
3754*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3755*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3756*771ad4dfSGeoffrey D. Bennett 
3757*771ad4dfSGeoffrey D. Bennett 	if (!info->has_msd_mode)
3758*771ad4dfSGeoffrey D. Bennett 		return 0;
3759*771ad4dfSGeoffrey D. Bennett 
3760*771ad4dfSGeoffrey D. Bennett 	/* If MSD mode is off, hide the switch by default */
3761*771ad4dfSGeoffrey D. Bennett 	if (!private->msd_switch && !(mixer->chip->setup & SCARLETT2_MSD_ENABLE))
3762*771ad4dfSGeoffrey D. Bennett 		return 0;
3763*771ad4dfSGeoffrey D. Bennett 
3764*771ad4dfSGeoffrey D. Bennett 	/* Add MSD control */
3765*771ad4dfSGeoffrey D. Bennett 	return scarlett2_add_new_ctl(mixer, &scarlett2_msd_ctl,
3766*771ad4dfSGeoffrey D. Bennett 				     0, 1, "MSD Mode Switch", NULL);
3767*771ad4dfSGeoffrey D. Bennett }
3768*771ad4dfSGeoffrey D. Bennett 
3769*771ad4dfSGeoffrey D. Bennett /*** Standalone Control ***/
3770*771ad4dfSGeoffrey D. Bennett 
scarlett2_standalone_ctl_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3771*771ad4dfSGeoffrey D. Bennett static int scarlett2_standalone_ctl_get(struct snd_kcontrol *kctl,
3772*771ad4dfSGeoffrey D. Bennett 					struct snd_ctl_elem_value *ucontrol)
3773*771ad4dfSGeoffrey D. Bennett {
3774*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3775*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = elem->head.mixer->private_data;
3776*771ad4dfSGeoffrey D. Bennett 
3777*771ad4dfSGeoffrey D. Bennett 	ucontrol->value.integer.value[0] = private->standalone_switch;
3778*771ad4dfSGeoffrey D. Bennett 	return 0;
3779*771ad4dfSGeoffrey D. Bennett }
3780*771ad4dfSGeoffrey D. Bennett 
scarlett2_standalone_ctl_put(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ucontrol)3781*771ad4dfSGeoffrey D. Bennett static int scarlett2_standalone_ctl_put(struct snd_kcontrol *kctl,
3782*771ad4dfSGeoffrey D. Bennett 					struct snd_ctl_elem_value *ucontrol)
3783*771ad4dfSGeoffrey D. Bennett {
3784*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_elem_info *elem = kctl->private_data;
3785*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = elem->head.mixer;
3786*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3787*771ad4dfSGeoffrey D. Bennett 
3788*771ad4dfSGeoffrey D. Bennett 	int oval, val, err = 0;
3789*771ad4dfSGeoffrey D. Bennett 
3790*771ad4dfSGeoffrey D. Bennett 	mutex_lock(&private->data_mutex);
3791*771ad4dfSGeoffrey D. Bennett 
3792*771ad4dfSGeoffrey D. Bennett 	oval = private->standalone_switch;
3793*771ad4dfSGeoffrey D. Bennett 	val = !!ucontrol->value.integer.value[0];
3794*771ad4dfSGeoffrey D. Bennett 
3795*771ad4dfSGeoffrey D. Bennett 	if (oval == val)
3796*771ad4dfSGeoffrey D. Bennett 		goto unlock;
3797*771ad4dfSGeoffrey D. Bennett 
3798*771ad4dfSGeoffrey D. Bennett 	private->standalone_switch = val;
3799*771ad4dfSGeoffrey D. Bennett 
3800*771ad4dfSGeoffrey D. Bennett 	/* Send switch change to the device */
3801*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_set_config(mixer,
3802*771ad4dfSGeoffrey D. Bennett 				       SCARLETT2_CONFIG_STANDALONE_SWITCH,
3803*771ad4dfSGeoffrey D. Bennett 				       0, val);
3804*771ad4dfSGeoffrey D. Bennett 	if (err == 0)
3805*771ad4dfSGeoffrey D. Bennett 		err = 1;
3806*771ad4dfSGeoffrey D. Bennett 
3807*771ad4dfSGeoffrey D. Bennett unlock:
3808*771ad4dfSGeoffrey D. Bennett 	mutex_unlock(&private->data_mutex);
3809*771ad4dfSGeoffrey D. Bennett 	return err;
3810*771ad4dfSGeoffrey D. Bennett }
3811*771ad4dfSGeoffrey D. Bennett 
3812*771ad4dfSGeoffrey D. Bennett static const struct snd_kcontrol_new scarlett2_standalone_ctl = {
3813*771ad4dfSGeoffrey D. Bennett 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3814*771ad4dfSGeoffrey D. Bennett 	.name = "",
3815*771ad4dfSGeoffrey D. Bennett 	.info = snd_ctl_boolean_mono_info,
3816*771ad4dfSGeoffrey D. Bennett 	.get  = scarlett2_standalone_ctl_get,
3817*771ad4dfSGeoffrey D. Bennett 	.put  = scarlett2_standalone_ctl_put,
3818*771ad4dfSGeoffrey D. Bennett };
3819*771ad4dfSGeoffrey D. Bennett 
scarlett2_add_standalone_ctl(struct usb_mixer_interface * mixer)3820*771ad4dfSGeoffrey D. Bennett static int scarlett2_add_standalone_ctl(struct usb_mixer_interface *mixer)
3821*771ad4dfSGeoffrey D. Bennett {
3822*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3823*771ad4dfSGeoffrey D. Bennett 
3824*771ad4dfSGeoffrey D. Bennett 	if (private->info->config_set == SCARLETT2_CONFIG_SET_NO_MIXER)
3825*771ad4dfSGeoffrey D. Bennett 		return 0;
3826*771ad4dfSGeoffrey D. Bennett 
3827*771ad4dfSGeoffrey D. Bennett 	/* Add standalone control */
3828*771ad4dfSGeoffrey D. Bennett 	return scarlett2_add_new_ctl(mixer, &scarlett2_standalone_ctl,
3829*771ad4dfSGeoffrey D. Bennett 				     0, 1, "Standalone Switch", NULL);
3830*771ad4dfSGeoffrey D. Bennett }
3831*771ad4dfSGeoffrey D. Bennett 
3832*771ad4dfSGeoffrey D. Bennett /*** Cleanup/Suspend Callbacks ***/
3833*771ad4dfSGeoffrey D. Bennett 
scarlett2_private_free(struct usb_mixer_interface * mixer)3834*771ad4dfSGeoffrey D. Bennett static void scarlett2_private_free(struct usb_mixer_interface *mixer)
3835*771ad4dfSGeoffrey D. Bennett {
3836*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3837*771ad4dfSGeoffrey D. Bennett 
3838*771ad4dfSGeoffrey D. Bennett 	cancel_delayed_work_sync(&private->work);
3839*771ad4dfSGeoffrey D. Bennett 	kfree(private);
3840*771ad4dfSGeoffrey D. Bennett 	mixer->private_data = NULL;
3841*771ad4dfSGeoffrey D. Bennett }
3842*771ad4dfSGeoffrey D. Bennett 
scarlett2_private_suspend(struct usb_mixer_interface * mixer)3843*771ad4dfSGeoffrey D. Bennett static void scarlett2_private_suspend(struct usb_mixer_interface *mixer)
3844*771ad4dfSGeoffrey D. Bennett {
3845*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3846*771ad4dfSGeoffrey D. Bennett 
3847*771ad4dfSGeoffrey D. Bennett 	if (cancel_delayed_work_sync(&private->work))
3848*771ad4dfSGeoffrey D. Bennett 		scarlett2_config_save(private->mixer);
3849*771ad4dfSGeoffrey D. Bennett }
3850*771ad4dfSGeoffrey D. Bennett 
3851*771ad4dfSGeoffrey D. Bennett /*** Initialisation ***/
3852*771ad4dfSGeoffrey D. Bennett 
scarlett2_count_mux_io(struct scarlett2_data * private)3853*771ad4dfSGeoffrey D. Bennett static void scarlett2_count_mux_io(struct scarlett2_data *private)
3854*771ad4dfSGeoffrey D. Bennett {
3855*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3856*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3857*771ad4dfSGeoffrey D. Bennett 	int port_type, srcs = 0, dsts = 0;
3858*771ad4dfSGeoffrey D. Bennett 
3859*771ad4dfSGeoffrey D. Bennett 	for (port_type = 0;
3860*771ad4dfSGeoffrey D. Bennett 	     port_type < SCARLETT2_PORT_TYPE_COUNT;
3861*771ad4dfSGeoffrey D. Bennett 	     port_type++) {
3862*771ad4dfSGeoffrey D. Bennett 		srcs += port_count[port_type][SCARLETT2_PORT_IN];
3863*771ad4dfSGeoffrey D. Bennett 		dsts += port_count[port_type][SCARLETT2_PORT_OUT];
3864*771ad4dfSGeoffrey D. Bennett 	}
3865*771ad4dfSGeoffrey D. Bennett 
3866*771ad4dfSGeoffrey D. Bennett 	private->num_mux_srcs = srcs;
3867*771ad4dfSGeoffrey D. Bennett 	private->num_mux_dsts = dsts;
3868*771ad4dfSGeoffrey D. Bennett }
3869*771ad4dfSGeoffrey D. Bennett 
3870*771ad4dfSGeoffrey D. Bennett /* Look through the interface descriptors for the Focusrite Control
3871*771ad4dfSGeoffrey D. Bennett  * interface (bInterfaceClass = 255 Vendor Specific Class) and set
3872*771ad4dfSGeoffrey D. Bennett  * bInterfaceNumber, bEndpointAddress, wMaxPacketSize, and bInterval
3873*771ad4dfSGeoffrey D. Bennett  * in private
3874*771ad4dfSGeoffrey D. Bennett  */
scarlett2_find_fc_interface(struct usb_device * dev,struct scarlett2_data * private)3875*771ad4dfSGeoffrey D. Bennett static int scarlett2_find_fc_interface(struct usb_device *dev,
3876*771ad4dfSGeoffrey D. Bennett 				       struct scarlett2_data *private)
3877*771ad4dfSGeoffrey D. Bennett {
3878*771ad4dfSGeoffrey D. Bennett 	struct usb_host_config *config = dev->actconfig;
3879*771ad4dfSGeoffrey D. Bennett 	int i;
3880*771ad4dfSGeoffrey D. Bennett 
3881*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < config->desc.bNumInterfaces; i++) {
3882*771ad4dfSGeoffrey D. Bennett 		struct usb_interface *intf = config->interface[i];
3883*771ad4dfSGeoffrey D. Bennett 		struct usb_interface_descriptor *desc =
3884*771ad4dfSGeoffrey D. Bennett 			&intf->altsetting[0].desc;
3885*771ad4dfSGeoffrey D. Bennett 		struct usb_endpoint_descriptor *epd;
3886*771ad4dfSGeoffrey D. Bennett 
3887*771ad4dfSGeoffrey D. Bennett 		if (desc->bInterfaceClass != 255)
3888*771ad4dfSGeoffrey D. Bennett 			continue;
3889*771ad4dfSGeoffrey D. Bennett 
3890*771ad4dfSGeoffrey D. Bennett 		epd = get_endpoint(intf->altsetting, 0);
3891*771ad4dfSGeoffrey D. Bennett 		private->bInterfaceNumber = desc->bInterfaceNumber;
3892*771ad4dfSGeoffrey D. Bennett 		private->bEndpointAddress = epd->bEndpointAddress &
3893*771ad4dfSGeoffrey D. Bennett 			USB_ENDPOINT_NUMBER_MASK;
3894*771ad4dfSGeoffrey D. Bennett 		private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize);
3895*771ad4dfSGeoffrey D. Bennett 		private->bInterval = epd->bInterval;
3896*771ad4dfSGeoffrey D. Bennett 		return 0;
3897*771ad4dfSGeoffrey D. Bennett 	}
3898*771ad4dfSGeoffrey D. Bennett 
3899*771ad4dfSGeoffrey D. Bennett 	return -EINVAL;
3900*771ad4dfSGeoffrey D. Bennett }
3901*771ad4dfSGeoffrey D. Bennett 
3902*771ad4dfSGeoffrey D. Bennett /* Initialise private data */
scarlett2_init_private(struct usb_mixer_interface * mixer,const struct scarlett2_device_entry * entry)3903*771ad4dfSGeoffrey D. Bennett static int scarlett2_init_private(struct usb_mixer_interface *mixer,
3904*771ad4dfSGeoffrey D. Bennett 				  const struct scarlett2_device_entry *entry)
3905*771ad4dfSGeoffrey D. Bennett {
3906*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private =
3907*771ad4dfSGeoffrey D. Bennett 		kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL);
3908*771ad4dfSGeoffrey D. Bennett 
3909*771ad4dfSGeoffrey D. Bennett 	if (!private)
3910*771ad4dfSGeoffrey D. Bennett 		return -ENOMEM;
3911*771ad4dfSGeoffrey D. Bennett 
3912*771ad4dfSGeoffrey D. Bennett 	mutex_init(&private->usb_mutex);
3913*771ad4dfSGeoffrey D. Bennett 	mutex_init(&private->data_mutex);
3914*771ad4dfSGeoffrey D. Bennett 	INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work);
3915*771ad4dfSGeoffrey D. Bennett 
3916*771ad4dfSGeoffrey D. Bennett 	mixer->private_data = private;
3917*771ad4dfSGeoffrey D. Bennett 	mixer->private_free = scarlett2_private_free;
3918*771ad4dfSGeoffrey D. Bennett 	mixer->private_suspend = scarlett2_private_suspend;
3919*771ad4dfSGeoffrey D. Bennett 
3920*771ad4dfSGeoffrey D. Bennett 	private->info = entry->info;
3921*771ad4dfSGeoffrey D. Bennett 	private->series_name = entry->series_name;
3922*771ad4dfSGeoffrey D. Bennett 	scarlett2_count_mux_io(private);
3923*771ad4dfSGeoffrey D. Bennett 	private->scarlett2_seq = 0;
3924*771ad4dfSGeoffrey D. Bennett 	private->mixer = mixer;
3925*771ad4dfSGeoffrey D. Bennett 
3926*771ad4dfSGeoffrey D. Bennett 	return scarlett2_find_fc_interface(mixer->chip->dev, private);
3927*771ad4dfSGeoffrey D. Bennett }
3928*771ad4dfSGeoffrey D. Bennett 
3929*771ad4dfSGeoffrey D. Bennett /* Cargo cult proprietary initialisation sequence */
scarlett2_usb_init(struct usb_mixer_interface * mixer)3930*771ad4dfSGeoffrey D. Bennett static int scarlett2_usb_init(struct usb_mixer_interface *mixer)
3931*771ad4dfSGeoffrey D. Bennett {
3932*771ad4dfSGeoffrey D. Bennett 	struct usb_device *dev = mixer->chip->dev;
3933*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3934*771ad4dfSGeoffrey D. Bennett 	u8 buf[24];
3935*771ad4dfSGeoffrey D. Bennett 	int err;
3936*771ad4dfSGeoffrey D. Bennett 
3937*771ad4dfSGeoffrey D. Bennett 	if (usb_pipe_type_check(dev, usb_sndctrlpipe(dev, 0)))
3938*771ad4dfSGeoffrey D. Bennett 		return -EINVAL;
3939*771ad4dfSGeoffrey D. Bennett 
3940*771ad4dfSGeoffrey D. Bennett 	/* step 0 */
3941*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_rx(dev, private->bInterfaceNumber,
3942*771ad4dfSGeoffrey D. Bennett 			       SCARLETT2_USB_CMD_INIT, buf, sizeof(buf));
3943*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
3944*771ad4dfSGeoffrey D. Bennett 		return err;
3945*771ad4dfSGeoffrey D. Bennett 
3946*771ad4dfSGeoffrey D. Bennett 	/* step 1 */
3947*771ad4dfSGeoffrey D. Bennett 	private->scarlett2_seq = 1;
3948*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_1, NULL, 0, NULL, 0);
3949*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
3950*771ad4dfSGeoffrey D. Bennett 		return err;
3951*771ad4dfSGeoffrey D. Bennett 
3952*771ad4dfSGeoffrey D. Bennett 	/* step 2 */
3953*771ad4dfSGeoffrey D. Bennett 	private->scarlett2_seq = 1;
3954*771ad4dfSGeoffrey D. Bennett 	return scarlett2_usb(mixer, SCARLETT2_USB_INIT_2, NULL, 0, NULL, 84);
3955*771ad4dfSGeoffrey D. Bennett }
3956*771ad4dfSGeoffrey D. Bennett 
3957*771ad4dfSGeoffrey D. Bennett /* Read configuration from the interface on start */
scarlett2_read_configs(struct usb_mixer_interface * mixer)3958*771ad4dfSGeoffrey D. Bennett static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
3959*771ad4dfSGeoffrey D. Bennett {
3960*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
3961*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
3962*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3963*771ad4dfSGeoffrey D. Bennett 	int num_line_out =
3964*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
3965*771ad4dfSGeoffrey D. Bennett 	int num_mixer_out =
3966*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
3967*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_usb_volume_status volume_status;
3968*771ad4dfSGeoffrey D. Bennett 	int err, i;
3969*771ad4dfSGeoffrey D. Bennett 
3970*771ad4dfSGeoffrey D. Bennett 	if (info->has_msd_mode) {
3971*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_usb_get_config(
3972*771ad4dfSGeoffrey D. Bennett 			mixer, SCARLETT2_CONFIG_MSD_SWITCH,
3973*771ad4dfSGeoffrey D. Bennett 			1, &private->msd_switch);
3974*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
3975*771ad4dfSGeoffrey D. Bennett 			return err;
3976*771ad4dfSGeoffrey D. Bennett 
3977*771ad4dfSGeoffrey D. Bennett 		/* no other controls are created if MSD mode is on */
3978*771ad4dfSGeoffrey D. Bennett 		if (private->msd_switch)
3979*771ad4dfSGeoffrey D. Bennett 			return 0;
3980*771ad4dfSGeoffrey D. Bennett 	}
3981*771ad4dfSGeoffrey D. Bennett 
3982*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_update_input_other(mixer);
3983*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
3984*771ad4dfSGeoffrey D. Bennett 		return err;
3985*771ad4dfSGeoffrey D. Bennett 
3986*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_update_monitor_other(mixer);
3987*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
3988*771ad4dfSGeoffrey D. Bennett 		return err;
3989*771ad4dfSGeoffrey D. Bennett 
3990*771ad4dfSGeoffrey D. Bennett 	/* the rest of the configuration is for devices with a mixer */
3991*771ad4dfSGeoffrey D. Bennett 	if (info->config_set == SCARLETT2_CONFIG_SET_NO_MIXER)
3992*771ad4dfSGeoffrey D. Bennett 		return 0;
3993*771ad4dfSGeoffrey D. Bennett 
3994*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_get_config(
3995*771ad4dfSGeoffrey D. Bennett 		mixer, SCARLETT2_CONFIG_STANDALONE_SWITCH,
3996*771ad4dfSGeoffrey D. Bennett 		1, &private->standalone_switch);
3997*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
3998*771ad4dfSGeoffrey D. Bennett 		return err;
3999*771ad4dfSGeoffrey D. Bennett 
4000*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_update_sync(mixer);
4001*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4002*771ad4dfSGeoffrey D. Bennett 		return err;
4003*771ad4dfSGeoffrey D. Bennett 
4004*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_get_volume_status(mixer, &volume_status);
4005*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4006*771ad4dfSGeoffrey D. Bennett 		return err;
4007*771ad4dfSGeoffrey D. Bennett 
4008*771ad4dfSGeoffrey D. Bennett 	if (info->line_out_hw_vol)
4009*771ad4dfSGeoffrey D. Bennett 		for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++)
4010*771ad4dfSGeoffrey D. Bennett 			private->dim_mute[i] = !!volume_status.dim_mute[i];
4011*771ad4dfSGeoffrey D. Bennett 
4012*771ad4dfSGeoffrey D. Bennett 	private->master_vol = clamp(
4013*771ad4dfSGeoffrey D. Bennett 		volume_status.master_vol + SCARLETT2_VOLUME_BIAS,
4014*771ad4dfSGeoffrey D. Bennett 		0, SCARLETT2_VOLUME_BIAS);
4015*771ad4dfSGeoffrey D. Bennett 
4016*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < num_line_out; i++) {
4017*771ad4dfSGeoffrey D. Bennett 		int volume, mute;
4018*771ad4dfSGeoffrey D. Bennett 
4019*771ad4dfSGeoffrey D. Bennett 		private->vol_sw_hw_switch[i] =
4020*771ad4dfSGeoffrey D. Bennett 			info->line_out_hw_vol
4021*771ad4dfSGeoffrey D. Bennett 				&& volume_status.sw_hw_switch[i];
4022*771ad4dfSGeoffrey D. Bennett 
4023*771ad4dfSGeoffrey D. Bennett 		volume = private->vol_sw_hw_switch[i]
4024*771ad4dfSGeoffrey D. Bennett 			   ? volume_status.master_vol
4025*771ad4dfSGeoffrey D. Bennett 			   : volume_status.sw_vol[i];
4026*771ad4dfSGeoffrey D. Bennett 		volume = clamp(volume + SCARLETT2_VOLUME_BIAS,
4027*771ad4dfSGeoffrey D. Bennett 			       0, SCARLETT2_VOLUME_BIAS);
4028*771ad4dfSGeoffrey D. Bennett 		private->vol[i] = volume;
4029*771ad4dfSGeoffrey D. Bennett 
4030*771ad4dfSGeoffrey D. Bennett 		mute = private->vol_sw_hw_switch[i]
4031*771ad4dfSGeoffrey D. Bennett 			 ? private->dim_mute[SCARLETT2_BUTTON_MUTE]
4032*771ad4dfSGeoffrey D. Bennett 			 : volume_status.mute_switch[i];
4033*771ad4dfSGeoffrey D. Bennett 		private->mute_switch[i] = mute;
4034*771ad4dfSGeoffrey D. Bennett 	}
4035*771ad4dfSGeoffrey D. Bennett 
4036*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < num_mixer_out; i++) {
4037*771ad4dfSGeoffrey D. Bennett 		err = scarlett2_usb_get_mix(mixer, i);
4038*771ad4dfSGeoffrey D. Bennett 		if (err < 0)
4039*771ad4dfSGeoffrey D. Bennett 			return err;
4040*771ad4dfSGeoffrey D. Bennett 	}
4041*771ad4dfSGeoffrey D. Bennett 
4042*771ad4dfSGeoffrey D. Bennett 	return scarlett2_usb_get_mux(mixer);
4043*771ad4dfSGeoffrey D. Bennett }
4044*771ad4dfSGeoffrey D. Bennett 
4045*771ad4dfSGeoffrey D. Bennett /* Notify on sync change */
scarlett2_notify_sync(struct usb_mixer_interface * mixer)4046*771ad4dfSGeoffrey D. Bennett static void scarlett2_notify_sync(
4047*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer)
4048*771ad4dfSGeoffrey D. Bennett {
4049*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
4050*771ad4dfSGeoffrey D. Bennett 
4051*771ad4dfSGeoffrey D. Bennett 	private->sync_updated = 1;
4052*771ad4dfSGeoffrey D. Bennett 
4053*771ad4dfSGeoffrey D. Bennett 	snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
4054*771ad4dfSGeoffrey D. Bennett 		       &private->sync_ctl->id);
4055*771ad4dfSGeoffrey D. Bennett }
4056*771ad4dfSGeoffrey D. Bennett 
4057*771ad4dfSGeoffrey D. Bennett /* Notify on monitor change */
scarlett2_notify_monitor(struct usb_mixer_interface * mixer)4058*771ad4dfSGeoffrey D. Bennett static void scarlett2_notify_monitor(
4059*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer)
4060*771ad4dfSGeoffrey D. Bennett {
4061*771ad4dfSGeoffrey D. Bennett 	struct snd_card *card = mixer->chip->card;
4062*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
4063*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
4064*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
4065*771ad4dfSGeoffrey D. Bennett 	int num_line_out =
4066*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
4067*771ad4dfSGeoffrey D. Bennett 	int i;
4068*771ad4dfSGeoffrey D. Bennett 
4069*771ad4dfSGeoffrey D. Bennett 	/* if line_out_hw_vol is 0, there are no controls to update */
4070*771ad4dfSGeoffrey D. Bennett 	if (!info->line_out_hw_vol)
4071*771ad4dfSGeoffrey D. Bennett 		return;
4072*771ad4dfSGeoffrey D. Bennett 
4073*771ad4dfSGeoffrey D. Bennett 	private->vol_updated = 1;
4074*771ad4dfSGeoffrey D. Bennett 
4075*771ad4dfSGeoffrey D. Bennett 	snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
4076*771ad4dfSGeoffrey D. Bennett 		       &private->master_vol_ctl->id);
4077*771ad4dfSGeoffrey D. Bennett 
4078*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < num_line_out; i++)
4079*771ad4dfSGeoffrey D. Bennett 		if (private->vol_sw_hw_switch[line_out_remap(private, i)])
4080*771ad4dfSGeoffrey D. Bennett 			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4081*771ad4dfSGeoffrey D. Bennett 				       &private->vol_ctls[i]->id);
4082*771ad4dfSGeoffrey D. Bennett }
4083*771ad4dfSGeoffrey D. Bennett 
4084*771ad4dfSGeoffrey D. Bennett /* Notify on dim/mute change */
scarlett2_notify_dim_mute(struct usb_mixer_interface * mixer)4085*771ad4dfSGeoffrey D. Bennett static void scarlett2_notify_dim_mute(
4086*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer)
4087*771ad4dfSGeoffrey D. Bennett {
4088*771ad4dfSGeoffrey D. Bennett 	struct snd_card *card = mixer->chip->card;
4089*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
4090*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
4091*771ad4dfSGeoffrey D. Bennett 	const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
4092*771ad4dfSGeoffrey D. Bennett 	int num_line_out =
4093*771ad4dfSGeoffrey D. Bennett 		port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
4094*771ad4dfSGeoffrey D. Bennett 	int i;
4095*771ad4dfSGeoffrey D. Bennett 
4096*771ad4dfSGeoffrey D. Bennett 	private->vol_updated = 1;
4097*771ad4dfSGeoffrey D. Bennett 
4098*771ad4dfSGeoffrey D. Bennett 	if (!info->line_out_hw_vol)
4099*771ad4dfSGeoffrey D. Bennett 		return;
4100*771ad4dfSGeoffrey D. Bennett 
4101*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++)
4102*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4103*771ad4dfSGeoffrey D. Bennett 			       &private->dim_mute_ctls[i]->id);
4104*771ad4dfSGeoffrey D. Bennett 
4105*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < num_line_out; i++)
4106*771ad4dfSGeoffrey D. Bennett 		if (private->vol_sw_hw_switch[line_out_remap(private, i)])
4107*771ad4dfSGeoffrey D. Bennett 			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4108*771ad4dfSGeoffrey D. Bennett 				       &private->mute_ctls[i]->id);
4109*771ad4dfSGeoffrey D. Bennett }
4110*771ad4dfSGeoffrey D. Bennett 
4111*771ad4dfSGeoffrey D. Bennett /* Notify on "input other" change (level/pad/air) */
scarlett2_notify_input_other(struct usb_mixer_interface * mixer)4112*771ad4dfSGeoffrey D. Bennett static void scarlett2_notify_input_other(
4113*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer)
4114*771ad4dfSGeoffrey D. Bennett {
4115*771ad4dfSGeoffrey D. Bennett 	struct snd_card *card = mixer->chip->card;
4116*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
4117*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
4118*771ad4dfSGeoffrey D. Bennett 	int i;
4119*771ad4dfSGeoffrey D. Bennett 
4120*771ad4dfSGeoffrey D. Bennett 	private->input_other_updated = 1;
4121*771ad4dfSGeoffrey D. Bennett 
4122*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < info->level_input_count; i++)
4123*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4124*771ad4dfSGeoffrey D. Bennett 			       &private->level_ctls[i]->id);
4125*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < info->pad_input_count; i++)
4126*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4127*771ad4dfSGeoffrey D. Bennett 			       &private->pad_ctls[i]->id);
4128*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < info->air_input_count; i++)
4129*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4130*771ad4dfSGeoffrey D. Bennett 			       &private->air_ctls[i]->id);
4131*771ad4dfSGeoffrey D. Bennett 	for (i = 0; i < info->phantom_count; i++)
4132*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4133*771ad4dfSGeoffrey D. Bennett 			       &private->phantom_ctls[i]->id);
4134*771ad4dfSGeoffrey D. Bennett }
4135*771ad4dfSGeoffrey D. Bennett 
4136*771ad4dfSGeoffrey D. Bennett /* Notify on "monitor other" change (direct monitor, speaker
4137*771ad4dfSGeoffrey D. Bennett  * switching, talkback)
4138*771ad4dfSGeoffrey D. Bennett  */
scarlett2_notify_monitor_other(struct usb_mixer_interface * mixer)4139*771ad4dfSGeoffrey D. Bennett static void scarlett2_notify_monitor_other(
4140*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer)
4141*771ad4dfSGeoffrey D. Bennett {
4142*771ad4dfSGeoffrey D. Bennett 	struct snd_card *card = mixer->chip->card;
4143*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
4144*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_info *info = private->info;
4145*771ad4dfSGeoffrey D. Bennett 
4146*771ad4dfSGeoffrey D. Bennett 	private->monitor_other_updated = 1;
4147*771ad4dfSGeoffrey D. Bennett 
4148*771ad4dfSGeoffrey D. Bennett 	if (info->direct_monitor) {
4149*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4150*771ad4dfSGeoffrey D. Bennett 			       &private->direct_monitor_ctl->id);
4151*771ad4dfSGeoffrey D. Bennett 		return;
4152*771ad4dfSGeoffrey D. Bennett 	}
4153*771ad4dfSGeoffrey D. Bennett 
4154*771ad4dfSGeoffrey D. Bennett 	if (info->has_speaker_switching)
4155*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4156*771ad4dfSGeoffrey D. Bennett 			       &private->speaker_switching_ctl->id);
4157*771ad4dfSGeoffrey D. Bennett 
4158*771ad4dfSGeoffrey D. Bennett 	if (info->has_talkback)
4159*771ad4dfSGeoffrey D. Bennett 		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4160*771ad4dfSGeoffrey D. Bennett 			       &private->talkback_ctl->id);
4161*771ad4dfSGeoffrey D. Bennett 
4162*771ad4dfSGeoffrey D. Bennett 	/* if speaker switching was recently enabled or disabled,
4163*771ad4dfSGeoffrey D. Bennett 	 * invalidate the dim/mute and mux enum controls
4164*771ad4dfSGeoffrey D. Bennett 	 */
4165*771ad4dfSGeoffrey D. Bennett 	if (private->speaker_switching_switched) {
4166*771ad4dfSGeoffrey D. Bennett 		int i;
4167*771ad4dfSGeoffrey D. Bennett 
4168*771ad4dfSGeoffrey D. Bennett 		scarlett2_notify_dim_mute(mixer);
4169*771ad4dfSGeoffrey D. Bennett 
4170*771ad4dfSGeoffrey D. Bennett 		private->speaker_switching_switched = 0;
4171*771ad4dfSGeoffrey D. Bennett 		private->mux_updated = 1;
4172*771ad4dfSGeoffrey D. Bennett 
4173*771ad4dfSGeoffrey D. Bennett 		for (i = 0; i < private->num_mux_dsts; i++)
4174*771ad4dfSGeoffrey D. Bennett 			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
4175*771ad4dfSGeoffrey D. Bennett 				       &private->mux_ctls[i]->id);
4176*771ad4dfSGeoffrey D. Bennett 	}
4177*771ad4dfSGeoffrey D. Bennett }
4178*771ad4dfSGeoffrey D. Bennett 
4179*771ad4dfSGeoffrey D. Bennett /* Interrupt callback */
scarlett2_notify(struct urb * urb)4180*771ad4dfSGeoffrey D. Bennett static void scarlett2_notify(struct urb *urb)
4181*771ad4dfSGeoffrey D. Bennett {
4182*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer = urb->context;
4183*771ad4dfSGeoffrey D. Bennett 	int len = urb->actual_length;
4184*771ad4dfSGeoffrey D. Bennett 	int ustatus = urb->status;
4185*771ad4dfSGeoffrey D. Bennett 	u32 data;
4186*771ad4dfSGeoffrey D. Bennett 
4187*771ad4dfSGeoffrey D. Bennett 	if (ustatus != 0 || len != 8)
4188*771ad4dfSGeoffrey D. Bennett 		goto requeue;
4189*771ad4dfSGeoffrey D. Bennett 
4190*771ad4dfSGeoffrey D. Bennett 	data = le32_to_cpu(*(__le32 *)urb->transfer_buffer);
4191*771ad4dfSGeoffrey D. Bennett 	if (data & SCARLETT2_USB_NOTIFY_SYNC)
4192*771ad4dfSGeoffrey D. Bennett 		scarlett2_notify_sync(mixer);
4193*771ad4dfSGeoffrey D. Bennett 	if (data & SCARLETT2_USB_NOTIFY_MONITOR)
4194*771ad4dfSGeoffrey D. Bennett 		scarlett2_notify_monitor(mixer);
4195*771ad4dfSGeoffrey D. Bennett 	if (data & SCARLETT2_USB_NOTIFY_DIM_MUTE)
4196*771ad4dfSGeoffrey D. Bennett 		scarlett2_notify_dim_mute(mixer);
4197*771ad4dfSGeoffrey D. Bennett 	if (data & SCARLETT2_USB_NOTIFY_INPUT_OTHER)
4198*771ad4dfSGeoffrey D. Bennett 		scarlett2_notify_input_other(mixer);
4199*771ad4dfSGeoffrey D. Bennett 	if (data & SCARLETT2_USB_NOTIFY_MONITOR_OTHER)
4200*771ad4dfSGeoffrey D. Bennett 		scarlett2_notify_monitor_other(mixer);
4201*771ad4dfSGeoffrey D. Bennett 
4202*771ad4dfSGeoffrey D. Bennett requeue:
4203*771ad4dfSGeoffrey D. Bennett 	if (ustatus != -ENOENT &&
4204*771ad4dfSGeoffrey D. Bennett 	    ustatus != -ECONNRESET &&
4205*771ad4dfSGeoffrey D. Bennett 	    ustatus != -ESHUTDOWN) {
4206*771ad4dfSGeoffrey D. Bennett 		urb->dev = mixer->chip->dev;
4207*771ad4dfSGeoffrey D. Bennett 		usb_submit_urb(urb, GFP_ATOMIC);
4208*771ad4dfSGeoffrey D. Bennett 	}
4209*771ad4dfSGeoffrey D. Bennett }
4210*771ad4dfSGeoffrey D. Bennett 
scarlett2_init_notify(struct usb_mixer_interface * mixer)4211*771ad4dfSGeoffrey D. Bennett static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
4212*771ad4dfSGeoffrey D. Bennett {
4213*771ad4dfSGeoffrey D. Bennett 	struct usb_device *dev = mixer->chip->dev;
4214*771ad4dfSGeoffrey D. Bennett 	struct scarlett2_data *private = mixer->private_data;
4215*771ad4dfSGeoffrey D. Bennett 	unsigned int pipe = usb_rcvintpipe(dev, private->bEndpointAddress);
4216*771ad4dfSGeoffrey D. Bennett 	void *transfer_buffer;
4217*771ad4dfSGeoffrey D. Bennett 
4218*771ad4dfSGeoffrey D. Bennett 	if (mixer->urb) {
4219*771ad4dfSGeoffrey D. Bennett 		usb_audio_err(mixer->chip,
4220*771ad4dfSGeoffrey D. Bennett 			      "%s: mixer urb already in use!\n", __func__);
4221*771ad4dfSGeoffrey D. Bennett 		return 0;
4222*771ad4dfSGeoffrey D. Bennett 	}
4223*771ad4dfSGeoffrey D. Bennett 
4224*771ad4dfSGeoffrey D. Bennett 	if (usb_pipe_type_check(dev, pipe))
4225*771ad4dfSGeoffrey D. Bennett 		return -EINVAL;
4226*771ad4dfSGeoffrey D. Bennett 
4227*771ad4dfSGeoffrey D. Bennett 	mixer->urb = usb_alloc_urb(0, GFP_KERNEL);
4228*771ad4dfSGeoffrey D. Bennett 	if (!mixer->urb)
4229*771ad4dfSGeoffrey D. Bennett 		return -ENOMEM;
4230*771ad4dfSGeoffrey D. Bennett 
4231*771ad4dfSGeoffrey D. Bennett 	transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL);
4232*771ad4dfSGeoffrey D. Bennett 	if (!transfer_buffer)
4233*771ad4dfSGeoffrey D. Bennett 		return -ENOMEM;
4234*771ad4dfSGeoffrey D. Bennett 
4235*771ad4dfSGeoffrey D. Bennett 	usb_fill_int_urb(mixer->urb, dev, pipe,
4236*771ad4dfSGeoffrey D. Bennett 			 transfer_buffer, private->wMaxPacketSize,
4237*771ad4dfSGeoffrey D. Bennett 			 scarlett2_notify, mixer, private->bInterval);
4238*771ad4dfSGeoffrey D. Bennett 
4239*771ad4dfSGeoffrey D. Bennett 	return usb_submit_urb(mixer->urb, GFP_KERNEL);
4240*771ad4dfSGeoffrey D. Bennett }
4241*771ad4dfSGeoffrey D. Bennett 
get_scarlett2_device_entry(struct usb_mixer_interface * mixer)4242*771ad4dfSGeoffrey D. Bennett static const struct scarlett2_device_entry *get_scarlett2_device_entry(
4243*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer)
4244*771ad4dfSGeoffrey D. Bennett {
4245*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_entry *entry = scarlett2_devices;
4246*771ad4dfSGeoffrey D. Bennett 
4247*771ad4dfSGeoffrey D. Bennett 	/* Find entry in scarlett2_devices */
4248*771ad4dfSGeoffrey D. Bennett 	while (entry->usb_id && entry->usb_id != mixer->chip->usb_id)
4249*771ad4dfSGeoffrey D. Bennett 		entry++;
4250*771ad4dfSGeoffrey D. Bennett 	if (!entry->usb_id)
4251*771ad4dfSGeoffrey D. Bennett 		return NULL;
4252*771ad4dfSGeoffrey D. Bennett 
4253*771ad4dfSGeoffrey D. Bennett 	return entry;
4254*771ad4dfSGeoffrey D. Bennett }
4255*771ad4dfSGeoffrey D. Bennett 
snd_scarlett2_controls_create(struct usb_mixer_interface * mixer,const struct scarlett2_device_entry * entry)4256*771ad4dfSGeoffrey D. Bennett static int snd_scarlett2_controls_create(
4257*771ad4dfSGeoffrey D. Bennett 	struct usb_mixer_interface *mixer,
4258*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_entry *entry)
4259*771ad4dfSGeoffrey D. Bennett {
4260*771ad4dfSGeoffrey D. Bennett 	int err;
4261*771ad4dfSGeoffrey D. Bennett 
4262*771ad4dfSGeoffrey D. Bennett 	/* Initialise private data */
4263*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_init_private(mixer, entry);
4264*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4265*771ad4dfSGeoffrey D. Bennett 		return err;
4266*771ad4dfSGeoffrey D. Bennett 
4267*771ad4dfSGeoffrey D. Bennett 	/* Send proprietary USB initialisation sequence */
4268*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_usb_init(mixer);
4269*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4270*771ad4dfSGeoffrey D. Bennett 		return err;
4271*771ad4dfSGeoffrey D. Bennett 
4272*771ad4dfSGeoffrey D. Bennett 	/* Read volume levels and controls from the interface */
4273*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_read_configs(mixer);
4274*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4275*771ad4dfSGeoffrey D. Bennett 		return err;
4276*771ad4dfSGeoffrey D. Bennett 
4277*771ad4dfSGeoffrey D. Bennett 	/* Create the MSD control */
4278*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_msd_ctl(mixer);
4279*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4280*771ad4dfSGeoffrey D. Bennett 		return err;
4281*771ad4dfSGeoffrey D. Bennett 
4282*771ad4dfSGeoffrey D. Bennett 	/* If MSD mode is enabled, don't create any other controls */
4283*771ad4dfSGeoffrey D. Bennett 	if (((struct scarlett2_data *)mixer->private_data)->msd_switch)
4284*771ad4dfSGeoffrey D. Bennett 		return 0;
4285*771ad4dfSGeoffrey D. Bennett 
4286*771ad4dfSGeoffrey D. Bennett 	/* Create the analogue output controls */
4287*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_line_out_ctls(mixer);
4288*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4289*771ad4dfSGeoffrey D. Bennett 		return err;
4290*771ad4dfSGeoffrey D. Bennett 
4291*771ad4dfSGeoffrey D. Bennett 	/* Create the analogue input controls */
4292*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_line_in_ctls(mixer);
4293*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4294*771ad4dfSGeoffrey D. Bennett 		return err;
4295*771ad4dfSGeoffrey D. Bennett 
4296*771ad4dfSGeoffrey D. Bennett 	/* Create the input, output, and mixer mux input selections */
4297*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_mux_enums(mixer);
4298*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4299*771ad4dfSGeoffrey D. Bennett 		return err;
4300*771ad4dfSGeoffrey D. Bennett 
4301*771ad4dfSGeoffrey D. Bennett 	/* Create the matrix mixer controls */
4302*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_mixer_ctls(mixer);
4303*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4304*771ad4dfSGeoffrey D. Bennett 		return err;
4305*771ad4dfSGeoffrey D. Bennett 
4306*771ad4dfSGeoffrey D. Bennett 	/* Create the level meter controls */
4307*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_meter_ctl(mixer);
4308*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4309*771ad4dfSGeoffrey D. Bennett 		return err;
4310*771ad4dfSGeoffrey D. Bennett 
4311*771ad4dfSGeoffrey D. Bennett 	/* Create the sync control */
4312*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_sync_ctl(mixer);
4313*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4314*771ad4dfSGeoffrey D. Bennett 		return err;
4315*771ad4dfSGeoffrey D. Bennett 
4316*771ad4dfSGeoffrey D. Bennett 	/* Create the direct monitor control */
4317*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_direct_monitor_ctl(mixer);
4318*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4319*771ad4dfSGeoffrey D. Bennett 		return err;
4320*771ad4dfSGeoffrey D. Bennett 
4321*771ad4dfSGeoffrey D. Bennett 	/* Create the speaker switching control */
4322*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_speaker_switch_ctl(mixer);
4323*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4324*771ad4dfSGeoffrey D. Bennett 		return err;
4325*771ad4dfSGeoffrey D. Bennett 
4326*771ad4dfSGeoffrey D. Bennett 	/* Create the talkback controls */
4327*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_talkback_ctls(mixer);
4328*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4329*771ad4dfSGeoffrey D. Bennett 		return err;
4330*771ad4dfSGeoffrey D. Bennett 
4331*771ad4dfSGeoffrey D. Bennett 	/* Create the standalone control */
4332*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_add_standalone_ctl(mixer);
4333*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4334*771ad4dfSGeoffrey D. Bennett 		return err;
4335*771ad4dfSGeoffrey D. Bennett 
4336*771ad4dfSGeoffrey D. Bennett 	/* Set up the interrupt polling */
4337*771ad4dfSGeoffrey D. Bennett 	err = scarlett2_init_notify(mixer);
4338*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4339*771ad4dfSGeoffrey D. Bennett 		return err;
4340*771ad4dfSGeoffrey D. Bennett 
4341*771ad4dfSGeoffrey D. Bennett 	return 0;
4342*771ad4dfSGeoffrey D. Bennett }
4343*771ad4dfSGeoffrey D. Bennett 
snd_scarlett2_init(struct usb_mixer_interface * mixer)4344*771ad4dfSGeoffrey D. Bennett int snd_scarlett2_init(struct usb_mixer_interface *mixer)
4345*771ad4dfSGeoffrey D. Bennett {
4346*771ad4dfSGeoffrey D. Bennett 	struct snd_usb_audio *chip = mixer->chip;
4347*771ad4dfSGeoffrey D. Bennett 	const struct scarlett2_device_entry *entry;
4348*771ad4dfSGeoffrey D. Bennett 	int err;
4349*771ad4dfSGeoffrey D. Bennett 
4350*771ad4dfSGeoffrey D. Bennett 	/* only use UAC_VERSION_2 */
4351*771ad4dfSGeoffrey D. Bennett 	if (!mixer->protocol)
4352*771ad4dfSGeoffrey D. Bennett 		return 0;
4353*771ad4dfSGeoffrey D. Bennett 
4354*771ad4dfSGeoffrey D. Bennett 	/* find entry in scarlett2_devices */
4355*771ad4dfSGeoffrey D. Bennett 	entry = get_scarlett2_device_entry(mixer);
4356*771ad4dfSGeoffrey D. Bennett 	if (!entry) {
4357*771ad4dfSGeoffrey D. Bennett 		usb_audio_err(mixer->chip,
4358*771ad4dfSGeoffrey D. Bennett 			      "%s: missing device entry for %04x:%04x\n",
4359*771ad4dfSGeoffrey D. Bennett 			      __func__,
4360*771ad4dfSGeoffrey D. Bennett 			      USB_ID_VENDOR(chip->usb_id),
4361*771ad4dfSGeoffrey D. Bennett 			      USB_ID_PRODUCT(chip->usb_id));
4362*771ad4dfSGeoffrey D. Bennett 		return 0;
4363*771ad4dfSGeoffrey D. Bennett 	}
4364*771ad4dfSGeoffrey D. Bennett 
4365*771ad4dfSGeoffrey D. Bennett 	if (chip->setup & SCARLETT2_DISABLE) {
4366*771ad4dfSGeoffrey D. Bennett 		usb_audio_info(chip,
4367*771ad4dfSGeoffrey D. Bennett 			"Focusrite %s Mixer Driver disabled "
4368*771ad4dfSGeoffrey D. Bennett 			"by modprobe options (snd_usb_audio "
4369*771ad4dfSGeoffrey D. Bennett 			"vid=0x%04x pid=0x%04x device_setup=%d)\n",
4370*771ad4dfSGeoffrey D. Bennett 			entry->series_name,
4371*771ad4dfSGeoffrey D. Bennett 			USB_ID_VENDOR(chip->usb_id),
4372*771ad4dfSGeoffrey D. Bennett 			USB_ID_PRODUCT(chip->usb_id),
4373*771ad4dfSGeoffrey D. Bennett 			SCARLETT2_DISABLE);
4374*771ad4dfSGeoffrey D. Bennett 		return 0;
4375*771ad4dfSGeoffrey D. Bennett 	}
4376*771ad4dfSGeoffrey D. Bennett 
4377*771ad4dfSGeoffrey D. Bennett 	usb_audio_info(chip,
4378*771ad4dfSGeoffrey D. Bennett 		"Focusrite %s Mixer Driver enabled (pid=0x%04x); "
4379*771ad4dfSGeoffrey D. Bennett 		"report any issues to g@b4.vu",
4380*771ad4dfSGeoffrey D. Bennett 		entry->series_name,
4381*771ad4dfSGeoffrey D. Bennett 		USB_ID_PRODUCT(chip->usb_id));
4382*771ad4dfSGeoffrey D. Bennett 
4383*771ad4dfSGeoffrey D. Bennett 	err = snd_scarlett2_controls_create(mixer, entry);
4384*771ad4dfSGeoffrey D. Bennett 	if (err < 0)
4385*771ad4dfSGeoffrey D. Bennett 		usb_audio_err(mixer->chip,
4386*771ad4dfSGeoffrey D. Bennett 			      "Error initialising %s Mixer Driver: %d",
4387*771ad4dfSGeoffrey D. Bennett 			      entry->series_name,
4388*771ad4dfSGeoffrey D. Bennett 			      err);
4389*771ad4dfSGeoffrey D. Bennett 
4390*771ad4dfSGeoffrey D. Bennett 	return err;
4391*771ad4dfSGeoffrey D. Bennett }
4392