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