blob: 53ebabf42472224ee1dee0eeea5e8f7879c4739c [file] [log] [blame]
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301// SPDX-License-Identifier: GPL-2.0
2/*
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +09303 * Focusrite Scarlett Gen 2/3 Driver for ALSA
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09304 *
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +09305 * Supported models:
6 * - 6i6/18i8/18i20 Gen 2
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09307 * - Solo/2i2/4i4/8i6/18i8/18i20 Gen 3
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +09308 *
9 * Copyright (c) 2018-2021 by Geoffrey D. Bennett <g at b4.vu>
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +093010 * Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com>
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +093011 *
12 * Based on the Scarlett (Gen 1) Driver for ALSA:
13 *
14 * Copyright (c) 2013 by Tobias Hoffmann
15 * Copyright (c) 2013 by Robin Gareus <robin at gareus.org>
16 * Copyright (c) 2002 by Takashi Iwai <tiwai at suse.de>
17 * Copyright (c) 2014 by Chris J Arges <chris.j.arges at canonical.com>
18 *
19 * Many codes borrowed from audio.c by
20 * Alan Cox (alan at lxorguk.ukuu.org.uk)
21 * Thomas Sailer (sailer at ife.ee.ethz.ch)
22 *
23 * Code cleanup:
24 * David Henningsson <david.henningsson at canonical.com>
25 */
26
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +093027/* The protocol was reverse engineered by looking at the communication
28 * between Focusrite Control 2.3.4 and the Focusrite(R) Scarlett 18i20
29 * (firmware 1083) using usbmon in July-August 2018.
30 *
31 * Scarlett 18i8 support added in April 2019.
32 *
33 * Scarlett 6i6 support added in June 2019 (thanks to Martin Wittmann
34 * for providing usbmon output and testing).
35 *
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +093036 * Scarlett 4i4/8i6 Gen 3 support added in May 2020 (thanks to Laurent
37 * Debricon for donating a 4i4 and to Fredrik Unger for providing 8i6
38 * usbmon output and testing).
39 *
40 * Scarlett 18i8/18i20 Gen 3 support added in June 2020 (thanks to
41 * Darren Jaeckel, Alex Sedlack, and Clovis Lunel for providing usbmon
42 * output, protocol traces and testing).
43 *
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +093044 * Support for loading mixer volume and mux configuration from the
45 * interface during driver initialisation added in May 2021 (thanks to
46 * Vladimir Sadovnikov for figuring out how).
47 *
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +093048 * Support for Solo/2i2 Gen 3 added in May 2021 (thanks to Alexander
49 * Vorona for 2i2 protocol traces).
50 *
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +093051 * Support for phantom power, direct monitoring, speaker switching,
52 * and talkback added in May-June 2021.
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +093053 *
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +093054 * This ALSA mixer gives access to (model-dependent):
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +093055 * - input, output, mixer-matrix muxes
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +093056 * - mixer-matrix gain stages
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +093057 * - gain/volume/mute controls
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +093058 * - level meters
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +093059 * - line/inst level, pad, and air controls
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +093060 * - phantom power, direct monitor, speaker switching, and talkback
61 * controls
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +093062 * - disable/enable MSD mode
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +093063 *
64 * <ditaa>
65 * /--------------\ 18chn 20chn /--------------\
66 * | Hardware in +--+------\ /-------------+--+ ALSA PCM out |
67 * \--------------/ | | | | \--------------/
68 * | | | /-----\ |
69 * | | | | | |
70 * | v v v | |
71 * | +---------------+ | |
72 * | \ Matrix Mux / | |
73 * | +-----+-----+ | |
74 * | | | |
75 * | |18chn | |
76 * | | | |
77 * | | 10chn| |
78 * | v | |
79 * | +------------+ | |
80 * | | Mixer | | |
81 * | | Matrix | | |
82 * | | | | |
83 * | | 18x10 Gain | | |
84 * | | stages | | |
85 * | +-----+------+ | |
86 * | | | |
87 * |18chn |10chn | |20chn
88 * | | | |
89 * | +----------/ |
90 * | | |
91 * v v v
92 * ===========================
93 * +---------------+ +--—------------+
94 * \ Output Mux / \ Capture Mux /
95 * +---+---+---+ +-----+-----+
96 * | | |
97 * 10chn| | |18chn
98 * | | |
99 * /--------------\ | | | /--------------\
100 * | S/PDIF, ADAT |<--/ |10chn \-->| ALSA PCM in |
101 * | Hardware out | | \--------------/
102 * \--------------/ |
103 * v
104 * +-------------+ Software gain per channel.
105 * | Master Gain |<-- 18i20 only: Switch per channel
106 * +------+------+ to select HW or SW gain control.
107 * |
108 * |10chn
109 * /--------------\ |
110 * | Analogue |<------/
111 * | Hardware out |
112 * \--------------/
113 * </ditaa>
114 *
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930115 * Gen 3 devices have a Mass Storage Device (MSD) mode where a small
116 * disk with registration and driver download information is presented
117 * to the host. To access the full functionality of the device without
118 * proprietary software, MSD mode can be disabled by:
119 * - holding down the 48V button for five seconds while powering on
120 * the device, or
121 * - using this driver and alsamixer to change the "MSD Mode" setting
122 * to Off and power-cycling the device
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930123 */
124
125#include <linux/slab.h>
126#include <linux/usb.h>
127#include <linux/moduleparam.h>
128
129#include <sound/control.h>
130#include <sound/tlv.h>
131
132#include "usbaudio.h"
133#include "mixer.h"
134#include "helper.h"
135
136#include "mixer_scarlett_gen2.h"
137
138/* device_setup value to enable */
139#define SCARLETT2_ENABLE 0x01
140
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930141/* device_setup value to allow turning MSD mode back on */
142#define SCARLETT2_MSD_ENABLE 0x02
143
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930144/* some gui mixers can't handle negative ctl values */
145#define SCARLETT2_VOLUME_BIAS 127
146
147/* mixer range from -80dB to +6dB in 0.5dB steps */
148#define SCARLETT2_MIXER_MIN_DB -80
149#define SCARLETT2_MIXER_BIAS (-SCARLETT2_MIXER_MIN_DB * 2)
150#define SCARLETT2_MIXER_MAX_DB 6
151#define SCARLETT2_MIXER_MAX_VALUE \
152 ((SCARLETT2_MIXER_MAX_DB - SCARLETT2_MIXER_MIN_DB) * 2)
Geoffrey D. Bennett2661f032021-06-08 04:43:25 +0930153#define SCARLETT2_MIXER_VALUE_COUNT (SCARLETT2_MIXER_MAX_VALUE + 1)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930154
155/* map from (dB + 80) * 2 to mixer value
156 * for dB in 0 .. 172: int(8192 * pow(10, ((dB - 160) / 2 / 20)))
157 */
Geoffrey D. Bennett2661f032021-06-08 04:43:25 +0930158static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = {
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930159 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
160 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8,
161 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
162 23, 24, 25, 27, 29, 30, 32, 34, 36, 38, 41, 43, 46, 48, 51,
163 54, 57, 61, 65, 68, 73, 77, 81, 86, 91, 97, 103, 109, 115,
164 122, 129, 137, 145, 154, 163, 173, 183, 194, 205, 217, 230,
165 244, 259, 274, 290, 307, 326, 345, 365, 387, 410, 434, 460,
166 487, 516, 547, 579, 614, 650, 689, 730, 773, 819, 867, 919,
167 973, 1031, 1092, 1157, 1225, 1298, 1375, 1456, 1543, 1634,
168 1731, 1833, 1942, 2057, 2179, 2308, 2445, 2590, 2744, 2906,
169 3078, 3261, 3454, 3659, 3876, 4105, 4349, 4606, 4879, 5168,
170 5475, 5799, 6143, 6507, 6892, 7301, 7733, 8192, 8677, 9191,
171 9736, 10313, 10924, 11571, 12257, 12983, 13752, 14567, 15430,
172 16345
173};
174
175/* Maximum number of analogue outputs */
176#define SCARLETT2_ANALOGUE_MAX 10
177
178/* Maximum number of level and pad switches */
179#define SCARLETT2_LEVEL_SWITCH_MAX 2
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930180#define SCARLETT2_PAD_SWITCH_MAX 8
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930181#define SCARLETT2_AIR_SWITCH_MAX 8
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930182#define SCARLETT2_PHANTOM_SWITCH_MAX 2
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930183
184/* Maximum number of inputs to the mixer */
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930185#define SCARLETT2_INPUT_MIX_MAX 25
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930186
187/* Maximum number of outputs from the mixer */
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930188#define SCARLETT2_OUTPUT_MIX_MAX 12
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930189
190/* Maximum size of the data in the USB mux assignment message:
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930191 * 20 inputs, 20 outputs, 25 matrix inputs, 12 spare
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930192 */
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930193#define SCARLETT2_MUX_MAX 77
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930194
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +0930195/* Maximum number of meters (sum of output port counts) */
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930196#define SCARLETT2_MAX_METERS 65
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930197
198/* Hardware port types:
199 * - None (no input to mux)
200 * - Analogue I/O
201 * - S/PDIF I/O
202 * - ADAT I/O
203 * - Mixer I/O
204 * - PCM I/O
205 */
206enum {
Geoffrey D. Bennett06a21622021-06-21 02:16:28 +0930207 SCARLETT2_PORT_TYPE_NONE = 0,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930208 SCARLETT2_PORT_TYPE_ANALOGUE = 1,
Geoffrey D. Bennett06a21622021-06-21 02:16:28 +0930209 SCARLETT2_PORT_TYPE_SPDIF = 2,
210 SCARLETT2_PORT_TYPE_ADAT = 3,
211 SCARLETT2_PORT_TYPE_MIX = 4,
212 SCARLETT2_PORT_TYPE_PCM = 5,
213 SCARLETT2_PORT_TYPE_COUNT = 6,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930214};
215
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +0930216/* I/O count of each port type kept in struct scarlett2_ports */
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930217enum {
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +0930218 SCARLETT2_PORT_IN = 0,
219 SCARLETT2_PORT_OUT = 1,
220 SCARLETT2_PORT_DIRNS = 2,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930221};
222
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +0930223/* Dim/Mute buttons on the 18i20 */
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +0930224enum {
225 SCARLETT2_BUTTON_MUTE = 0,
226 SCARLETT2_BUTTON_DIM = 1,
227 SCARLETT2_DIM_MUTE_COUNT = 2,
228};
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930229
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +0930230static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = {
Geoffrey D. Bennettcdf72832021-07-23 05:41:53 +0930231 "Mute Playback Switch", "Dim Playback Switch"
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930232};
233
234/* Description of each hardware port type:
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +0930235 * - id: hardware ID of this port type
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930236 * - src_descr: printf format string for mux input selections
237 * - src_num_offset: added to channel number for the fprintf
238 * - dst_descr: printf format string for mixer controls
239 */
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +0930240struct scarlett2_port {
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930241 u16 id;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930242 const char * const src_descr;
243 int src_num_offset;
244 const char * const dst_descr;
245};
246
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +0930247static const struct scarlett2_port scarlett2_ports[SCARLETT2_PORT_TYPE_COUNT] = {
248 [SCARLETT2_PORT_TYPE_NONE] = {
249 .id = 0x000,
250 .src_descr = "Off"
251 },
252 [SCARLETT2_PORT_TYPE_ANALOGUE] = {
253 .id = 0x080,
254 .src_descr = "Analogue %d",
255 .src_num_offset = 1,
256 .dst_descr = "Analogue Output %02d Playback"
257 },
258 [SCARLETT2_PORT_TYPE_SPDIF] = {
259 .id = 0x180,
260 .src_descr = "S/PDIF %d",
261 .src_num_offset = 1,
262 .dst_descr = "S/PDIF Output %d Playback"
263 },
264 [SCARLETT2_PORT_TYPE_ADAT] = {
265 .id = 0x200,
266 .src_descr = "ADAT %d",
267 .src_num_offset = 1,
268 .dst_descr = "ADAT Output %d Playback"
269 },
270 [SCARLETT2_PORT_TYPE_MIX] = {
271 .id = 0x300,
272 .src_descr = "Mix %c",
273 .src_num_offset = 'A',
274 .dst_descr = "Mixer Input %02d Capture"
275 },
276 [SCARLETT2_PORT_TYPE_PCM] = {
277 .id = 0x600,
278 .src_descr = "PCM %d",
279 .src_num_offset = 1,
280 .dst_descr = "PCM %02d Capture"
281 },
282};
283
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +0930284/* Number of mux tables: one for each band of sample rates
285 * (44.1/48kHz, 88.2/96kHz, and 176.4/176kHz)
286 */
287#define SCARLETT2_MUX_TABLES 3
288
289/* Maximum number of entries in a mux table */
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930290#define SCARLETT2_MAX_MUX_ENTRIES 10
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +0930291
292/* One entry within mux_assignment defines the port type and range of
293 * ports to add to the set_mux message. The end of the list is marked
294 * with count == 0.
295 */
296struct scarlett2_mux_entry {
297 u8 port_type;
298 u8 start;
299 u8 count;
300};
301
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930302struct scarlett2_device_info {
Geoffrey D. Bennettd92b9152021-06-22 03:39:31 +0930303 u32 usb_id; /* USB device identifier */
Geoffrey D. Bennett904e6da2021-06-22 03:39:35 +0930304
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930305 /* Gen 3 devices have an internal MSD mode switch that needs
306 * to be disabled in order to access the full functionality of
307 * the device.
308 */
309 u8 has_msd_mode;
310
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930311 /* Gen 3 devices without a mixer have a different
312 * configuration set
313 */
314 u8 has_mixer;
315
Geoffrey D. Bennett904e6da2021-06-22 03:39:35 +0930316 /* line out hw volume is sw controlled */
317 u8 line_out_hw_vol;
318
Geoffrey D. Bennette914d842021-06-23 02:33:58 +0930319 /* support for main/alt speaker switching */
320 u8 has_speaker_switching;
321
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +0930322 /* support for talkback microphone */
323 u8 has_talkback;
324
Geoffrey D. Bennett904e6da2021-06-22 03:39:35 +0930325 /* the number of analogue inputs with a software switchable
326 * level control that can be set to line or instrument
327 */
328 u8 level_input_count;
329
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930330 /* the first input with a level control (0-based) */
331 u8 level_input_first;
332
Geoffrey D. Bennett904e6da2021-06-22 03:39:35 +0930333 /* the number of analogue inputs with a software switchable
334 * 10dB pad control
335 */
336 u8 pad_input_count;
337
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930338 /* the number of analogue inputs with a software switchable
339 * "air" control
340 */
341 u8 air_input_count;
342
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930343 /* the number of phantom (48V) software switchable controls */
344 u8 phantom_count;
345
346 /* the number of inputs each phantom switch controls */
347 u8 inputs_per_phantom;
348
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +0930349 /* the number of direct monitor options
350 * (0 = none, 1 = mono only, 2 = mono/stereo)
351 */
352 u8 direct_monitor;
353
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +0930354 /* remap analogue outputs; 18i8 Gen 3 has "line 3/4" connected
355 * internally to the analogue 7/8 outputs
356 */
357 u8 line_out_remap_enable;
358 u8 line_out_remap[SCARLETT2_ANALOGUE_MAX];
359
Geoffrey D. Bennett904e6da2021-06-22 03:39:35 +0930360 /* additional description for the line out volume controls */
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930361 const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX];
Geoffrey D. Bennett904e6da2021-06-22 03:39:35 +0930362
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +0930363 /* number of sources/destinations of each port type */
364 const int port_count[SCARLETT2_PORT_TYPE_COUNT][SCARLETT2_PORT_DIRNS];
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +0930365
366 /* layout/order of the entries in the set_mux message */
367 struct scarlett2_mux_entry mux_assignment[SCARLETT2_MUX_TABLES]
368 [SCARLETT2_MAX_MUX_ENTRIES];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930369};
370
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +0930371struct scarlett2_data {
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930372 struct usb_mixer_interface *mixer;
373 struct mutex usb_mutex; /* prevent sending concurrent USB requests */
374 struct mutex data_mutex; /* lock access to this data */
375 struct delayed_work work;
376 const struct scarlett2_device_info *info;
Geoffrey D. Bennett6c0a2072021-06-21 02:16:52 +0930377 __u8 bInterfaceNumber;
378 __u8 bEndpointAddress;
379 __u16 wMaxPacketSize;
380 __u8 bInterval;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930381 int num_mux_srcs;
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +0930382 int num_mux_dsts;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930383 u16 scarlett2_seq;
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +0930384 u8 sync_updated;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930385 u8 vol_updated;
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +0930386 u8 input_other_updated;
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +0930387 u8 monitor_other_updated;
Geoffrey D. Bennett8df25eb2021-06-23 02:33:50 +0930388 u8 mux_updated;
Geoffrey D. Bennette914d842021-06-23 02:33:58 +0930389 u8 speaker_switching_switched;
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +0930390 u8 sync;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930391 u8 master_vol;
392 u8 vol[SCARLETT2_ANALOGUE_MAX];
393 u8 vol_sw_hw_switch[SCARLETT2_ANALOGUE_MAX];
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +0930394 u8 mute_switch[SCARLETT2_ANALOGUE_MAX];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930395 u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX];
396 u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX];
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +0930397 u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT];
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930398 u8 air_switch[SCARLETT2_AIR_SWITCH_MAX];
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930399 u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX];
400 u8 phantom_persistence;
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +0930401 u8 direct_monitor_switch;
Geoffrey D. Bennette914d842021-06-23 02:33:58 +0930402 u8 speaker_switching_switch;
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +0930403 u8 talkback_switch;
404 u8 talkback_map[SCARLETT2_OUTPUT_MIX_MAX];
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930405 u8 msd_switch;
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +0930406 struct snd_kcontrol *sync_ctl;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930407 struct snd_kcontrol *master_vol_ctl;
408 struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX];
Geoffrey D. Bennettf02da652021-06-23 02:33:45 +0930409 struct snd_kcontrol *sw_hw_ctls[SCARLETT2_ANALOGUE_MAX];
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +0930410 struct snd_kcontrol *mute_ctls[SCARLETT2_ANALOGUE_MAX];
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +0930411 struct snd_kcontrol *dim_mute_ctls[SCARLETT2_DIM_MUTE_COUNT];
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +0930412 struct snd_kcontrol *level_ctls[SCARLETT2_LEVEL_SWITCH_MAX];
413 struct snd_kcontrol *pad_ctls[SCARLETT2_PAD_SWITCH_MAX];
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930414 struct snd_kcontrol *air_ctls[SCARLETT2_AIR_SWITCH_MAX];
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930415 struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX];
Geoffrey D. Bennettf02da652021-06-23 02:33:45 +0930416 struct snd_kcontrol *mux_ctls[SCARLETT2_MUX_MAX];
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +0930417 struct snd_kcontrol *direct_monitor_ctl;
Geoffrey D. Bennette914d842021-06-23 02:33:58 +0930418 struct snd_kcontrol *speaker_switching_ctl;
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +0930419 struct snd_kcontrol *talkback_ctl;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930420 u8 mux[SCARLETT2_MUX_MAX];
421 u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX];
422};
423
424/*** Model-specific data ***/
425
426static const struct scarlett2_device_info s6i6_gen2_info = {
Geoffrey D. Bennettd92b9152021-06-22 03:39:31 +0930427 .usb_id = USB_ID(0x1235, 0x8203),
428
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930429 .has_mixer = 1,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930430 .level_input_count = 2,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930431 .pad_input_count = 2,
432
433 .line_out_descrs = {
Geoffrey D. Bennettc712c6c2021-06-22 03:39:18 +0930434 "Headphones 1 L",
435 "Headphones 1 R",
436 "Headphones 2 L",
437 "Headphones 2 R",
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930438 },
439
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +0930440 .port_count = {
441 [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
442 [SCARLETT2_PORT_TYPE_ANALOGUE] = { 4, 4 },
443 [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 },
444 [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 },
445 [SCARLETT2_PORT_TYPE_PCM] = { 6, 6 },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930446 },
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +0930447
448 .mux_assignment = { {
449 { SCARLETT2_PORT_TYPE_PCM, 0, 6 },
450 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
451 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
452 { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
453 { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
454 { 0, 0, 0 },
455 }, {
456 { SCARLETT2_PORT_TYPE_PCM, 0, 6 },
457 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
458 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
459 { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
460 { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
461 { 0, 0, 0 },
462 }, {
463 { SCARLETT2_PORT_TYPE_PCM, 0, 6 },
464 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
465 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
466 { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
467 { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
468 { 0, 0, 0 },
469 } },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930470};
471
472static const struct scarlett2_device_info s18i8_gen2_info = {
Geoffrey D. Bennettd92b9152021-06-22 03:39:31 +0930473 .usb_id = USB_ID(0x1235, 0x8204),
474
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930475 .has_mixer = 1,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930476 .level_input_count = 2,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930477 .pad_input_count = 4,
478
479 .line_out_descrs = {
480 "Monitor L",
481 "Monitor R",
482 "Headphones 1 L",
483 "Headphones 1 R",
484 "Headphones 2 L",
485 "Headphones 2 R",
486 },
487
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +0930488 .port_count = {
489 [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
490 [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 6 },
491 [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 },
492 [SCARLETT2_PORT_TYPE_ADAT] = { 8, 0 },
493 [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 },
494 [SCARLETT2_PORT_TYPE_PCM] = { 8, 18 },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930495 },
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +0930496
497 .mux_assignment = { {
498 { SCARLETT2_PORT_TYPE_PCM, 0, 18 },
499 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 },
500 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
501 { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
502 { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
503 { 0, 0, 0 },
504 }, {
505 { SCARLETT2_PORT_TYPE_PCM, 0, 14 },
506 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 },
507 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
508 { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
509 { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
510 { 0, 0, 0 },
511 }, {
512 { SCARLETT2_PORT_TYPE_PCM, 0, 10 },
513 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 },
514 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
515 { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
516 { SCARLETT2_PORT_TYPE_NONE, 0, 4 },
517 { 0, 0, 0 },
518 } },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930519};
520
521static const struct scarlett2_device_info s18i20_gen2_info = {
Geoffrey D. Bennettd92b9152021-06-22 03:39:31 +0930522 .usb_id = USB_ID(0x1235, 0x8201),
523
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930524 .has_mixer = 1,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930525 .line_out_hw_vol = 1,
526
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930527 .line_out_descrs = {
528 "Monitor L",
529 "Monitor R",
530 NULL,
531 NULL,
532 NULL,
533 NULL,
534 "Headphones 1 L",
535 "Headphones 1 R",
536 "Headphones 2 L",
537 "Headphones 2 R",
538 },
539
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +0930540 .port_count = {
541 [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
542 [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 10 },
543 [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 },
544 [SCARLETT2_PORT_TYPE_ADAT] = { 8, 8 },
545 [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 },
546 [SCARLETT2_PORT_TYPE_PCM] = { 20, 18 },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930547 },
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +0930548
549 .mux_assignment = { {
550 { SCARLETT2_PORT_TYPE_PCM, 0, 18 },
551 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
552 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
553 { SCARLETT2_PORT_TYPE_ADAT, 0, 8 },
554 { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
555 { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
556 { 0, 0, 0 },
557 }, {
558 { SCARLETT2_PORT_TYPE_PCM, 0, 14 },
559 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
560 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
561 { SCARLETT2_PORT_TYPE_ADAT, 0, 4 },
562 { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
563 { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
564 { 0, 0, 0 },
565 }, {
566 { SCARLETT2_PORT_TYPE_PCM, 0, 10 },
567 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
568 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
569 { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
570 { SCARLETT2_PORT_TYPE_NONE, 0, 6 },
571 { 0, 0, 0 },
572 } },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930573};
574
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930575static const struct scarlett2_device_info solo_gen3_info = {
576 .usb_id = USB_ID(0x1235, 0x8211),
577
578 .has_msd_mode = 1,
579 .level_input_count = 1,
580 .level_input_first = 1,
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930581 .air_input_count = 1,
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930582 .phantom_count = 1,
583 .inputs_per_phantom = 1,
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +0930584 .direct_monitor = 1,
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930585};
586
587static const struct scarlett2_device_info s2i2_gen3_info = {
588 .usb_id = USB_ID(0x1235, 0x8210),
589
590 .has_msd_mode = 1,
591 .level_input_count = 2,
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930592 .air_input_count = 2,
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930593 .phantom_count = 1,
594 .inputs_per_phantom = 2,
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +0930595 .direct_monitor = 2,
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930596};
597
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930598static const struct scarlett2_device_info s4i4_gen3_info = {
599 .usb_id = USB_ID(0x1235, 0x8212),
600
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930601 .has_msd_mode = 1,
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930602 .has_mixer = 1,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930603 .level_input_count = 2,
604 .pad_input_count = 2,
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930605 .air_input_count = 2,
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930606 .phantom_count = 1,
607 .inputs_per_phantom = 2,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930608
609 .line_out_descrs = {
610 "Monitor L",
611 "Monitor R",
612 "Headphones L",
613 "Headphones R",
614 },
615
616 .port_count = {
617 [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
618 [SCARLETT2_PORT_TYPE_ANALOGUE] = { 4, 4 },
619 [SCARLETT2_PORT_TYPE_MIX] = { 6, 8 },
620 [SCARLETT2_PORT_TYPE_PCM] = { 4, 6 },
621 },
622
623 .mux_assignment = { {
624 { SCARLETT2_PORT_TYPE_PCM, 0, 6 },
625 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
626 { SCARLETT2_PORT_TYPE_MIX, 0, 8 },
627 { SCARLETT2_PORT_TYPE_NONE, 0, 16 },
628 { 0, 0, 0 },
629 }, {
630 { SCARLETT2_PORT_TYPE_PCM, 0, 6 },
631 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
632 { SCARLETT2_PORT_TYPE_MIX, 0, 8 },
633 { SCARLETT2_PORT_TYPE_NONE, 0, 16 },
634 { 0, 0, 0 },
635 }, {
636 { SCARLETT2_PORT_TYPE_PCM, 0, 6 },
637 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
638 { SCARLETT2_PORT_TYPE_MIX, 0, 8 },
639 { SCARLETT2_PORT_TYPE_NONE, 0, 16 },
640 { 0, 0, 0 },
641 } },
642};
643
644static const struct scarlett2_device_info s8i6_gen3_info = {
645 .usb_id = USB_ID(0x1235, 0x8213),
646
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930647 .has_msd_mode = 1,
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930648 .has_mixer = 1,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930649 .level_input_count = 2,
650 .pad_input_count = 2,
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930651 .air_input_count = 2,
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930652 .phantom_count = 1,
653 .inputs_per_phantom = 2,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930654
655 .line_out_descrs = {
656 "Headphones 1 L",
657 "Headphones 1 R",
658 "Headphones 2 L",
659 "Headphones 2 R",
660 },
661
662 .port_count = {
663 [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
664 [SCARLETT2_PORT_TYPE_ANALOGUE] = { 6, 4 },
665 [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 },
666 [SCARLETT2_PORT_TYPE_MIX] = { 8, 8 },
667 [SCARLETT2_PORT_TYPE_PCM] = { 6, 10 },
668 },
669
670 .mux_assignment = { {
671 { SCARLETT2_PORT_TYPE_PCM, 0, 8 },
672 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
673 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
674 { SCARLETT2_PORT_TYPE_PCM, 8, 2 },
675 { SCARLETT2_PORT_TYPE_MIX, 0, 8 },
676 { SCARLETT2_PORT_TYPE_NONE, 0, 18 },
677 { 0, 0, 0 },
678 }, {
679 { SCARLETT2_PORT_TYPE_PCM, 0, 8 },
680 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
681 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
682 { SCARLETT2_PORT_TYPE_PCM, 8, 2 },
683 { SCARLETT2_PORT_TYPE_MIX, 0, 8 },
684 { SCARLETT2_PORT_TYPE_NONE, 0, 18 },
685 { 0, 0, 0 },
686 }, {
687 { SCARLETT2_PORT_TYPE_PCM, 0, 8 },
688 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
689 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
690 { SCARLETT2_PORT_TYPE_PCM, 8, 2 },
691 { SCARLETT2_PORT_TYPE_MIX, 0, 8 },
692 { SCARLETT2_PORT_TYPE_NONE, 0, 18 },
693 { 0, 0, 0 },
694 } },
695};
696
697static const struct scarlett2_device_info s18i8_gen3_info = {
698 .usb_id = USB_ID(0x1235, 0x8214),
699
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930700 .has_msd_mode = 1,
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930701 .has_mixer = 1,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930702 .line_out_hw_vol = 1,
Geoffrey D. Bennette914d842021-06-23 02:33:58 +0930703 .has_speaker_switching = 1,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930704 .level_input_count = 2,
Geoffrey D. Bennettfe9a23a2021-06-27 22:52:26 +0930705 .pad_input_count = 4,
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930706 .air_input_count = 4,
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930707 .phantom_count = 2,
708 .inputs_per_phantom = 2,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930709
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +0930710 .line_out_remap_enable = 1,
711 .line_out_remap = { 0, 1, 6, 7, 2, 3, 4, 5 },
712
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930713 .line_out_descrs = {
714 "Monitor L",
715 "Monitor R",
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +0930716 "Alt Monitor L",
717 "Alt Monitor R",
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930718 "Headphones 1 L",
719 "Headphones 1 R",
720 "Headphones 2 L",
721 "Headphones 2 R",
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930722 },
723
724 .port_count = {
725 [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
726 [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 8 },
727 [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 },
728 [SCARLETT2_PORT_TYPE_ADAT] = { 8, 0 },
729 [SCARLETT2_PORT_TYPE_MIX] = { 10, 20 },
730 [SCARLETT2_PORT_TYPE_PCM] = { 8, 20 },
731 },
732
733 .mux_assignment = { {
734 { SCARLETT2_PORT_TYPE_PCM, 0, 10 },
735 { SCARLETT2_PORT_TYPE_PCM, 12, 8 },
736 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 2 },
737 { SCARLETT2_PORT_TYPE_ANALOGUE, 6, 2 },
738 { SCARLETT2_PORT_TYPE_ANALOGUE, 2, 4 },
739 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
740 { SCARLETT2_PORT_TYPE_PCM, 10, 2 },
741 { SCARLETT2_PORT_TYPE_MIX, 0, 20 },
742 { SCARLETT2_PORT_TYPE_NONE, 0, 10 },
743 { 0, 0, 0 },
744 }, {
745 { SCARLETT2_PORT_TYPE_PCM, 0, 10 },
746 { SCARLETT2_PORT_TYPE_PCM, 12, 4 },
747 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 2 },
748 { SCARLETT2_PORT_TYPE_ANALOGUE, 6, 2 },
749 { SCARLETT2_PORT_TYPE_ANALOGUE, 2, 4 },
750 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
751 { SCARLETT2_PORT_TYPE_PCM, 10, 2 },
752 { SCARLETT2_PORT_TYPE_MIX, 0, 20 },
753 { SCARLETT2_PORT_TYPE_NONE, 0, 10 },
754 { 0, 0, 0 },
755 }, {
756 { SCARLETT2_PORT_TYPE_PCM, 0, 10 },
757 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 2 },
758 { SCARLETT2_PORT_TYPE_ANALOGUE, 6, 2 },
759 { SCARLETT2_PORT_TYPE_ANALOGUE, 2, 4 },
760 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
761 { SCARLETT2_PORT_TYPE_MIX, 0, 20 },
762 { SCARLETT2_PORT_TYPE_NONE, 0, 10 },
763 { 0, 0, 0 },
764 } },
765};
766
767static const struct scarlett2_device_info s18i20_gen3_info = {
768 .usb_id = USB_ID(0x1235, 0x8215),
769
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930770 .has_msd_mode = 1,
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930771 .has_mixer = 1,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930772 .line_out_hw_vol = 1,
Geoffrey D. Bennette914d842021-06-23 02:33:58 +0930773 .has_speaker_switching = 1,
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +0930774 .has_talkback = 1,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930775 .level_input_count = 2,
776 .pad_input_count = 8,
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930777 .air_input_count = 8,
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930778 .phantom_count = 2,
779 .inputs_per_phantom = 4,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930780
781 .line_out_descrs = {
782 "Monitor 1 L",
783 "Monitor 1 R",
784 "Monitor 2 L",
785 "Monitor 2 R",
786 NULL,
787 NULL,
788 "Headphones 1 L",
789 "Headphones 1 R",
790 "Headphones 2 L",
791 "Headphones 2 R",
792 },
793
794 .port_count = {
795 [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
796 [SCARLETT2_PORT_TYPE_ANALOGUE] = { 9, 10 },
797 [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 },
798 [SCARLETT2_PORT_TYPE_ADAT] = { 8, 8 },
799 [SCARLETT2_PORT_TYPE_MIX] = { 12, 25 },
800 [SCARLETT2_PORT_TYPE_PCM] = { 20, 20 },
801 },
802
803 .mux_assignment = { {
804 { SCARLETT2_PORT_TYPE_PCM, 0, 8 },
805 { SCARLETT2_PORT_TYPE_PCM, 10, 10 },
806 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
807 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
808 { SCARLETT2_PORT_TYPE_ADAT, 0, 8 },
809 { SCARLETT2_PORT_TYPE_PCM, 8, 2 },
810 { SCARLETT2_PORT_TYPE_MIX, 0, 25 },
811 { SCARLETT2_PORT_TYPE_NONE, 0, 12 },
812 { 0, 0, 0 },
813 }, {
814 { SCARLETT2_PORT_TYPE_PCM, 0, 8 },
815 { SCARLETT2_PORT_TYPE_PCM, 10, 8 },
816 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
817 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
818 { SCARLETT2_PORT_TYPE_ADAT, 0, 8 },
819 { SCARLETT2_PORT_TYPE_PCM, 8, 2 },
820 { SCARLETT2_PORT_TYPE_MIX, 0, 25 },
821 { SCARLETT2_PORT_TYPE_NONE, 0, 10 },
822 { 0, 0, 0 },
823 }, {
824 { SCARLETT2_PORT_TYPE_PCM, 0, 10 },
825 { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
826 { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
827 { SCARLETT2_PORT_TYPE_NONE, 0, 24 },
828 { 0, 0, 0 },
829 } },
830};
831
Geoffrey D. Bennettd92b9152021-06-22 03:39:31 +0930832static const struct scarlett2_device_info *scarlett2_devices[] = {
833 /* Supported Gen 2 devices */
834 &s6i6_gen2_info,
835 &s18i8_gen2_info,
836 &s18i20_gen2_info,
837
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930838 /* Supported Gen 3 devices */
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930839 &solo_gen3_info,
840 &s2i2_gen3_info,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +0930841 &s4i4_gen3_info,
842 &s8i6_gen3_info,
843 &s18i8_gen3_info,
844 &s18i20_gen3_info,
845
Geoffrey D. Bennettd92b9152021-06-22 03:39:31 +0930846 /* End of list */
847 NULL
848};
849
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930850/* get the starting port index number for a given port type/direction */
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +0930851static int scarlett2_get_port_start_num(
852 const int port_count[][SCARLETT2_PORT_DIRNS],
853 int direction, int port_type)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930854{
855 int i, num = 0;
856
857 for (i = 0; i < port_type; i++)
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +0930858 num += port_count[i][direction];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930859
860 return num;
861}
862
863/*** USB Interactions ***/
864
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +0930865/* Notifications from the interface */
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +0930866#define SCARLETT2_USB_NOTIFY_SYNC 0x00000008
867#define SCARLETT2_USB_NOTIFY_DIM_MUTE 0x00200000
868#define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000
869#define SCARLETT2_USB_NOTIFY_INPUT_OTHER 0x00800000
870#define SCARLETT2_USB_NOTIFY_MONITOR_OTHER 0x01000000
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930871
872/* Commands for sending/receiving requests/responses */
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +0930873#define SCARLETT2_USB_CMD_INIT 0
Geoffrey D. Bennett1f7fa6e2021-06-22 03:39:06 +0930874#define SCARLETT2_USB_CMD_REQ 2
875#define SCARLETT2_USB_CMD_RESP 3
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930876
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +0930877#define SCARLETT2_USB_INIT_1 0x00000000
878#define SCARLETT2_USB_INIT_2 0x00000002
Geoffrey D. Bennett06a21622021-06-21 02:16:28 +0930879#define SCARLETT2_USB_GET_METER 0x00001001
880#define SCARLETT2_USB_GET_MIX 0x00002001
881#define SCARLETT2_USB_SET_MIX 0x00002002
882#define SCARLETT2_USB_GET_MUX 0x00003001
883#define SCARLETT2_USB_SET_MUX 0x00003002
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +0930884#define SCARLETT2_USB_GET_SYNC 0x00006004
Geoffrey D. Bennett06a21622021-06-21 02:16:28 +0930885#define SCARLETT2_USB_GET_DATA 0x00800000
886#define SCARLETT2_USB_SET_DATA 0x00800001
887#define SCARLETT2_USB_DATA_CMD 0x00800002
888
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930889#define SCARLETT2_USB_CONFIG_SAVE 6
890
891#define SCARLETT2_USB_VOLUME_STATUS_OFFSET 0x31
892#define SCARLETT2_USB_METER_LEVELS_GET_MAGIC 1
893
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930894/* volume status is read together (matches scarlett2_config_items[1]) */
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930895struct scarlett2_usb_volume_status {
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +0930896 /* dim/mute buttons */
897 u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930898
899 u8 pad1;
900
901 /* software volume setting */
902 s16 sw_vol[SCARLETT2_ANALOGUE_MAX];
903
904 /* actual volume of output inc. dim (-18dB) */
905 s16 hw_vol[SCARLETT2_ANALOGUE_MAX];
906
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +0930907 /* internal mute buttons */
908 u8 mute_switch[SCARLETT2_ANALOGUE_MAX];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930909
910 /* sw (0) or hw (1) controlled */
911 u8 sw_hw_switch[SCARLETT2_ANALOGUE_MAX];
912
913 u8 pad3[6];
914
915 /* front panel volume knob */
916 s16 master_vol;
917} __packed;
918
919/* Configuration parameters that can be read and written */
920enum {
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +0930921 SCARLETT2_CONFIG_DIM_MUTE = 0,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930922 SCARLETT2_CONFIG_LINE_OUT_VOLUME = 1,
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +0930923 SCARLETT2_CONFIG_MUTE_SWITCH = 2,
924 SCARLETT2_CONFIG_SW_HW_SWITCH = 3,
925 SCARLETT2_CONFIG_LEVEL_SWITCH = 4,
926 SCARLETT2_CONFIG_PAD_SWITCH = 5,
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930927 SCARLETT2_CONFIG_MSD_SWITCH = 6,
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930928 SCARLETT2_CONFIG_AIR_SWITCH = 7,
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930929 SCARLETT2_CONFIG_PHANTOM_SWITCH = 8,
930 SCARLETT2_CONFIG_PHANTOM_PERSISTENCE = 9,
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +0930931 SCARLETT2_CONFIG_DIRECT_MONITOR = 10,
Geoffrey D. Bennette914d842021-06-23 02:33:58 +0930932 SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH = 11,
933 SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE = 12,
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +0930934 SCARLETT2_CONFIG_TALKBACK_MAP = 13,
935 SCARLETT2_CONFIG_COUNT = 14
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930936};
937
938/* Location, size, and activation command number for the configuration
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +0930939 * parameters. Size is in bits and may be 1, 8, or 16.
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930940 */
941struct scarlett2_config {
942 u8 offset;
943 u8 size;
944 u8 activate;
945};
946
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930947/* scarlett2_config_items[0] is for devices without a mixer
948 * scarlett2_config_items[1] is for devices with a mixer
949 */
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930950static const struct scarlett2_config
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930951 scarlett2_config_items[2][SCARLETT2_CONFIG_COUNT] =
952
953/* Devices without a mixer (Solo and 2i2 Gen 3) */
954{ {
955 [SCARLETT2_CONFIG_MSD_SWITCH] = {
956 .offset = 0x04, .size = 8, .activate = 6 },
957
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930958 [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = {
959 .offset = 0x05, .size = 8, .activate = 6 },
960
961 [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
962 .offset = 0x06, .size = 8, .activate = 3 },
963
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +0930964 [SCARLETT2_CONFIG_DIRECT_MONITOR] = {
965 .offset = 0x07, .size = 8, .activate = 4 },
966
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930967 [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
968 .offset = 0x08, .size = 1, .activate = 7 },
969
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930970 [SCARLETT2_CONFIG_AIR_SWITCH] = {
971 .offset = 0x09, .size = 1, .activate = 8 },
972
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +0930973/* Devices with a mixer (Gen 2 and all other Gen 3) */
974}, {
Geoffrey D. Bennett76cb6802021-06-22 03:39:29 +0930975 [SCARLETT2_CONFIG_DIM_MUTE] = {
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +0930976 .offset = 0x31, .size = 8, .activate = 2 },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930977
Geoffrey D. Bennett76cb6802021-06-22 03:39:29 +0930978 [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +0930979 .offset = 0x34, .size = 16, .activate = 1 },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930980
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +0930981 [SCARLETT2_CONFIG_MUTE_SWITCH] = {
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +0930982 .offset = 0x5c, .size = 8, .activate = 1 },
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +0930983
Geoffrey D. Bennett76cb6802021-06-22 03:39:29 +0930984 [SCARLETT2_CONFIG_SW_HW_SWITCH] = {
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +0930985 .offset = 0x66, .size = 8, .activate = 3 },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930986
Geoffrey D. Bennett76cb6802021-06-22 03:39:29 +0930987 [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +0930988 .offset = 0x7c, .size = 8, .activate = 7 },
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +0930989
Geoffrey D. Bennett76cb6802021-06-22 03:39:29 +0930990 [SCARLETT2_CONFIG_PAD_SWITCH] = {
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +0930991 .offset = 0x84, .size = 8, .activate = 8 },
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930992
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +0930993 [SCARLETT2_CONFIG_AIR_SWITCH] = {
994 .offset = 0x8c, .size = 8, .activate = 8 },
995
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +0930996 [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
997 .offset = 0x9c, .size = 1, .activate = 8 },
998
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +0930999 [SCARLETT2_CONFIG_MSD_SWITCH] = {
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301000 .offset = 0x9d, .size = 8, .activate = 6 },
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +09301001
1002 [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = {
1003 .offset = 0x9e, .size = 8, .activate = 6 },
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09301004
1005 [SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH] = {
1006 .offset = 0x9f, .size = 1, .activate = 10 },
1007
1008 [SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE] = {
1009 .offset = 0xa0, .size = 1, .activate = 10 },
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09301010
1011 [SCARLETT2_CONFIG_TALKBACK_MAP] = {
1012 .offset = 0xb0, .size = 16, .activate = 10 },
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09301013} };
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301014
1015/* proprietary request/response format */
1016struct scarlett2_usb_packet {
Takashi Iwaid8f48932020-02-01 09:05:29 +01001017 __le32 cmd;
1018 __le16 size;
1019 __le16 seq;
1020 __le32 error;
1021 __le32 pad;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301022 u8 data[];
1023};
1024
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301025static void scarlett2_fill_request_header(struct scarlett2_data *private,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301026 struct scarlett2_usb_packet *req,
1027 u32 cmd, u16 req_size)
1028{
1029 /* sequence must go up by 1 for each request */
1030 u16 seq = private->scarlett2_seq++;
1031
1032 req->cmd = cpu_to_le32(cmd);
1033 req->size = cpu_to_le16(req_size);
1034 req->seq = cpu_to_le16(seq);
1035 req->error = 0;
1036 req->pad = 0;
1037}
1038
Geoffrey D. Bennett1f7fa6e2021-06-22 03:39:06 +09301039static int scarlett2_usb_tx(struct usb_device *dev, int interface,
1040 void *buf, u16 size)
1041{
1042 return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1043 SCARLETT2_USB_CMD_REQ,
1044 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
1045 0, interface, buf, size);
1046}
1047
1048static int scarlett2_usb_rx(struct usb_device *dev, int interface,
1049 u32 usb_req, void *buf, u16 size)
1050{
1051 return snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
1052 usb_req,
1053 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
1054 0, interface, buf, size);
1055}
1056
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301057/* Send a proprietary format request to the Scarlett interface */
1058static int scarlett2_usb(
1059 struct usb_mixer_interface *mixer, u32 cmd,
1060 void *req_data, u16 req_size, void *resp_data, u16 resp_size)
1061{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301062 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett1f7fa6e2021-06-22 03:39:06 +09301063 struct usb_device *dev = mixer->chip->dev;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301064 u16 req_buf_size = sizeof(struct scarlett2_usb_packet) + req_size;
1065 u16 resp_buf_size = sizeof(struct scarlett2_usb_packet) + resp_size;
Geoffrey D. Bennettb677b6c2021-06-21 02:16:30 +09301066 struct scarlett2_usb_packet *req, *resp = NULL;
1067 int err;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301068
1069 req = kmalloc(req_buf_size, GFP_KERNEL);
1070 if (!req) {
1071 err = -ENOMEM;
1072 goto error;
1073 }
1074
1075 resp = kmalloc(resp_buf_size, GFP_KERNEL);
1076 if (!resp) {
1077 err = -ENOMEM;
1078 goto error;
1079 }
1080
1081 mutex_lock(&private->usb_mutex);
1082
1083 /* build request message and send it */
1084
1085 scarlett2_fill_request_header(private, req, cmd, req_size);
1086
1087 if (req_size)
1088 memcpy(req->data, req_data, req_size);
1089
Geoffrey D. Bennett1f7fa6e2021-06-22 03:39:06 +09301090 err = scarlett2_usb_tx(dev, private->bInterfaceNumber,
1091 req, req_buf_size);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301092
1093 if (err != req_buf_size) {
1094 usb_audio_err(
1095 mixer->chip,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +09301096 "Scarlett Gen 2/3 USB request result cmd %x was %d\n",
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301097 cmd, err);
1098 err = -EINVAL;
1099 goto unlock;
1100 }
1101
1102 /* send a second message to get the response */
1103
Geoffrey D. Bennett1f7fa6e2021-06-22 03:39:06 +09301104 err = scarlett2_usb_rx(dev, private->bInterfaceNumber,
1105 SCARLETT2_USB_CMD_RESP,
1106 resp, resp_buf_size);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301107
1108 /* validate the response */
1109
1110 if (err != resp_buf_size) {
1111 usb_audio_err(
1112 mixer->chip,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +09301113 "Scarlett Gen 2/3 USB response result cmd %x was %d "
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +09301114 "expected %d\n",
1115 cmd, err, resp_buf_size);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301116 err = -EINVAL;
1117 goto unlock;
1118 }
1119
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +09301120 /* cmd/seq/size should match except when initialising
1121 * seq sent = 1, response = 0
1122 */
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301123 if (resp->cmd != req->cmd ||
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +09301124 (resp->seq != req->seq &&
1125 (le16_to_cpu(req->seq) != 1 || resp->seq != 0)) ||
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301126 resp_size != le16_to_cpu(resp->size) ||
1127 resp->error ||
1128 resp->pad) {
1129 usb_audio_err(
1130 mixer->chip,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +09301131 "Scarlett Gen 2/3 USB invalid response; "
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301132 "cmd tx/rx %d/%d seq %d/%d size %d/%d "
1133 "error %d pad %d\n",
Takashi Iwaid8f48932020-02-01 09:05:29 +01001134 le32_to_cpu(req->cmd), le32_to_cpu(resp->cmd),
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301135 le16_to_cpu(req->seq), le16_to_cpu(resp->seq),
1136 resp_size, le16_to_cpu(resp->size),
Takashi Iwaid8f48932020-02-01 09:05:29 +01001137 le32_to_cpu(resp->error),
1138 le32_to_cpu(resp->pad));
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301139 err = -EINVAL;
1140 goto unlock;
1141 }
1142
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +09301143 if (resp_data && resp_size > 0)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301144 memcpy(resp_data, resp->data, resp_size);
1145
1146unlock:
1147 mutex_unlock(&private->usb_mutex);
1148error:
1149 kfree(req);
1150 kfree(resp);
1151 return err;
1152}
1153
Geoffrey D. Bennett8aea2e32021-06-23 02:32:09 +09301154/* Send a USB message to get data; result placed in *buf */
1155static int scarlett2_usb_get(
1156 struct usb_mixer_interface *mixer,
1157 int offset, void *buf, int size)
1158{
1159 struct {
1160 __le32 offset;
1161 __le32 size;
1162 } __packed req;
1163
1164 req.offset = cpu_to_le32(offset);
1165 req.size = cpu_to_le32(size);
1166 return scarlett2_usb(mixer, SCARLETT2_USB_GET_DATA,
1167 &req, sizeof(req), buf, size);
1168}
1169
1170/* Send a USB message to get configuration parameters; result placed in *buf */
1171static int scarlett2_usb_get_config(
1172 struct usb_mixer_interface *mixer,
1173 int config_item_num, int count, void *buf)
1174{
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09301175 struct scarlett2_data *private = mixer->private_data;
1176 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennett8aea2e32021-06-23 02:32:09 +09301177 const struct scarlett2_config *config_item =
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09301178 &scarlett2_config_items[info->has_mixer][config_item_num];
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301179 int size, err, i;
Nathan Chancellor9a7b7ec2021-06-26 22:12:03 -07001180 u8 *buf_8;
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301181 u8 value;
Geoffrey D. Bennett8aea2e32021-06-23 02:32:09 +09301182
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301183 /* For byte-sized parameters, retrieve directly into buf */
1184 if (config_item->size >= 8) {
1185 size = config_item->size / 8 * count;
Geoffrey D. Bennettac34df72021-06-23 02:34:09 +09301186 err = scarlett2_usb_get(mixer, config_item->offset, buf, size);
1187 if (err < 0)
1188 return err;
Nathan Chancellor9a7b7ec2021-06-26 22:12:03 -07001189 if (size == 2) {
1190 u16 *buf_16 = buf;
1191
1192 for (i = 0; i < count; i++, buf_16++)
1193 *buf_16 = le16_to_cpu(*(__le16 *)buf_16);
1194 }
Geoffrey D. Bennettac34df72021-06-23 02:34:09 +09301195 return 0;
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301196 }
1197
1198 /* For bit-sized parameters, retrieve into value */
1199 err = scarlett2_usb_get(mixer, config_item->offset, &value, 1);
1200 if (err < 0)
1201 return err;
1202
1203 /* then unpack from value into buf[] */
Nathan Chancellor9a7b7ec2021-06-26 22:12:03 -07001204 buf_8 = buf;
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301205 for (i = 0; i < 8 && i < count; i++, value >>= 1)
Nathan Chancellor9a7b7ec2021-06-26 22:12:03 -07001206 *buf_8++ = value & 1;
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301207
1208 return 0;
Geoffrey D. Bennett8aea2e32021-06-23 02:32:09 +09301209}
1210
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301211/* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */
1212static void scarlett2_config_save(struct usb_mixer_interface *mixer)
1213{
Takashi Iwaid8f48932020-02-01 09:05:29 +01001214 __le32 req = cpu_to_le32(SCARLETT2_USB_CONFIG_SAVE);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301215
1216 scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD,
1217 &req, sizeof(u32),
1218 NULL, 0);
1219}
1220
1221/* Delayed work to save config */
1222static void scarlett2_config_save_work(struct work_struct *work)
1223{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301224 struct scarlett2_data *private =
1225 container_of(work, struct scarlett2_data, work.work);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301226
1227 scarlett2_config_save(private->mixer);
1228}
1229
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +09301230/* Send a USB message to set a SCARLETT2_CONFIG_* parameter */
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301231static int scarlett2_usb_set_config(
1232 struct usb_mixer_interface *mixer,
1233 int config_item_num, int index, int value)
1234{
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09301235 struct scarlett2_data *private = mixer->private_data;
1236 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennett29672632021-06-21 02:16:48 +09301237 const struct scarlett2_config *config_item =
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09301238 &scarlett2_config_items[info->has_mixer][config_item_num];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301239 struct {
Takashi Iwaid8f48932020-02-01 09:05:29 +01001240 __le32 offset;
1241 __le32 bytes;
1242 __le32 value;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301243 } __packed req;
Takashi Iwaid8f48932020-02-01 09:05:29 +01001244 __le32 req2;
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301245 int offset, size;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301246 int err;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301247
1248 /* Cancel any pending NVRAM save */
1249 cancel_delayed_work_sync(&private->work);
1250
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301251 /* Convert config_item->size in bits to size in bytes and
1252 * calculate offset
1253 */
1254 if (config_item->size >= 8) {
1255 size = config_item->size / 8;
1256 offset = config_item->offset + index * size;
1257
1258 /* If updating a bit, retrieve the old value, set/clear the
1259 * bit as needed, and update value
1260 */
1261 } else {
1262 u8 tmp;
1263
1264 size = 1;
1265 offset = config_item->offset;
1266
1267 scarlett2_usb_get(mixer, offset, &tmp, 1);
1268 if (value)
1269 tmp |= (1 << index);
1270 else
1271 tmp &= ~(1 << index);
1272
1273 value = tmp;
1274 }
1275
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301276 /* Send the configuration parameter data */
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301277 req.offset = cpu_to_le32(offset);
1278 req.bytes = cpu_to_le32(size);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301279 req.value = cpu_to_le32(value);
1280 err = scarlett2_usb(mixer, SCARLETT2_USB_SET_DATA,
Geoffrey D. Bennett9e15fae2021-06-23 02:32:25 +09301281 &req, sizeof(u32) * 2 + size,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301282 NULL, 0);
1283 if (err < 0)
1284 return err;
1285
1286 /* Activate the change */
Geoffrey D. Bennett29672632021-06-21 02:16:48 +09301287 req2 = cpu_to_le32(config_item->activate);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301288 err = scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD,
1289 &req2, sizeof(req2), NULL, 0);
1290 if (err < 0)
1291 return err;
1292
1293 /* Schedule the change to be written to NVRAM */
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +09301294 if (config_item->activate != SCARLETT2_USB_CONFIG_SAVE)
1295 schedule_delayed_work(&private->work, msecs_to_jiffies(2000));
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301296
1297 return 0;
1298}
1299
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +09301300/* Send a USB message to get sync status; result placed in *sync */
1301static int scarlett2_usb_get_sync_status(
1302 struct usb_mixer_interface *mixer,
1303 u8 *sync)
1304{
1305 __le32 data;
1306 int err;
1307
1308 err = scarlett2_usb(mixer, SCARLETT2_USB_GET_SYNC,
1309 NULL, 0, &data, sizeof(data));
1310 if (err < 0)
1311 return err;
1312
1313 *sync = !!data;
1314 return 0;
1315}
1316
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301317/* Send a USB message to get volume status; result placed in *buf */
1318static int scarlett2_usb_get_volume_status(
1319 struct usb_mixer_interface *mixer,
1320 struct scarlett2_usb_volume_status *buf)
1321{
1322 return scarlett2_usb_get(mixer, SCARLETT2_USB_VOLUME_STATUS_OFFSET,
1323 buf, sizeof(*buf));
1324}
1325
Geoffrey D. Bennett2661f032021-06-08 04:43:25 +09301326/* Send a USB message to get the volumes for all inputs of one mix
1327 * and put the values into private->mix[]
1328 */
1329static int scarlett2_usb_get_mix(struct usb_mixer_interface *mixer,
1330 int mix_num)
1331{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301332 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett2661f032021-06-08 04:43:25 +09301333 const struct scarlett2_device_info *info = private->info;
1334
1335 int num_mixer_in =
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301336 info->port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett2661f032021-06-08 04:43:25 +09301337 int err, i, j, k;
1338
1339 struct {
1340 __le16 mix_num;
1341 __le16 count;
1342 } __packed req;
1343
1344 __le16 data[SCARLETT2_INPUT_MIX_MAX];
1345
1346 req.mix_num = cpu_to_le16(mix_num);
1347 req.count = cpu_to_le16(num_mixer_in);
1348
1349 err = scarlett2_usb(mixer, SCARLETT2_USB_GET_MIX,
1350 &req, sizeof(req),
1351 data, num_mixer_in * sizeof(u16));
1352 if (err < 0)
1353 return err;
1354
1355 for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++) {
1356 u16 mixer_value = le16_to_cpu(data[i]);
1357
1358 for (k = 0; k < SCARLETT2_MIXER_VALUE_COUNT; k++)
1359 if (scarlett2_mixer_values[k] >= mixer_value)
1360 break;
1361 if (k == SCARLETT2_MIXER_VALUE_COUNT)
1362 k = SCARLETT2_MIXER_MAX_VALUE;
1363 private->mix[j] = k;
1364 }
1365
1366 return 0;
1367}
1368
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301369/* Send a USB message to set the volumes for all inputs of one mix
1370 * (values obtained from private->mix[])
1371 */
1372static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer,
Geoffrey D. Bennett06a21622021-06-21 02:16:28 +09301373 int mix_num)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301374{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301375 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301376 const struct scarlett2_device_info *info = private->info;
1377
1378 struct {
Takashi Iwaid8f48932020-02-01 09:05:29 +01001379 __le16 mix_num;
1380 __le16 data[SCARLETT2_INPUT_MIX_MAX];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301381 } __packed req;
1382
1383 int i, j;
1384 int num_mixer_in =
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301385 info->port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301386
1387 req.mix_num = cpu_to_le16(mix_num);
1388
1389 for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++)
1390 req.data[i] = cpu_to_le16(
1391 scarlett2_mixer_values[private->mix[j]]
1392 );
1393
1394 return scarlett2_usb(mixer, SCARLETT2_USB_SET_MIX,
1395 &req, (num_mixer_in + 1) * sizeof(u16),
1396 NULL, 0);
1397}
1398
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301399/* Convert a port number index (per info->port_count) to a hardware ID */
1400static u32 scarlett2_mux_src_num_to_id(
1401 const int port_count[][SCARLETT2_PORT_DIRNS], int num)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301402{
1403 int port_type;
1404
1405 for (port_type = 0;
1406 port_type < SCARLETT2_PORT_TYPE_COUNT;
1407 port_type++) {
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301408 if (num < port_count[port_type][SCARLETT2_PORT_IN])
1409 return scarlett2_ports[port_type].id | num;
1410 num -= port_count[port_type][SCARLETT2_PORT_IN];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301411 }
1412
1413 /* Oops */
1414 return 0;
1415}
1416
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301417/* Convert a hardware ID to a port number index */
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301418static u32 scarlett2_mux_id_to_num(
1419 const int port_count[][SCARLETT2_PORT_DIRNS], int direction, u32 id)
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301420{
1421 int port_type;
1422 int port_num = 0;
1423
1424 for (port_type = 0;
1425 port_type < SCARLETT2_PORT_TYPE_COUNT;
1426 port_type++) {
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301427 int base = scarlett2_ports[port_type].id;
1428 int count = port_count[port_type][direction];
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301429
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301430 if (id >= base && id < base + count)
1431 return port_num + id - base;
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301432 port_num += count;
1433 }
1434
1435 /* Oops */
1436 return -1;
1437}
1438
1439/* Convert one mux entry from the interface and load into private->mux[] */
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301440static void scarlett2_usb_populate_mux(struct scarlett2_data *private,
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301441 u32 mux_entry)
1442{
1443 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301444 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301445
1446 int dst_idx, src_idx;
1447
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301448 dst_idx = scarlett2_mux_id_to_num(port_count, SCARLETT2_PORT_OUT,
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301449 mux_entry & 0xFFF);
1450 if (dst_idx < 0)
1451 return;
1452
1453 if (dst_idx >= private->num_mux_dsts) {
1454 usb_audio_err(private->mixer->chip,
1455 "BUG: scarlett2_mux_id_to_num(%06x, OUT): %d >= %d",
1456 mux_entry, dst_idx, private->num_mux_dsts);
1457 return;
1458 }
1459
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301460 src_idx = scarlett2_mux_id_to_num(port_count, SCARLETT2_PORT_IN,
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301461 mux_entry >> 12);
1462 if (src_idx < 0)
1463 return;
1464
1465 if (src_idx >= private->num_mux_srcs) {
1466 usb_audio_err(private->mixer->chip,
1467 "BUG: scarlett2_mux_id_to_num(%06x, IN): %d >= %d",
1468 mux_entry, src_idx, private->num_mux_srcs);
1469 return;
1470 }
1471
1472 private->mux[dst_idx] = src_idx;
1473}
1474
1475/* Send USB message to get mux inputs and then populate private->mux[] */
1476static int scarlett2_usb_get_mux(struct usb_mixer_interface *mixer)
1477{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301478 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301479 int count = private->num_mux_dsts;
1480 int err, i;
1481
1482 struct {
1483 __le16 num;
1484 __le16 count;
1485 } __packed req;
1486
1487 __le32 data[SCARLETT2_MUX_MAX];
1488
Geoffrey D. Bennett8df25eb2021-06-23 02:33:50 +09301489 private->mux_updated = 0;
1490
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09301491 req.num = 0;
1492 req.count = cpu_to_le16(count);
1493
1494 err = scarlett2_usb(mixer, SCARLETT2_USB_GET_MUX,
1495 &req, sizeof(req),
1496 data, count * sizeof(u32));
1497 if (err < 0)
1498 return err;
1499
1500 for (i = 0; i < count; i++)
1501 scarlett2_usb_populate_mux(private, le32_to_cpu(data[i]));
1502
1503 return 0;
1504}
1505
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301506/* Send USB messages to set mux inputs */
1507static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer)
1508{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301509 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301510 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301511 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +09301512 int table;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301513
1514 struct {
Takashi Iwaid8f48932020-02-01 09:05:29 +01001515 __le16 pad;
1516 __le16 num;
1517 __le32 data[SCARLETT2_MUX_MAX];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301518 } __packed req;
1519
1520 req.pad = 0;
1521
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +09301522 /* set mux settings for each rate */
1523 for (table = 0; table < SCARLETT2_MUX_TABLES; table++) {
1524 const struct scarlett2_mux_entry *entry;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301525
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +09301526 /* i counts over the output array */
1527 int i = 0, err;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301528
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +09301529 req.num = cpu_to_le16(table);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301530
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +09301531 /* loop through each entry */
1532 for (entry = info->mux_assignment[table];
1533 entry->count;
1534 entry++) {
1535 int j;
1536 int port_type = entry->port_type;
1537 int port_idx = entry->start;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301538 int mux_idx = scarlett2_get_port_start_num(port_count,
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +09301539 SCARLETT2_PORT_OUT, port_type) + port_idx;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301540 int dst_id = scarlett2_ports[port_type].id + port_idx;
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +09301541
1542 /* Empty slots */
1543 if (!dst_id) {
1544 for (j = 0; j < entry->count; j++)
1545 req.data[i++] = 0;
1546 continue;
1547 }
1548
1549 /* Non-empty mux slots use the lower 12 bits
1550 * for the destination and next 12 bits for
1551 * the source
1552 */
1553 for (j = 0; j < entry->count; j++) {
1554 int src_id = scarlett2_mux_src_num_to_id(
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301555 port_count, private->mux[mux_idx++]);
Geoffrey D. Bennett6522c362021-06-22 03:39:41 +09301556 req.data[i++] = cpu_to_le32(dst_id |
1557 src_id << 12);
1558 dst_id++;
1559 }
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301560 }
1561
1562 err = scarlett2_usb(mixer, SCARLETT2_USB_SET_MUX,
1563 &req, (i + 1) * sizeof(u32),
1564 NULL, 0);
1565 if (err < 0)
1566 return err;
1567 }
1568
1569 return 0;
1570}
1571
1572/* Send USB message to get meter levels */
1573static int scarlett2_usb_get_meter_levels(struct usb_mixer_interface *mixer,
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +09301574 u16 num_meters, u16 *levels)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301575{
1576 struct {
Takashi Iwaid8f48932020-02-01 09:05:29 +01001577 __le16 pad;
1578 __le16 num_meters;
1579 __le32 magic;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301580 } __packed req;
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +09301581 u32 resp[SCARLETT2_MAX_METERS];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301582 int i, err;
1583
1584 req.pad = 0;
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +09301585 req.num_meters = cpu_to_le16(num_meters);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301586 req.magic = cpu_to_le32(SCARLETT2_USB_METER_LEVELS_GET_MAGIC);
Geoffrey D. Bennett06a21622021-06-21 02:16:28 +09301587 err = scarlett2_usb(mixer, SCARLETT2_USB_GET_METER,
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +09301588 &req, sizeof(req), resp, num_meters * sizeof(u32));
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301589 if (err < 0)
1590 return err;
1591
1592 /* copy, convert to u16 */
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +09301593 for (i = 0; i < num_meters; i++)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301594 levels[i] = resp[i];
1595
1596 return 0;
1597}
1598
1599/*** Control Functions ***/
1600
1601/* helper function to create a new control */
1602static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer,
1603 const struct snd_kcontrol_new *ncontrol,
1604 int index, int channels, const char *name,
1605 struct snd_kcontrol **kctl_return)
1606{
1607 struct snd_kcontrol *kctl;
1608 struct usb_mixer_elem_info *elem;
1609 int err;
1610
1611 elem = kzalloc(sizeof(*elem), GFP_KERNEL);
1612 if (!elem)
1613 return -ENOMEM;
1614
Takashi Iwai785b6f292021-06-23 02:30:49 +09301615 /* We set USB_MIXER_BESPOKEN type, so that the core USB mixer code
1616 * ignores them for resume and other operations.
1617 * Also, the head.id field is set to 0, as we don't use this field.
1618 */
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301619 elem->head.mixer = mixer;
1620 elem->control = index;
Takashi Iwai785b6f292021-06-23 02:30:49 +09301621 elem->head.id = 0;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301622 elem->channels = channels;
Takashi Iwai785b6f292021-06-23 02:30:49 +09301623 elem->val_type = USB_MIXER_BESPOKEN;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301624
1625 kctl = snd_ctl_new1(ncontrol, elem);
1626 if (!kctl) {
1627 kfree(elem);
1628 return -ENOMEM;
1629 }
1630 kctl->private_free = snd_usb_mixer_elem_free;
1631
Joe Perches75b1a8f2021-01-04 09:17:34 -08001632 strscpy(kctl->id.name, name, sizeof(kctl->id.name));
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301633
1634 err = snd_usb_mixer_add_control(&elem->head, kctl);
1635 if (err < 0)
1636 return err;
1637
1638 if (kctl_return)
1639 *kctl_return = kctl;
1640
1641 return 0;
1642}
1643
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +09301644/*** Sync Control ***/
1645
1646/* Update sync control after receiving notification that the status
1647 * has changed
1648 */
1649static int scarlett2_update_sync(struct usb_mixer_interface *mixer)
1650{
1651 struct scarlett2_data *private = mixer->private_data;
1652
1653 private->sync_updated = 0;
1654 return scarlett2_usb_get_sync_status(mixer, &private->sync);
1655}
1656
1657static int scarlett2_sync_ctl_info(struct snd_kcontrol *kctl,
1658 struct snd_ctl_elem_info *uinfo)
1659{
1660 static const char *texts[2] = {
1661 "Unlocked", "Locked"
1662 };
1663 return snd_ctl_enum_info(uinfo, 1, 2, texts);
1664}
1665
1666static int scarlett2_sync_ctl_get(struct snd_kcontrol *kctl,
1667 struct snd_ctl_elem_value *ucontrol)
1668{
1669 struct usb_mixer_elem_info *elem = kctl->private_data;
1670 struct usb_mixer_interface *mixer = elem->head.mixer;
1671 struct scarlett2_data *private = mixer->private_data;
1672
1673 mutex_lock(&private->data_mutex);
1674 if (private->sync_updated)
1675 scarlett2_update_sync(mixer);
1676 ucontrol->value.enumerated.item[0] = private->sync;
1677 mutex_unlock(&private->data_mutex);
1678
1679 return 0;
1680}
1681
1682static const struct snd_kcontrol_new scarlett2_sync_ctl = {
1683 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1684 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1685 .name = "",
1686 .info = scarlett2_sync_ctl_info,
1687 .get = scarlett2_sync_ctl_get
1688};
1689
1690static int scarlett2_add_sync_ctl(struct usb_mixer_interface *mixer)
1691{
1692 struct scarlett2_data *private = mixer->private_data;
1693
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09301694 /* devices without a mixer also don't support reporting sync status */
1695 if (!private->info->has_mixer)
1696 return 0;
1697
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +09301698 return scarlett2_add_new_ctl(mixer, &scarlett2_sync_ctl,
1699 0, 1, "Sync Status", &private->sync_ctl);
1700}
1701
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301702/*** Analogue Line Out Volume Controls ***/
1703
1704/* Update hardware volume controls after receiving notification that
1705 * they have changed
1706 */
1707static int scarlett2_update_volumes(struct usb_mixer_interface *mixer)
1708{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301709 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett03bdbcf2021-06-21 02:16:34 +09301710 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301711 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301712 struct scarlett2_usb_volume_status volume_status;
1713 int num_line_out =
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09301714 port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301715 int err, i;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301716 int mute;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301717
1718 private->vol_updated = 0;
1719
1720 err = scarlett2_usb_get_volume_status(mixer, &volume_status);
1721 if (err < 0)
1722 return err;
1723
1724 private->master_vol = clamp(
1725 volume_status.master_vol + SCARLETT2_VOLUME_BIAS,
1726 0, SCARLETT2_VOLUME_BIAS);
1727
Geoffrey D. Bennett03bdbcf2021-06-21 02:16:34 +09301728 if (info->line_out_hw_vol)
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09301729 for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++)
1730 private->dim_mute[i] = !!volume_status.dim_mute[i];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301731
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301732 mute = private->dim_mute[SCARLETT2_BUTTON_MUTE];
1733
1734 for (i = 0; i < num_line_out; i++)
1735 if (private->vol_sw_hw_switch[i]) {
1736 private->vol[i] = private->master_vol;
1737 private->mute_switch[i] = mute;
1738 }
1739
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301740 return 0;
1741}
1742
1743static int scarlett2_volume_ctl_info(struct snd_kcontrol *kctl,
1744 struct snd_ctl_elem_info *uinfo)
1745{
1746 struct usb_mixer_elem_info *elem = kctl->private_data;
1747
1748 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1749 uinfo->count = elem->channels;
1750 uinfo->value.integer.min = 0;
1751 uinfo->value.integer.max = SCARLETT2_VOLUME_BIAS;
1752 uinfo->value.integer.step = 1;
1753 return 0;
1754}
1755
1756static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl,
1757 struct snd_ctl_elem_value *ucontrol)
1758{
1759 struct usb_mixer_elem_info *elem = kctl->private_data;
1760 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301761 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301762
Geoffrey D. Bennett9b5ddea92021-06-21 02:16:43 +09301763 mutex_lock(&private->data_mutex);
1764 if (private->vol_updated)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301765 scarlett2_update_volumes(mixer);
Geoffrey D. Bennett9b5ddea92021-06-21 02:16:43 +09301766 mutex_unlock(&private->data_mutex);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301767
1768 ucontrol->value.integer.value[0] = private->master_vol;
1769 return 0;
1770}
1771
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09301772static int line_out_remap(struct scarlett2_data *private, int index)
1773{
1774 const struct scarlett2_device_info *info = private->info;
1775
1776 if (!info->line_out_remap_enable)
1777 return index;
1778 return info->line_out_remap[index];
1779}
1780
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301781static int scarlett2_volume_ctl_get(struct snd_kcontrol *kctl,
1782 struct snd_ctl_elem_value *ucontrol)
1783{
1784 struct usb_mixer_elem_info *elem = kctl->private_data;
1785 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301786 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09301787 int index = line_out_remap(private, elem->control);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301788
Geoffrey D. Bennett9b5ddea92021-06-21 02:16:43 +09301789 mutex_lock(&private->data_mutex);
1790 if (private->vol_updated)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301791 scarlett2_update_volumes(mixer);
Geoffrey D. Bennett9b5ddea92021-06-21 02:16:43 +09301792 mutex_unlock(&private->data_mutex);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301793
1794 ucontrol->value.integer.value[0] = private->vol[index];
1795 return 0;
1796}
1797
1798static int scarlett2_volume_ctl_put(struct snd_kcontrol *kctl,
1799 struct snd_ctl_elem_value *ucontrol)
1800{
1801 struct usb_mixer_elem_info *elem = kctl->private_data;
1802 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301803 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09301804 int index = line_out_remap(private, elem->control);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301805 int oval, val, err = 0;
1806
1807 mutex_lock(&private->data_mutex);
1808
1809 oval = private->vol[index];
1810 val = ucontrol->value.integer.value[0];
1811
1812 if (oval == val)
1813 goto unlock;
1814
1815 private->vol[index] = val;
1816 err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME,
1817 index, val - SCARLETT2_VOLUME_BIAS);
1818 if (err == 0)
1819 err = 1;
1820
1821unlock:
1822 mutex_unlock(&private->data_mutex);
1823 return err;
1824}
1825
1826static const DECLARE_TLV_DB_MINMAX(
1827 db_scale_scarlett2_gain, -SCARLETT2_VOLUME_BIAS * 100, 0
1828);
1829
1830static const struct snd_kcontrol_new scarlett2_master_volume_ctl = {
1831 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1832 .access = SNDRV_CTL_ELEM_ACCESS_READ |
1833 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1834 .name = "",
1835 .info = scarlett2_volume_ctl_info,
1836 .get = scarlett2_master_volume_ctl_get,
1837 .private_value = 0, /* max value */
1838 .tlv = { .p = db_scale_scarlett2_gain }
1839};
1840
1841static const struct snd_kcontrol_new scarlett2_line_out_volume_ctl = {
1842 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1843 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
1844 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1845 .name = "",
1846 .info = scarlett2_volume_ctl_info,
1847 .get = scarlett2_volume_ctl_get,
1848 .put = scarlett2_volume_ctl_put,
1849 .private_value = 0, /* max value */
1850 .tlv = { .p = db_scale_scarlett2_gain }
1851};
1852
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301853/*** Mute Switch Controls ***/
1854
1855static int scarlett2_mute_ctl_get(struct snd_kcontrol *kctl,
1856 struct snd_ctl_elem_value *ucontrol)
1857{
1858 struct usb_mixer_elem_info *elem = kctl->private_data;
Geoffrey D. Bennett9ee0fc82021-07-23 05:42:48 +09301859 struct usb_mixer_interface *mixer = elem->head.mixer;
1860 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09301861 int index = line_out_remap(private, elem->control);
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301862
Geoffrey D. Bennett9ee0fc82021-07-23 05:42:48 +09301863 mutex_lock(&private->data_mutex);
1864 if (private->vol_updated)
1865 scarlett2_update_volumes(mixer);
1866 mutex_unlock(&private->data_mutex);
1867
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301868 ucontrol->value.integer.value[0] = private->mute_switch[index];
1869 return 0;
1870}
1871
1872static int scarlett2_mute_ctl_put(struct snd_kcontrol *kctl,
1873 struct snd_ctl_elem_value *ucontrol)
1874{
1875 struct usb_mixer_elem_info *elem = kctl->private_data;
1876 struct usb_mixer_interface *mixer = elem->head.mixer;
1877 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09301878 int index = line_out_remap(private, elem->control);
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301879 int oval, val, err = 0;
1880
1881 mutex_lock(&private->data_mutex);
1882
1883 oval = private->mute_switch[index];
1884 val = !!ucontrol->value.integer.value[0];
1885
1886 if (oval == val)
1887 goto unlock;
1888
1889 private->mute_switch[index] = val;
1890
1891 /* Send mute change to the device */
1892 err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MUTE_SWITCH,
1893 index, val);
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09301894 if (err == 0)
1895 err = 1;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301896
1897unlock:
1898 mutex_unlock(&private->data_mutex);
1899 return err;
1900}
1901
1902static const struct snd_kcontrol_new scarlett2_mute_ctl = {
1903 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1904 .name = "",
1905 .info = snd_ctl_boolean_mono_info,
1906 .get = scarlett2_mute_ctl_get,
1907 .put = scarlett2_mute_ctl_put,
1908};
1909
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301910/*** HW/SW Volume Switch Controls ***/
1911
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09301912static void scarlett2_sw_hw_ctl_ro(struct scarlett2_data *private, int index)
1913{
1914 private->sw_hw_ctls[index]->vd[0].access &=
1915 ~SNDRV_CTL_ELEM_ACCESS_WRITE;
1916}
1917
1918static void scarlett2_sw_hw_ctl_rw(struct scarlett2_data *private, int index)
1919{
1920 private->sw_hw_ctls[index]->vd[0].access |=
1921 SNDRV_CTL_ELEM_ACCESS_WRITE;
1922}
1923
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301924static int scarlett2_sw_hw_enum_ctl_info(struct snd_kcontrol *kctl,
1925 struct snd_ctl_elem_info *uinfo)
1926{
1927 static const char *const values[2] = {
1928 "SW", "HW"
1929 };
1930
1931 return snd_ctl_enum_info(uinfo, 1, 2, values);
1932}
1933
1934static int scarlett2_sw_hw_enum_ctl_get(struct snd_kcontrol *kctl,
1935 struct snd_ctl_elem_value *ucontrol)
1936{
1937 struct usb_mixer_elem_info *elem = kctl->private_data;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09301938 struct scarlett2_data *private = elem->head.mixer->private_data;
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09301939 int index = line_out_remap(private, elem->control);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301940
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09301941 ucontrol->value.enumerated.item[0] = private->vol_sw_hw_switch[index];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09301942 return 0;
1943}
1944
Geoffrey D. Bennett06250c82021-06-22 03:39:37 +09301945static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer,
1946 int index, int value)
1947{
1948 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301949 struct snd_card *card = mixer->chip->card;
Geoffrey D. Bennett06250c82021-06-22 03:39:37 +09301950
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301951 /* Set/Clear write bits */
1952 if (value) {
Geoffrey D. Bennett06250c82021-06-22 03:39:37 +09301953 private->vol_ctls[index]->vd[0].access |=
1954 SNDRV_CTL_ELEM_ACCESS_WRITE;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301955 private->mute_ctls[index]->vd[0].access |=
1956 SNDRV_CTL_ELEM_ACCESS_WRITE;
1957 } else {
Geoffrey D. Bennett06250c82021-06-22 03:39:37 +09301958 private->vol_ctls[index]->vd[0].access &=
1959 ~SNDRV_CTL_ELEM_ACCESS_WRITE;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301960 private->mute_ctls[index]->vd[0].access &=
1961 ~SNDRV_CTL_ELEM_ACCESS_WRITE;
1962 }
Geoffrey D. Bennett06250c82021-06-22 03:39:37 +09301963
Geoffrey D. Bennett2b8b12b2021-07-23 05:43:26 +09301964 /* Notify of write bit and possible value change */
1965 snd_ctl_notify(card,
1966 SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
Geoffrey D. Bennett06250c82021-06-22 03:39:37 +09301967 &private->vol_ctls[index]->id);
Geoffrey D. Bennett2b8b12b2021-07-23 05:43:26 +09301968 snd_ctl_notify(card,
1969 SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09301970 &private->mute_ctls[index]->id);
Geoffrey D. Bennett06250c82021-06-22 03:39:37 +09301971}
1972
Geoffrey D. Bennett3b9e3722021-06-23 02:33:36 +09301973static int scarlett2_sw_hw_change(struct usb_mixer_interface *mixer,
1974 int ctl_index, int val)
1975{
1976 struct scarlett2_data *private = mixer->private_data;
1977 int index = line_out_remap(private, ctl_index);
1978 int err;
1979
1980 private->vol_sw_hw_switch[index] = val;
1981
1982 /* Change access mode to RO (hardware controlled volume)
1983 * or RW (software controlled volume)
1984 */
1985 scarlett2_vol_ctl_set_writable(mixer, ctl_index, !val);
1986
1987 /* Reset volume/mute to master volume/mute */
1988 private->vol[index] = private->master_vol;
1989 private->mute_switch[index] = private->dim_mute[SCARLETT2_BUTTON_MUTE];
1990
1991 /* Set SW volume to current HW volume */
1992 err = scarlett2_usb_set_config(
1993 mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME,
1994 index, private->master_vol - SCARLETT2_VOLUME_BIAS);
1995 if (err < 0)
1996 return err;
1997
1998 /* Set SW mute to current HW mute */
1999 err = scarlett2_usb_set_config(
2000 mixer, SCARLETT2_CONFIG_MUTE_SWITCH,
2001 index, private->dim_mute[SCARLETT2_BUTTON_MUTE]);
2002 if (err < 0)
2003 return err;
2004
2005 /* Send SW/HW switch change to the device */
2006 return scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH,
2007 index, val);
2008}
2009
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302010static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl,
2011 struct snd_ctl_elem_value *ucontrol)
2012{
2013 struct usb_mixer_elem_info *elem = kctl->private_data;
2014 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09302015 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09302016 int ctl_index = elem->control;
2017 int index = line_out_remap(private, ctl_index);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302018 int oval, val, err = 0;
2019
2020 mutex_lock(&private->data_mutex);
2021
2022 oval = private->vol_sw_hw_switch[index];
Geoffrey D. Bennett64c02a92021-06-21 02:16:47 +09302023 val = !!ucontrol->value.enumerated.item[0];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302024
2025 if (oval == val)
2026 goto unlock;
2027
Geoffrey D. Bennett3b9e3722021-06-23 02:33:36 +09302028 err = scarlett2_sw_hw_change(mixer, ctl_index, val);
Geoffrey D. Bennettc5d8e002021-06-21 02:16:45 +09302029 if (err == 0)
2030 err = 1;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302031
2032unlock:
2033 mutex_unlock(&private->data_mutex);
2034 return err;
2035}
2036
2037static const struct snd_kcontrol_new scarlett2_sw_hw_enum_ctl = {
2038 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2039 .name = "",
2040 .info = scarlett2_sw_hw_enum_ctl_info,
2041 .get = scarlett2_sw_hw_enum_ctl_get,
2042 .put = scarlett2_sw_hw_enum_ctl_put,
2043};
2044
2045/*** Line Level/Instrument Level Switch Controls ***/
2046
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09302047static int scarlett2_update_input_other(struct usb_mixer_interface *mixer)
2048{
2049 struct scarlett2_data *private = mixer->private_data;
2050 const struct scarlett2_device_info *info = private->info;
2051
2052 private->input_other_updated = 0;
2053
2054 if (info->level_input_count) {
2055 int err = scarlett2_usb_get_config(
2056 mixer, SCARLETT2_CONFIG_LEVEL_SWITCH,
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09302057 info->level_input_count + info->level_input_first,
2058 private->level_switch);
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09302059 if (err < 0)
2060 return err;
2061 }
2062
2063 if (info->pad_input_count) {
2064 int err = scarlett2_usb_get_config(
2065 mixer, SCARLETT2_CONFIG_PAD_SWITCH,
2066 info->pad_input_count, private->pad_switch);
2067 if (err < 0)
2068 return err;
2069 }
2070
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +09302071 if (info->air_input_count) {
2072 int err = scarlett2_usb_get_config(
2073 mixer, SCARLETT2_CONFIG_AIR_SWITCH,
2074 info->air_input_count, private->air_switch);
2075 if (err < 0)
2076 return err;
2077 }
2078
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +09302079 if (info->phantom_count) {
2080 int err = scarlett2_usb_get_config(
2081 mixer, SCARLETT2_CONFIG_PHANTOM_SWITCH,
2082 info->phantom_count, private->phantom_switch);
2083 if (err < 0)
2084 return err;
2085
2086 err = scarlett2_usb_get_config(
2087 mixer, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE,
2088 1, &private->phantom_persistence);
2089 if (err < 0)
2090 return err;
2091 }
2092
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09302093 return 0;
2094}
2095
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302096static int scarlett2_level_enum_ctl_info(struct snd_kcontrol *kctl,
2097 struct snd_ctl_elem_info *uinfo)
2098{
2099 static const char *const values[2] = {
2100 "Line", "Inst"
2101 };
2102
2103 return snd_ctl_enum_info(uinfo, 1, 2, values);
2104}
2105
2106static int scarlett2_level_enum_ctl_get(struct snd_kcontrol *kctl,
2107 struct snd_ctl_elem_value *ucontrol)
2108{
2109 struct usb_mixer_elem_info *elem = kctl->private_data;
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09302110 struct usb_mixer_interface *mixer = elem->head.mixer;
2111 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09302112 const struct scarlett2_device_info *info = private->info;
2113
2114 int index = elem->control + info->level_input_first;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302115
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09302116 mutex_lock(&private->data_mutex);
2117 if (private->input_other_updated)
2118 scarlett2_update_input_other(mixer);
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09302119 ucontrol->value.enumerated.item[0] = private->level_switch[index];
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09302120 mutex_unlock(&private->data_mutex);
2121
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302122 return 0;
2123}
2124
2125static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl,
2126 struct snd_ctl_elem_value *ucontrol)
2127{
2128 struct usb_mixer_elem_info *elem = kctl->private_data;
2129 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09302130 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09302131 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302132
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09302133 int index = elem->control + info->level_input_first;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302134 int oval, val, err = 0;
2135
2136 mutex_lock(&private->data_mutex);
2137
2138 oval = private->level_switch[index];
Geoffrey D. Bennett64c02a92021-06-21 02:16:47 +09302139 val = !!ucontrol->value.enumerated.item[0];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302140
2141 if (oval == val)
2142 goto unlock;
2143
2144 private->level_switch[index] = val;
2145
2146 /* Send switch change to the device */
2147 err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LEVEL_SWITCH,
2148 index, val);
Geoffrey D. Bennettc5d8e002021-06-21 02:16:45 +09302149 if (err == 0)
2150 err = 1;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302151
2152unlock:
2153 mutex_unlock(&private->data_mutex);
2154 return err;
2155}
2156
2157static const struct snd_kcontrol_new scarlett2_level_enum_ctl = {
2158 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2159 .name = "",
2160 .info = scarlett2_level_enum_ctl_info,
2161 .get = scarlett2_level_enum_ctl_get,
2162 .put = scarlett2_level_enum_ctl_put,
2163};
2164
2165/*** Pad Switch Controls ***/
2166
2167static int scarlett2_pad_ctl_get(struct snd_kcontrol *kctl,
2168 struct snd_ctl_elem_value *ucontrol)
2169{
2170 struct usb_mixer_elem_info *elem = kctl->private_data;
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09302171 struct usb_mixer_interface *mixer = elem->head.mixer;
2172 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302173
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09302174 mutex_lock(&private->data_mutex);
2175 if (private->input_other_updated)
2176 scarlett2_update_input_other(mixer);
Geoffrey D. Bennett64c02a92021-06-21 02:16:47 +09302177 ucontrol->value.integer.value[0] =
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302178 private->pad_switch[elem->control];
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09302179 mutex_unlock(&private->data_mutex);
2180
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302181 return 0;
2182}
2183
2184static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl,
2185 struct snd_ctl_elem_value *ucontrol)
2186{
2187 struct usb_mixer_elem_info *elem = kctl->private_data;
2188 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09302189 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302190
2191 int index = elem->control;
2192 int oval, val, err = 0;
2193
2194 mutex_lock(&private->data_mutex);
2195
2196 oval = private->pad_switch[index];
2197 val = !!ucontrol->value.integer.value[0];
2198
2199 if (oval == val)
2200 goto unlock;
2201
2202 private->pad_switch[index] = val;
2203
2204 /* Send switch change to the device */
2205 err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PAD_SWITCH,
2206 index, val);
Geoffrey D. Bennettc5d8e002021-06-21 02:16:45 +09302207 if (err == 0)
2208 err = 1;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302209
2210unlock:
2211 mutex_unlock(&private->data_mutex);
2212 return err;
2213}
2214
2215static const struct snd_kcontrol_new scarlett2_pad_ctl = {
2216 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2217 .name = "",
2218 .info = snd_ctl_boolean_mono_info,
2219 .get = scarlett2_pad_ctl_get,
2220 .put = scarlett2_pad_ctl_put,
2221};
2222
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +09302223/*** Air Switch Controls ***/
2224
2225static int scarlett2_air_ctl_get(struct snd_kcontrol *kctl,
2226 struct snd_ctl_elem_value *ucontrol)
2227{
2228 struct usb_mixer_elem_info *elem = kctl->private_data;
2229 struct usb_mixer_interface *mixer = elem->head.mixer;
2230 struct scarlett2_data *private = mixer->private_data;
2231
2232 mutex_lock(&private->data_mutex);
2233 if (private->input_other_updated)
2234 scarlett2_update_input_other(mixer);
2235 ucontrol->value.integer.value[0] = private->air_switch[elem->control];
2236 mutex_unlock(&private->data_mutex);
2237
2238 return 0;
2239}
2240
2241static int scarlett2_air_ctl_put(struct snd_kcontrol *kctl,
2242 struct snd_ctl_elem_value *ucontrol)
2243{
2244 struct usb_mixer_elem_info *elem = kctl->private_data;
2245 struct usb_mixer_interface *mixer = elem->head.mixer;
2246 struct scarlett2_data *private = mixer->private_data;
2247
2248 int index = elem->control;
2249 int oval, val, err = 0;
2250
2251 mutex_lock(&private->data_mutex);
2252
2253 oval = private->air_switch[index];
2254 val = !!ucontrol->value.integer.value[0];
2255
2256 if (oval == val)
2257 goto unlock;
2258
2259 private->air_switch[index] = val;
2260
2261 /* Send switch change to the device */
2262 err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_AIR_SWITCH,
2263 index, val);
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302264 if (err == 0)
2265 err = 1;
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +09302266
2267unlock:
2268 mutex_unlock(&private->data_mutex);
2269 return err;
2270}
2271
2272static const struct snd_kcontrol_new scarlett2_air_ctl = {
2273 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2274 .name = "",
2275 .info = snd_ctl_boolean_mono_info,
2276 .get = scarlett2_air_ctl_get,
2277 .put = scarlett2_air_ctl_put,
2278};
2279
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +09302280/*** Phantom Switch Controls ***/
2281
2282static int scarlett2_phantom_ctl_get(struct snd_kcontrol *kctl,
2283 struct snd_ctl_elem_value *ucontrol)
2284{
2285 struct usb_mixer_elem_info *elem = kctl->private_data;
2286 struct usb_mixer_interface *mixer = elem->head.mixer;
2287 struct scarlett2_data *private = mixer->private_data;
2288
2289 mutex_lock(&private->data_mutex);
2290 if (private->input_other_updated)
2291 scarlett2_update_input_other(mixer);
2292 ucontrol->value.integer.value[0] =
2293 private->phantom_switch[elem->control];
2294 mutex_unlock(&private->data_mutex);
2295
2296 return 0;
2297}
2298
2299static int scarlett2_phantom_ctl_put(struct snd_kcontrol *kctl,
2300 struct snd_ctl_elem_value *ucontrol)
2301{
2302 struct usb_mixer_elem_info *elem = kctl->private_data;
2303 struct usb_mixer_interface *mixer = elem->head.mixer;
2304 struct scarlett2_data *private = mixer->private_data;
2305
2306 int index = elem->control;
2307 int oval, val, err = 0;
2308
2309 mutex_lock(&private->data_mutex);
2310
2311 oval = private->phantom_switch[index];
2312 val = !!ucontrol->value.integer.value[0];
2313
2314 if (oval == val)
2315 goto unlock;
2316
2317 private->phantom_switch[index] = val;
2318
2319 /* Send switch change to the device */
2320 err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PHANTOM_SWITCH,
2321 index, val);
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302322 if (err == 0)
2323 err = 1;
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +09302324
2325unlock:
2326 mutex_unlock(&private->data_mutex);
2327 return err;
2328}
2329
2330static const struct snd_kcontrol_new scarlett2_phantom_ctl = {
2331 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2332 .name = "",
2333 .info = snd_ctl_boolean_mono_info,
2334 .get = scarlett2_phantom_ctl_get,
2335 .put = scarlett2_phantom_ctl_put,
2336};
2337
2338/*** Phantom Persistence Control ***/
2339
2340static int scarlett2_phantom_persistence_ctl_get(
2341 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2342{
2343 struct usb_mixer_elem_info *elem = kctl->private_data;
2344 struct scarlett2_data *private = elem->head.mixer->private_data;
2345
2346 ucontrol->value.integer.value[0] = private->phantom_persistence;
2347 return 0;
2348}
2349
2350static int scarlett2_phantom_persistence_ctl_put(
2351 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2352{
2353 struct usb_mixer_elem_info *elem = kctl->private_data;
2354 struct usb_mixer_interface *mixer = elem->head.mixer;
2355 struct scarlett2_data *private = mixer->private_data;
2356
2357 int index = elem->control;
2358 int oval, val, err = 0;
2359
2360 mutex_lock(&private->data_mutex);
2361
2362 oval = private->phantom_persistence;
2363 val = !!ucontrol->value.integer.value[0];
2364
2365 if (oval == val)
2366 goto unlock;
2367
2368 private->phantom_persistence = val;
2369
2370 /* Send switch change to the device */
2371 err = scarlett2_usb_set_config(
2372 mixer, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE, index, val);
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302373 if (err == 0)
2374 err = 1;
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +09302375
2376unlock:
2377 mutex_unlock(&private->data_mutex);
2378 return err;
2379}
2380
2381static const struct snd_kcontrol_new scarlett2_phantom_persistence_ctl = {
2382 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2383 .name = "",
2384 .info = snd_ctl_boolean_mono_info,
2385 .get = scarlett2_phantom_persistence_ctl_get,
2386 .put = scarlett2_phantom_persistence_ctl_put,
2387};
2388
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09302389/*** Direct Monitor Control ***/
2390
2391static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer)
2392{
2393 struct scarlett2_data *private = mixer->private_data;
2394 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302395 int err;
2396
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09302397 /* monitor_other_enable[0] enables speaker switching
2398 * monitor_other_enable[1] enables talkback
2399 */
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302400 u8 monitor_other_enable[2];
2401
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09302402 /* monitor_other_switch[0] activates the alternate speakers
2403 * monitor_other_switch[1] activates talkback
2404 */
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302405 u8 monitor_other_switch[2];
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09302406
2407 private->monitor_other_updated = 0;
2408
2409 if (info->direct_monitor)
2410 return scarlett2_usb_get_config(
2411 mixer, SCARLETT2_CONFIG_DIRECT_MONITOR,
2412 1, &private->direct_monitor_switch);
2413
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09302414 /* if it doesn't do speaker switching then it also doesn't do
2415 * talkback
2416 */
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302417 if (!info->has_speaker_switching)
2418 return 0;
2419
2420 err = scarlett2_usb_get_config(
2421 mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE,
2422 2, monitor_other_enable);
2423 if (err < 0)
2424 return err;
2425
2426 err = scarlett2_usb_get_config(
2427 mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH,
2428 2, monitor_other_switch);
2429 if (err < 0)
2430 return err;
2431
2432 if (!monitor_other_enable[0])
2433 private->speaker_switching_switch = 0;
2434 else
2435 private->speaker_switching_switch = monitor_other_switch[0] + 1;
2436
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09302437 if (info->has_talkback) {
2438 const int (*port_count)[SCARLETT2_PORT_DIRNS] =
2439 info->port_count;
2440 int num_mixes =
2441 port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
2442 u16 bitmap;
2443 int i;
2444
2445 if (!monitor_other_enable[1])
2446 private->talkback_switch = 0;
2447 else
2448 private->talkback_switch = monitor_other_switch[1] + 1;
2449
2450 err = scarlett2_usb_get_config(mixer,
2451 SCARLETT2_CONFIG_TALKBACK_MAP,
2452 1, &bitmap);
Takashi Iwai8ec59ac2021-09-29 09:35:40 +02002453 if (err < 0)
2454 return err;
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09302455 for (i = 0; i < num_mixes; i++, bitmap >>= 1)
2456 private->talkback_map[i] = bitmap & 1;
2457 }
2458
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09302459 return 0;
2460}
2461
2462static int scarlett2_direct_monitor_ctl_get(
2463 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2464{
2465 struct usb_mixer_elem_info *elem = kctl->private_data;
2466 struct usb_mixer_interface *mixer = elem->head.mixer;
2467 struct scarlett2_data *private = elem->head.mixer->private_data;
2468
2469 mutex_lock(&private->data_mutex);
2470 if (private->monitor_other_updated)
2471 scarlett2_update_monitor_other(mixer);
2472 ucontrol->value.enumerated.item[0] = private->direct_monitor_switch;
2473 mutex_unlock(&private->data_mutex);
2474
2475 return 0;
2476}
2477
2478static int scarlett2_direct_monitor_ctl_put(
2479 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2480{
2481 struct usb_mixer_elem_info *elem = kctl->private_data;
2482 struct usb_mixer_interface *mixer = elem->head.mixer;
2483 struct scarlett2_data *private = mixer->private_data;
2484
2485 int index = elem->control;
2486 int oval, val, err = 0;
2487
2488 mutex_lock(&private->data_mutex);
2489
2490 oval = private->direct_monitor_switch;
2491 val = min(ucontrol->value.enumerated.item[0], 2U);
2492
2493 if (oval == val)
2494 goto unlock;
2495
2496 private->direct_monitor_switch = val;
2497
2498 /* Send switch change to the device */
2499 err = scarlett2_usb_set_config(
2500 mixer, SCARLETT2_CONFIG_DIRECT_MONITOR, index, val);
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302501 if (err == 0)
2502 err = 1;
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09302503
2504unlock:
2505 mutex_unlock(&private->data_mutex);
2506 return err;
2507}
2508
2509static int scarlett2_direct_monitor_stereo_enum_ctl_info(
2510 struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
2511{
2512 static const char *const values[3] = {
2513 "Off", "Mono", "Stereo"
2514 };
2515
2516 return snd_ctl_enum_info(uinfo, 1, 3, values);
2517}
2518
2519/* Direct Monitor for Solo is mono-only and only needs a boolean control
2520 * Direct Monitor for 2i2 is selectable between Off/Mono/Stereo
2521 */
2522static const struct snd_kcontrol_new scarlett2_direct_monitor_ctl[2] = {
2523 {
2524 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2525 .name = "",
2526 .info = snd_ctl_boolean_mono_info,
2527 .get = scarlett2_direct_monitor_ctl_get,
2528 .put = scarlett2_direct_monitor_ctl_put,
2529 },
2530 {
2531 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2532 .name = "",
2533 .info = scarlett2_direct_monitor_stereo_enum_ctl_info,
2534 .get = scarlett2_direct_monitor_ctl_get,
2535 .put = scarlett2_direct_monitor_ctl_put,
2536 }
2537};
2538
2539static int scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface *mixer)
2540{
2541 struct scarlett2_data *private = mixer->private_data;
2542 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennettd3a4f782021-07-23 05:42:08 +09302543 const char *s;
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09302544
2545 if (!info->direct_monitor)
2546 return 0;
2547
Geoffrey D. Bennettd3a4f782021-07-23 05:42:08 +09302548 s = info->direct_monitor == 1
2549 ? "Direct Monitor Playback Switch"
2550 : "Direct Monitor Playback Enum";
2551
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09302552 return scarlett2_add_new_ctl(
2553 mixer, &scarlett2_direct_monitor_ctl[info->direct_monitor - 1],
Geoffrey D. Bennettd3a4f782021-07-23 05:42:08 +09302554 0, 1, s, &private->direct_monitor_ctl);
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09302555}
2556
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302557/*** Speaker Switching Control ***/
2558
2559static int scarlett2_speaker_switch_enum_ctl_info(
2560 struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
2561{
2562 static const char *const values[3] = {
2563 "Off", "Main", "Alt"
2564 };
2565
2566 return snd_ctl_enum_info(uinfo, 1, 3, values);
2567}
2568
2569static int scarlett2_speaker_switch_enum_ctl_get(
2570 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2571{
2572 struct usb_mixer_elem_info *elem = kctl->private_data;
2573 struct usb_mixer_interface *mixer = elem->head.mixer;
2574 struct scarlett2_data *private = mixer->private_data;
2575
2576 mutex_lock(&private->data_mutex);
2577 if (private->monitor_other_updated)
2578 scarlett2_update_monitor_other(mixer);
2579 ucontrol->value.enumerated.item[0] = private->speaker_switching_switch;
2580 mutex_unlock(&private->data_mutex);
2581
2582 return 0;
2583}
2584
2585/* when speaker switching gets enabled, switch the main/alt speakers
2586 * to HW volume and disable those controls
2587 */
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302588static int scarlett2_speaker_switch_enable(struct usb_mixer_interface *mixer)
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302589{
2590 struct snd_card *card = mixer->chip->card;
2591 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302592 int i, err;
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302593
2594 for (i = 0; i < 4; i++) {
2595 int index = line_out_remap(private, i);
2596
2597 /* switch the main/alt speakers to HW volume */
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302598 if (!private->vol_sw_hw_switch[index]) {
2599 err = scarlett2_sw_hw_change(private->mixer, i, 1);
2600 if (err < 0)
2601 return err;
2602 }
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302603
2604 /* disable the line out SW/HW switch */
2605 scarlett2_sw_hw_ctl_ro(private, i);
Geoffrey D. Bennett2b8b12b2021-07-23 05:43:26 +09302606 snd_ctl_notify(card,
2607 SNDRV_CTL_EVENT_MASK_VALUE |
2608 SNDRV_CTL_EVENT_MASK_INFO,
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302609 &private->sw_hw_ctls[i]->id);
2610 }
2611
2612 /* when the next monitor-other notify comes in, update the mux
2613 * configuration
2614 */
2615 private->speaker_switching_switched = 1;
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302616
2617 return 0;
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302618}
2619
2620/* when speaker switching gets disabled, reenable the hw/sw controls
2621 * and invalidate the routing
2622 */
2623static void scarlett2_speaker_switch_disable(struct usb_mixer_interface *mixer)
2624{
2625 struct snd_card *card = mixer->chip->card;
2626 struct scarlett2_data *private = mixer->private_data;
2627 int i;
2628
2629 /* enable the line out SW/HW switch */
2630 for (i = 0; i < 4; i++) {
2631 scarlett2_sw_hw_ctl_rw(private, i);
2632 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
2633 &private->sw_hw_ctls[i]->id);
2634 }
2635
2636 /* when the next monitor-other notify comes in, update the mux
2637 * configuration
2638 */
2639 private->speaker_switching_switched = 1;
2640}
2641
2642static int scarlett2_speaker_switch_enum_ctl_put(
2643 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2644{
2645 struct usb_mixer_elem_info *elem = kctl->private_data;
2646 struct usb_mixer_interface *mixer = elem->head.mixer;
2647 struct scarlett2_data *private = mixer->private_data;
2648
2649 int oval, val, err = 0;
2650
2651 mutex_lock(&private->data_mutex);
2652
2653 oval = private->speaker_switching_switch;
2654 val = min(ucontrol->value.enumerated.item[0], 2U);
2655
2656 if (oval == val)
2657 goto unlock;
2658
2659 private->speaker_switching_switch = val;
2660
2661 /* enable/disable speaker switching */
2662 err = scarlett2_usb_set_config(
2663 mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE,
2664 0, !!val);
2665 if (err < 0)
2666 goto unlock;
2667
2668 /* if speaker switching is enabled, select main or alt */
2669 err = scarlett2_usb_set_config(
2670 mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH,
2671 0, val == 2);
2672 if (err < 0)
2673 goto unlock;
2674
2675 /* update controls if speaker switching gets enabled or disabled */
2676 if (!oval && val)
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302677 err = scarlett2_speaker_switch_enable(mixer);
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302678 else if (oval && !val)
2679 scarlett2_speaker_switch_disable(mixer);
2680
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302681 if (err == 0)
2682 err = 1;
2683
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09302684unlock:
2685 mutex_unlock(&private->data_mutex);
2686 return err;
2687}
2688
2689static const struct snd_kcontrol_new scarlett2_speaker_switch_enum_ctl = {
2690 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2691 .name = "",
2692 .info = scarlett2_speaker_switch_enum_ctl_info,
2693 .get = scarlett2_speaker_switch_enum_ctl_get,
2694 .put = scarlett2_speaker_switch_enum_ctl_put,
2695};
2696
2697static int scarlett2_add_speaker_switch_ctl(
2698 struct usb_mixer_interface *mixer)
2699{
2700 struct scarlett2_data *private = mixer->private_data;
2701 const struct scarlett2_device_info *info = private->info;
2702
2703 if (!info->has_speaker_switching)
2704 return 0;
2705
2706 return scarlett2_add_new_ctl(
2707 mixer, &scarlett2_speaker_switch_enum_ctl,
2708 0, 1, "Speaker Switching Playback Enum",
2709 &private->speaker_switching_ctl);
2710}
2711
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09302712/*** Talkback and Talkback Map Controls ***/
2713
2714static int scarlett2_talkback_enum_ctl_info(
2715 struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
2716{
2717 static const char *const values[3] = {
2718 "Disabled", "Off", "On"
2719 };
2720
2721 return snd_ctl_enum_info(uinfo, 1, 3, values);
2722}
2723
2724static int scarlett2_talkback_enum_ctl_get(
2725 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2726{
2727 struct usb_mixer_elem_info *elem = kctl->private_data;
2728 struct usb_mixer_interface *mixer = elem->head.mixer;
2729 struct scarlett2_data *private = mixer->private_data;
2730
2731 mutex_lock(&private->data_mutex);
2732 if (private->monitor_other_updated)
2733 scarlett2_update_monitor_other(mixer);
2734 ucontrol->value.enumerated.item[0] = private->talkback_switch;
2735 mutex_unlock(&private->data_mutex);
2736
2737 return 0;
2738}
2739
2740static int scarlett2_talkback_enum_ctl_put(
2741 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2742{
2743 struct usb_mixer_elem_info *elem = kctl->private_data;
2744 struct usb_mixer_interface *mixer = elem->head.mixer;
2745 struct scarlett2_data *private = mixer->private_data;
2746
2747 int oval, val, err = 0;
2748
2749 mutex_lock(&private->data_mutex);
2750
2751 oval = private->talkback_switch;
2752 val = min(ucontrol->value.enumerated.item[0], 2U);
2753
2754 if (oval == val)
2755 goto unlock;
2756
2757 private->talkback_switch = val;
2758
2759 /* enable/disable talkback */
2760 err = scarlett2_usb_set_config(
2761 mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE,
2762 1, !!val);
2763 if (err < 0)
2764 goto unlock;
2765
2766 /* if talkback is enabled, select main or alt */
2767 err = scarlett2_usb_set_config(
2768 mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH,
2769 1, val == 2);
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302770 if (err == 0)
2771 err = 1;
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09302772
2773unlock:
2774 mutex_unlock(&private->data_mutex);
2775 return err;
2776}
2777
2778static const struct snd_kcontrol_new scarlett2_talkback_enum_ctl = {
2779 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2780 .name = "",
2781 .info = scarlett2_talkback_enum_ctl_info,
2782 .get = scarlett2_talkback_enum_ctl_get,
2783 .put = scarlett2_talkback_enum_ctl_put,
2784};
2785
2786static int scarlett2_talkback_map_ctl_get(
2787 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2788{
2789 struct usb_mixer_elem_info *elem = kctl->private_data;
2790 struct usb_mixer_interface *mixer = elem->head.mixer;
2791 struct scarlett2_data *private = mixer->private_data;
2792 int index = elem->control;
2793
2794 ucontrol->value.integer.value[0] = private->talkback_map[index];
2795
2796 return 0;
2797}
2798
2799static int scarlett2_talkback_map_ctl_put(
2800 struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
2801{
2802 struct usb_mixer_elem_info *elem = kctl->private_data;
2803 struct usb_mixer_interface *mixer = elem->head.mixer;
2804 struct scarlett2_data *private = mixer->private_data;
2805 const int (*port_count)[SCARLETT2_PORT_DIRNS] =
2806 private->info->port_count;
2807 int num_mixes = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
2808
2809 int index = elem->control;
2810 int oval, val, err = 0, i;
2811 u16 bitmap = 0;
2812
2813 mutex_lock(&private->data_mutex);
2814
2815 oval = private->talkback_map[index];
2816 val = !!ucontrol->value.integer.value[0];
2817
2818 if (oval == val)
2819 goto unlock;
2820
2821 private->talkback_map[index] = val;
2822
2823 for (i = 0; i < num_mixes; i++)
2824 bitmap |= private->talkback_map[i] << i;
2825
2826 /* Send updated bitmap to the device */
2827 err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_TALKBACK_MAP,
2828 0, bitmap);
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09302829 if (err == 0)
2830 err = 1;
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09302831
2832unlock:
2833 mutex_unlock(&private->data_mutex);
2834 return err;
2835}
2836
2837static const struct snd_kcontrol_new scarlett2_talkback_map_ctl = {
2838 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2839 .name = "",
2840 .info = snd_ctl_boolean_mono_info,
2841 .get = scarlett2_talkback_map_ctl_get,
2842 .put = scarlett2_talkback_map_ctl_put,
2843};
2844
2845static int scarlett2_add_talkback_ctls(
2846 struct usb_mixer_interface *mixer)
2847{
2848 struct scarlett2_data *private = mixer->private_data;
2849 const struct scarlett2_device_info *info = private->info;
2850 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
2851 int num_mixes = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
2852 int err, i;
2853 char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2854
2855 if (!info->has_talkback)
2856 return 0;
2857
2858 err = scarlett2_add_new_ctl(
2859 mixer, &scarlett2_talkback_enum_ctl,
2860 0, 1, "Talkback Playback Enum",
2861 &private->talkback_ctl);
2862 if (err < 0)
2863 return err;
2864
2865 for (i = 0; i < num_mixes; i++) {
2866 snprintf(s, sizeof(s),
2867 "Talkback Mix %c Playback Switch", i + 'A');
2868 err = scarlett2_add_new_ctl(mixer, &scarlett2_talkback_map_ctl,
2869 i, 1, s, NULL);
2870 if (err < 0)
2871 return err;
2872 }
2873
2874 return 0;
2875}
2876
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09302877/*** Dim/Mute Controls ***/
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302878
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09302879static int scarlett2_dim_mute_ctl_get(struct snd_kcontrol *kctl,
2880 struct snd_ctl_elem_value *ucontrol)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302881{
2882 struct usb_mixer_elem_info *elem = kctl->private_data;
2883 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09302884 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302885
Geoffrey D. Bennett9b5ddea92021-06-21 02:16:43 +09302886 mutex_lock(&private->data_mutex);
2887 if (private->vol_updated)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302888 scarlett2_update_volumes(mixer);
Geoffrey D. Bennett9b5ddea92021-06-21 02:16:43 +09302889 mutex_unlock(&private->data_mutex);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302890
Geoffrey D. Bennett64c02a92021-06-21 02:16:47 +09302891 ucontrol->value.integer.value[0] = private->dim_mute[elem->control];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302892 return 0;
2893}
2894
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09302895static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl,
2896 struct snd_ctl_elem_value *ucontrol)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302897{
2898 struct usb_mixer_elem_info *elem = kctl->private_data;
2899 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09302900 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09302901 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09302902 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09302903 int num_line_out =
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09302904 port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302905
2906 int index = elem->control;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09302907 int oval, val, err = 0, i;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302908
2909 mutex_lock(&private->data_mutex);
2910
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09302911 oval = private->dim_mute[index];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302912 val = !!ucontrol->value.integer.value[0];
2913
2914 if (oval == val)
2915 goto unlock;
2916
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09302917 private->dim_mute[index] = val;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302918
2919 /* Send switch change to the device */
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09302920 err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_DIM_MUTE,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302921 index, val);
Geoffrey D. Bennettc5d8e002021-06-21 02:16:45 +09302922 if (err == 0)
2923 err = 1;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302924
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09302925 if (index == SCARLETT2_BUTTON_MUTE)
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09302926 for (i = 0; i < num_line_out; i++) {
2927 int line_index = line_out_remap(private, i);
2928
2929 if (private->vol_sw_hw_switch[line_index]) {
2930 private->mute_switch[line_index] = val;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09302931 snd_ctl_notify(mixer->chip->card,
Geoffrey D. Bennett2b8b12b2021-07-23 05:43:26 +09302932 SNDRV_CTL_EVENT_MASK_VALUE,
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09302933 &private->mute_ctls[i]->id);
2934 }
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09302935 }
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09302936
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302937unlock:
2938 mutex_unlock(&private->data_mutex);
2939 return err;
2940}
2941
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09302942static const struct snd_kcontrol_new scarlett2_dim_mute_ctl = {
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302943 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2944 .name = "",
2945 .info = snd_ctl_boolean_mono_info,
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09302946 .get = scarlett2_dim_mute_ctl_get,
2947 .put = scarlett2_dim_mute_ctl_put
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302948};
2949
2950/*** Create the analogue output controls ***/
2951
2952static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer)
2953{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09302954 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302955 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09302956 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302957 int num_line_out =
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09302958 port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302959 int err, i;
2960 char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2961
2962 /* Add R/O HW volume control */
2963 if (info->line_out_hw_vol) {
2964 snprintf(s, sizeof(s), "Master HW Playback Volume");
2965 err = scarlett2_add_new_ctl(mixer,
2966 &scarlett2_master_volume_ctl,
2967 0, 1, s, &private->master_vol_ctl);
2968 if (err < 0)
2969 return err;
2970 }
2971
2972 /* Add volume controls */
2973 for (i = 0; i < num_line_out; i++) {
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09302974 int index = line_out_remap(private, i);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09302975
2976 /* Fader */
2977 if (info->line_out_descrs[i])
2978 snprintf(s, sizeof(s),
2979 "Line %02d (%s) Playback Volume",
2980 i + 1, info->line_out_descrs[i]);
2981 else
2982 snprintf(s, sizeof(s),
2983 "Line %02d Playback Volume",
2984 i + 1);
2985 err = scarlett2_add_new_ctl(mixer,
2986 &scarlett2_line_out_volume_ctl,
2987 i, 1, s, &private->vol_ctls[i]);
2988 if (err < 0)
2989 return err;
2990
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09302991 /* Mute Switch */
2992 snprintf(s, sizeof(s),
2993 "Line %02d Mute Playback Switch",
2994 i + 1);
2995 err = scarlett2_add_new_ctl(mixer,
2996 &scarlett2_mute_ctl,
2997 i, 1, s,
2998 &private->mute_ctls[i]);
2999 if (err < 0)
3000 return err;
3001
3002 /* Make the fader and mute controls read-only if the
3003 * SW/HW switch is set to HW
3004 */
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09303005 if (private->vol_sw_hw_switch[index])
Geoffrey D. Bennett06250c82021-06-22 03:39:37 +09303006 scarlett2_vol_ctl_set_writable(mixer, i, 0);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303007
3008 /* SW/HW Switch */
3009 if (info->line_out_hw_vol) {
3010 snprintf(s, sizeof(s),
3011 "Line Out %02d Volume Control Playback Enum",
3012 i + 1);
3013 err = scarlett2_add_new_ctl(mixer,
3014 &scarlett2_sw_hw_enum_ctl,
Geoffrey D. Bennettf02da652021-06-23 02:33:45 +09303015 i, 1, s,
3016 &private->sw_hw_ctls[i]);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303017 if (err < 0)
3018 return err;
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09303019
3020 /* Make the switch read-only if the line is
3021 * involved in speaker switching
3022 */
3023 if (private->speaker_switching_switch && i < 4)
3024 scarlett2_sw_hw_ctl_ro(private, i);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303025 }
3026 }
3027
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303028 /* Add dim/mute controls */
Geoffrey D. Bennett03bdbcf2021-06-21 02:16:34 +09303029 if (info->line_out_hw_vol)
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303030 for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) {
Geoffrey D. Bennett03bdbcf2021-06-21 02:16:34 +09303031 err = scarlett2_add_new_ctl(
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303032 mixer, &scarlett2_dim_mute_ctl,
3033 i, 1, scarlett2_dim_mute_names[i],
3034 &private->dim_mute_ctls[i]);
Geoffrey D. Bennett03bdbcf2021-06-21 02:16:34 +09303035 if (err < 0)
3036 return err;
3037 }
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303038
3039 return 0;
3040}
3041
3042/*** Create the analogue input controls ***/
3043
3044static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer)
3045{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303046 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303047 const struct scarlett2_device_info *info = private->info;
3048 int err, i;
3049 char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
Geoffrey D. Bennett077e1042021-06-22 03:39:26 +09303050 const char *fmt = "Line In %d %s Capture %s";
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +09303051 const char *fmt2 = "Line In %d-%d %s Capture %s";
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303052
3053 /* Add input level (line/inst) controls */
3054 for (i = 0; i < info->level_input_count; i++) {
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09303055 snprintf(s, sizeof(s), fmt, i + 1 + info->level_input_first,
3056 "Level", "Enum");
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303057 err = scarlett2_add_new_ctl(mixer, &scarlett2_level_enum_ctl,
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09303058 i, 1, s, &private->level_ctls[i]);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303059 if (err < 0)
3060 return err;
3061 }
3062
3063 /* Add input pad controls */
3064 for (i = 0; i < info->pad_input_count; i++) {
Geoffrey D. Bennett077e1042021-06-22 03:39:26 +09303065 snprintf(s, sizeof(s), fmt, i + 1, "Pad", "Switch");
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303066 err = scarlett2_add_new_ctl(mixer, &scarlett2_pad_ctl,
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09303067 i, 1, s, &private->pad_ctls[i]);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303068 if (err < 0)
3069 return err;
3070 }
3071
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +09303072 /* Add input air controls */
3073 for (i = 0; i < info->air_input_count; i++) {
3074 snprintf(s, sizeof(s), fmt, i + 1, "Air", "Switch");
3075 err = scarlett2_add_new_ctl(mixer, &scarlett2_air_ctl,
3076 i, 1, s, &private->air_ctls[i]);
3077 if (err < 0)
3078 return err;
3079 }
3080
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +09303081 /* Add input phantom controls */
3082 if (info->inputs_per_phantom == 1) {
3083 for (i = 0; i < info->phantom_count; i++) {
3084 snprintf(s, sizeof(s), fmt, i + 1,
3085 "Phantom Power", "Switch");
3086 err = scarlett2_add_new_ctl(
3087 mixer, &scarlett2_phantom_ctl,
3088 i, 1, s, &private->phantom_ctls[i]);
3089 if (err < 0)
3090 return err;
3091 }
3092 } else if (info->inputs_per_phantom > 1) {
3093 for (i = 0; i < info->phantom_count; i++) {
3094 int from = i * info->inputs_per_phantom + 1;
3095 int to = (i + 1) * info->inputs_per_phantom;
3096
3097 snprintf(s, sizeof(s), fmt2, from, to,
3098 "Phantom Power", "Switch");
3099 err = scarlett2_add_new_ctl(
3100 mixer, &scarlett2_phantom_ctl,
3101 i, 1, s, &private->phantom_ctls[i]);
3102 if (err < 0)
3103 return err;
3104 }
3105 }
3106 if (info->phantom_count) {
3107 err = scarlett2_add_new_ctl(
3108 mixer, &scarlett2_phantom_persistence_ctl, 0, 1,
3109 "Phantom Power Persistence Capture Switch", NULL);
3110 if (err < 0)
3111 return err;
3112 }
3113
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303114 return 0;
3115}
3116
3117/*** Mixer Volume Controls ***/
3118
3119static int scarlett2_mixer_ctl_info(struct snd_kcontrol *kctl,
3120 struct snd_ctl_elem_info *uinfo)
3121{
3122 struct usb_mixer_elem_info *elem = kctl->private_data;
3123
3124 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3125 uinfo->count = elem->channels;
3126 uinfo->value.integer.min = 0;
3127 uinfo->value.integer.max = SCARLETT2_MIXER_MAX_VALUE;
3128 uinfo->value.integer.step = 1;
3129 return 0;
3130}
3131
3132static int scarlett2_mixer_ctl_get(struct snd_kcontrol *kctl,
3133 struct snd_ctl_elem_value *ucontrol)
3134{
3135 struct usb_mixer_elem_info *elem = kctl->private_data;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303136 struct scarlett2_data *private = elem->head.mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303137
3138 ucontrol->value.integer.value[0] = private->mix[elem->control];
3139 return 0;
3140}
3141
3142static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl,
3143 struct snd_ctl_elem_value *ucontrol)
3144{
3145 struct usb_mixer_elem_info *elem = kctl->private_data;
3146 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303147 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303148 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303149 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303150 int oval, val, num_mixer_in, mix_num, err = 0;
Geoffrey D. Bennett3eeb2a12021-06-21 02:16:41 +09303151 int index = elem->control;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303152
3153 mutex_lock(&private->data_mutex);
3154
Geoffrey D. Bennett3eeb2a12021-06-21 02:16:41 +09303155 oval = private->mix[index];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303156 val = ucontrol->value.integer.value[0];
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303157 num_mixer_in = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett3eeb2a12021-06-21 02:16:41 +09303158 mix_num = index / num_mixer_in;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303159
3160 if (oval == val)
3161 goto unlock;
3162
Geoffrey D. Bennett3eeb2a12021-06-21 02:16:41 +09303163 private->mix[index] = val;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303164 err = scarlett2_usb_set_mix(mixer, mix_num);
3165 if (err == 0)
3166 err = 1;
3167
3168unlock:
3169 mutex_unlock(&private->data_mutex);
3170 return err;
3171}
3172
3173static const DECLARE_TLV_DB_MINMAX(
3174 db_scale_scarlett2_mixer,
3175 SCARLETT2_MIXER_MIN_DB * 100,
3176 SCARLETT2_MIXER_MAX_DB * 100
3177);
3178
3179static const struct snd_kcontrol_new scarlett2_mixer_ctl = {
3180 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3181 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
3182 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
3183 .name = "",
3184 .info = scarlett2_mixer_ctl_info,
3185 .get = scarlett2_mixer_ctl_get,
3186 .put = scarlett2_mixer_ctl_put,
3187 .private_value = SCARLETT2_MIXER_MAX_DB, /* max value */
3188 .tlv = { .p = db_scale_scarlett2_mixer }
3189};
3190
3191static int scarlett2_add_mixer_ctls(struct usb_mixer_interface *mixer)
3192{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303193 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303194 const struct scarlett2_device_info *info = private->info;
3195 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303196 int err, i, j;
3197 int index;
3198 char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3199
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303200 int num_inputs =
3201 port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT];
3202 int num_outputs =
3203 port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303204
Geoffrey D. Bennettb677b6c2021-06-21 02:16:30 +09303205 for (i = 0, index = 0; i < num_outputs; i++)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303206 for (j = 0; j < num_inputs; j++, index++) {
3207 snprintf(s, sizeof(s),
3208 "Mix %c Input %02d Playback Volume",
3209 'A' + i, j + 1);
3210 err = scarlett2_add_new_ctl(mixer, &scarlett2_mixer_ctl,
3211 index, 1, s, NULL);
3212 if (err < 0)
3213 return err;
3214 }
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303215
3216 return 0;
3217}
3218
3219/*** Mux Source Selection Controls ***/
3220
3221static int scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol *kctl,
3222 struct snd_ctl_elem_info *uinfo)
3223{
3224 struct usb_mixer_elem_info *elem = kctl->private_data;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303225 struct scarlett2_data *private = elem->head.mixer->private_data;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303226 const struct scarlett2_device_info *info = private->info;
3227 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303228 unsigned int item = uinfo->value.enumerated.item;
3229 int items = private->num_mux_srcs;
3230 int port_type;
3231
3232 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3233 uinfo->count = elem->channels;
3234 uinfo->value.enumerated.items = items;
3235
3236 if (item >= items)
3237 item = uinfo->value.enumerated.item = items - 1;
3238
3239 for (port_type = 0;
3240 port_type < SCARLETT2_PORT_TYPE_COUNT;
3241 port_type++) {
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303242 if (item < port_count[port_type][SCARLETT2_PORT_IN]) {
3243 const struct scarlett2_port *port =
3244 &scarlett2_ports[port_type];
3245
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303246 sprintf(uinfo->value.enumerated.name,
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303247 port->src_descr, item + port->src_num_offset);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303248 return 0;
3249 }
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303250 item -= port_count[port_type][SCARLETT2_PORT_IN];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303251 }
3252
3253 return -EINVAL;
3254}
3255
3256static int scarlett2_mux_src_enum_ctl_get(struct snd_kcontrol *kctl,
3257 struct snd_ctl_elem_value *ucontrol)
3258{
3259 struct usb_mixer_elem_info *elem = kctl->private_data;
Geoffrey D. Bennett8df25eb2021-06-23 02:33:50 +09303260 struct usb_mixer_interface *mixer = elem->head.mixer;
3261 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09303262 const struct scarlett2_device_info *info = private->info;
3263 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3264 int line_out_count =
3265 port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
3266 int index = elem->control;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303267
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09303268 if (index < line_out_count)
3269 index = line_out_remap(private, index);
3270
Geoffrey D. Bennett8df25eb2021-06-23 02:33:50 +09303271 mutex_lock(&private->data_mutex);
3272 if (private->mux_updated)
3273 scarlett2_usb_get_mux(mixer);
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09303274 ucontrol->value.enumerated.item[0] = private->mux[index];
Geoffrey D. Bennett8df25eb2021-06-23 02:33:50 +09303275 mutex_unlock(&private->data_mutex);
3276
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303277 return 0;
3278}
3279
3280static int scarlett2_mux_src_enum_ctl_put(struct snd_kcontrol *kctl,
3281 struct snd_ctl_elem_value *ucontrol)
3282{
3283 struct usb_mixer_elem_info *elem = kctl->private_data;
3284 struct usb_mixer_interface *mixer = elem->head.mixer;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303285 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09303286 const struct scarlett2_device_info *info = private->info;
3287 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
3288 int line_out_count =
3289 port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303290 int index = elem->control;
3291 int oval, val, err = 0;
3292
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09303293 if (index < line_out_count)
3294 index = line_out_remap(private, index);
3295
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303296 mutex_lock(&private->data_mutex);
3297
3298 oval = private->mux[index];
Geoffrey D. Bennett64c02a92021-06-21 02:16:47 +09303299 val = min(ucontrol->value.enumerated.item[0],
3300 private->num_mux_srcs - 1U);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303301
3302 if (oval == val)
3303 goto unlock;
3304
3305 private->mux[index] = val;
3306 err = scarlett2_usb_set_mux(mixer);
3307 if (err == 0)
3308 err = 1;
3309
3310unlock:
3311 mutex_unlock(&private->data_mutex);
3312 return err;
3313}
3314
3315static const struct snd_kcontrol_new scarlett2_mux_src_enum_ctl = {
3316 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3317 .name = "",
3318 .info = scarlett2_mux_src_enum_ctl_info,
3319 .get = scarlett2_mux_src_enum_ctl_get,
3320 .put = scarlett2_mux_src_enum_ctl_put,
3321};
3322
3323static int scarlett2_add_mux_enums(struct usb_mixer_interface *mixer)
3324{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303325 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303326 const struct scarlett2_device_info *info = private->info;
3327 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303328 int port_type, channel, i;
3329
3330 for (i = 0, port_type = 0;
3331 port_type < SCARLETT2_PORT_TYPE_COUNT;
3332 port_type++) {
3333 for (channel = 0;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303334 channel < port_count[port_type][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303335 channel++, i++) {
3336 int err;
3337 char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303338 const char *const descr =
3339 scarlett2_ports[port_type].dst_descr;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303340
3341 snprintf(s, sizeof(s) - 5, descr, channel + 1);
3342 strcat(s, " Enum");
3343
3344 err = scarlett2_add_new_ctl(mixer,
3345 &scarlett2_mux_src_enum_ctl,
Geoffrey D. Bennettf02da652021-06-23 02:33:45 +09303346 i, 1, s,
3347 &private->mux_ctls[i]);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303348 if (err < 0)
3349 return err;
3350 }
3351 }
3352
3353 return 0;
3354}
3355
3356/*** Meter Controls ***/
3357
3358static int scarlett2_meter_ctl_info(struct snd_kcontrol *kctl,
3359 struct snd_ctl_elem_info *uinfo)
3360{
3361 struct usb_mixer_elem_info *elem = kctl->private_data;
3362
3363 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3364 uinfo->count = elem->channels;
3365 uinfo->value.integer.min = 0;
3366 uinfo->value.integer.max = 4095;
3367 uinfo->value.integer.step = 1;
3368 return 0;
3369}
3370
3371static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl,
3372 struct snd_ctl_elem_value *ucontrol)
3373{
3374 struct usb_mixer_elem_info *elem = kctl->private_data;
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +09303375 u16 meter_levels[SCARLETT2_MAX_METERS];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303376 int i, err;
3377
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +09303378 err = scarlett2_usb_get_meter_levels(elem->head.mixer, elem->channels,
3379 meter_levels);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303380 if (err < 0)
3381 return err;
3382
3383 for (i = 0; i < elem->channels; i++)
3384 ucontrol->value.integer.value[i] = meter_levels[i];
3385
3386 return 0;
3387}
3388
3389static const struct snd_kcontrol_new scarlett2_meter_ctl = {
3390 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
3391 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
3392 .name = "",
3393 .info = scarlett2_meter_ctl_info,
3394 .get = scarlett2_meter_ctl_get
3395};
3396
3397static int scarlett2_add_meter_ctl(struct usb_mixer_interface *mixer)
3398{
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +09303399 struct scarlett2_data *private = mixer->private_data;
3400
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09303401 /* devices without a mixer also don't support reporting levels */
3402 if (!private->info->has_mixer)
3403 return 0;
3404
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303405 return scarlett2_add_new_ctl(mixer, &scarlett2_meter_ctl,
Geoffrey D. Bennettb126bba2021-06-22 03:39:46 +09303406 0, private->num_mux_dsts,
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303407 "Level Meter", NULL);
3408}
3409
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +09303410/*** MSD Controls ***/
3411
3412static int scarlett2_msd_ctl_get(struct snd_kcontrol *kctl,
3413 struct snd_ctl_elem_value *ucontrol)
3414{
3415 struct usb_mixer_elem_info *elem = kctl->private_data;
3416 struct scarlett2_data *private = elem->head.mixer->private_data;
3417
3418 ucontrol->value.integer.value[0] = private->msd_switch;
3419 return 0;
3420}
3421
3422static int scarlett2_msd_ctl_put(struct snd_kcontrol *kctl,
3423 struct snd_ctl_elem_value *ucontrol)
3424{
3425 struct usb_mixer_elem_info *elem = kctl->private_data;
3426 struct usb_mixer_interface *mixer = elem->head.mixer;
3427 struct scarlett2_data *private = mixer->private_data;
3428
3429 int oval, val, err = 0;
3430
3431 mutex_lock(&private->data_mutex);
3432
3433 oval = private->msd_switch;
3434 val = !!ucontrol->value.integer.value[0];
3435
3436 if (oval == val)
3437 goto unlock;
3438
3439 private->msd_switch = val;
3440
3441 /* Send switch change to the device */
3442 err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MSD_SWITCH,
3443 0, val);
Geoffrey D. Bennett459d2322021-06-27 22:52:56 +09303444 if (err == 0)
3445 err = 1;
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +09303446
3447unlock:
3448 mutex_unlock(&private->data_mutex);
3449 return err;
3450}
3451
3452static const struct snd_kcontrol_new scarlett2_msd_ctl = {
3453 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3454 .name = "",
3455 .info = snd_ctl_boolean_mono_info,
3456 .get = scarlett2_msd_ctl_get,
3457 .put = scarlett2_msd_ctl_put,
3458};
3459
3460static int scarlett2_add_msd_ctl(struct usb_mixer_interface *mixer)
3461{
3462 struct scarlett2_data *private = mixer->private_data;
3463 const struct scarlett2_device_info *info = private->info;
3464
3465 if (!info->has_msd_mode)
3466 return 0;
3467
3468 /* If MSD mode is off, hide the switch by default */
3469 if (!private->msd_switch && !(mixer->chip->setup & SCARLETT2_MSD_ENABLE))
3470 return 0;
3471
3472 /* Add MSD control */
3473 return scarlett2_add_new_ctl(mixer, &scarlett2_msd_ctl,
Geoffrey D. Bennettcdf72832021-07-23 05:41:53 +09303474 0, 1, "MSD Mode Switch", NULL);
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +09303475}
3476
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303477/*** Cleanup/Suspend Callbacks ***/
3478
3479static void scarlett2_private_free(struct usb_mixer_interface *mixer)
3480{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303481 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303482
3483 cancel_delayed_work_sync(&private->work);
3484 kfree(private);
3485 mixer->private_data = NULL;
3486}
3487
3488static void scarlett2_private_suspend(struct usb_mixer_interface *mixer)
3489{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303490 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303491
3492 if (cancel_delayed_work_sync(&private->work))
3493 scarlett2_config_save(private->mixer);
3494}
3495
3496/*** Initialisation ***/
3497
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303498static void scarlett2_count_mux_io(struct scarlett2_data *private)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303499{
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303500 const struct scarlett2_device_info *info = private->info;
3501 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09303502 int port_type, srcs = 0, dsts = 0;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303503
3504 for (port_type = 0;
3505 port_type < SCARLETT2_PORT_TYPE_COUNT;
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09303506 port_type++) {
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303507 srcs += port_count[port_type][SCARLETT2_PORT_IN];
3508 dsts += port_count[port_type][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303509 }
3510
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09303511 private->num_mux_srcs = srcs;
3512 private->num_mux_dsts = dsts;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303513}
3514
Geoffrey D. Bennett6c0a2072021-06-21 02:16:52 +09303515/* Look through the interface descriptors for the Focusrite Control
3516 * interface (bInterfaceClass = 255 Vendor Specific Class) and set
3517 * bInterfaceNumber, bEndpointAddress, wMaxPacketSize, and bInterval
3518 * in private
3519 */
3520static int scarlett2_find_fc_interface(struct usb_device *dev,
3521 struct scarlett2_data *private)
3522{
3523 struct usb_host_config *config = dev->actconfig;
3524 int i;
3525
3526 for (i = 0; i < config->desc.bNumInterfaces; i++) {
3527 struct usb_interface *intf = config->interface[i];
3528 struct usb_interface_descriptor *desc =
3529 &intf->altsetting[0].desc;
3530 struct usb_endpoint_descriptor *epd;
3531
3532 if (desc->bInterfaceClass != 255)
3533 continue;
3534
3535 epd = get_endpoint(intf->altsetting, 0);
3536 private->bInterfaceNumber = desc->bInterfaceNumber;
3537 private->bEndpointAddress = epd->bEndpointAddress &
3538 USB_ENDPOINT_NUMBER_MASK;
3539 private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize);
3540 private->bInterval = epd->bInterval;
3541 return 0;
3542 }
3543
3544 return -EINVAL;
3545}
3546
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +09303547/* Initialise private data */
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303548static int scarlett2_init_private(struct usb_mixer_interface *mixer,
3549 const struct scarlett2_device_info *info)
3550{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303551 struct scarlett2_data *private =
3552 kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303553
3554 if (!private)
3555 return -ENOMEM;
3556
3557 mutex_init(&private->usb_mutex);
3558 mutex_init(&private->data_mutex);
3559 INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work);
Geoffrey D. Bennett6c0a2072021-06-21 02:16:52 +09303560
3561 mixer->private_data = private;
3562 mixer->private_free = scarlett2_private_free;
3563 mixer->private_suspend = scarlett2_private_suspend;
3564
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303565 private->info = info;
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09303566 scarlett2_count_mux_io(private);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303567 private->scarlett2_seq = 0;
3568 private->mixer = mixer;
Geoffrey D. Bennett6c0a2072021-06-21 02:16:52 +09303569
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +09303570 return scarlett2_find_fc_interface(mixer->chip->dev, private);
3571}
3572
3573/* Cargo cult proprietary initialisation sequence */
3574static int scarlett2_usb_init(struct usb_mixer_interface *mixer)
3575{
3576 struct usb_device *dev = mixer->chip->dev;
3577 struct scarlett2_data *private = mixer->private_data;
3578 u8 buf[24];
3579 int err;
3580
3581 if (usb_pipe_type_check(dev, usb_sndctrlpipe(dev, 0)))
3582 return -EINVAL;
3583
3584 /* step 0 */
3585 err = scarlett2_usb_rx(dev, private->bInterfaceNumber,
3586 SCARLETT2_USB_CMD_INIT, buf, sizeof(buf));
Geoffrey D. Bennett6c0a2072021-06-21 02:16:52 +09303587 if (err < 0)
3588 return err;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303589
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +09303590 /* step 1 */
3591 private->scarlett2_seq = 1;
3592 err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_1, NULL, 0, NULL, 0);
3593 if (err < 0)
3594 return err;
3595
3596 /* step 2 */
3597 private->scarlett2_seq = 1;
3598 return scarlett2_usb(mixer, SCARLETT2_USB_INIT_2, NULL, 0, NULL, 84);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303599}
3600
Geoffrey D. Bennett2661f032021-06-08 04:43:25 +09303601/* Read configuration from the interface on start */
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303602static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
3603{
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303604 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303605 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303606 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303607 int num_line_out =
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303608 port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett2661f032021-06-08 04:43:25 +09303609 int num_mixer_out =
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303610 port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303611 struct scarlett2_usb_volume_status volume_status;
3612 int err, i;
3613
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +09303614 if (info->has_msd_mode) {
3615 err = scarlett2_usb_get_config(
3616 mixer, SCARLETT2_CONFIG_MSD_SWITCH,
3617 1, &private->msd_switch);
3618 if (err < 0)
3619 return err;
3620
3621 /* no other controls are created if MSD mode is on */
3622 if (private->msd_switch)
3623 return 0;
3624 }
3625
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09303626 err = scarlett2_update_input_other(mixer);
3627 if (err < 0)
3628 return err;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303629
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09303630 err = scarlett2_update_monitor_other(mixer);
3631 if (err < 0)
3632 return err;
3633
Geoffrey D. Bennett2fa96272021-06-23 02:32:31 +09303634 /* the rest of the configuration is for devices with a mixer */
3635 if (!info->has_mixer)
3636 return 0;
3637
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +09303638 err = scarlett2_update_sync(mixer);
3639 if (err < 0)
3640 return err;
3641
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303642 err = scarlett2_usb_get_volume_status(mixer, &volume_status);
3643 if (err < 0)
3644 return err;
3645
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09303646 if (info->line_out_hw_vol)
3647 for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++)
3648 private->dim_mute[i] = !!volume_status.dim_mute[i];
3649
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303650 private->master_vol = clamp(
3651 volume_status.master_vol + SCARLETT2_VOLUME_BIAS,
3652 0, SCARLETT2_VOLUME_BIAS);
3653
3654 for (i = 0; i < num_line_out; i++) {
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09303655 int volume, mute;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303656
3657 private->vol_sw_hw_switch[i] =
3658 info->line_out_hw_vol
3659 && volume_status.sw_hw_switch[i];
3660
3661 volume = private->vol_sw_hw_switch[i]
3662 ? volume_status.master_vol
3663 : volume_status.sw_vol[i];
3664 volume = clamp(volume + SCARLETT2_VOLUME_BIAS,
3665 0, SCARLETT2_VOLUME_BIAS);
3666 private->vol[i] = volume;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303667
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09303668 mute = private->vol_sw_hw_switch[i]
3669 ? private->dim_mute[SCARLETT2_BUTTON_MUTE]
3670 : volume_status.mute_switch[i];
3671 private->mute_switch[i] = mute;
3672 }
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303673
Geoffrey D. Bennett2661f032021-06-08 04:43:25 +09303674 for (i = 0; i < num_mixer_out; i++) {
3675 err = scarlett2_usb_get_mix(mixer, i);
3676 if (err < 0)
3677 return err;
3678 }
3679
Geoffrey D. Bennettd6f9afe92021-06-08 04:43:51 +09303680 return scarlett2_usb_get_mux(mixer);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303681}
3682
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +09303683/* Notify on sync change */
3684static void scarlett2_notify_sync(
3685 struct usb_mixer_interface *mixer)
3686{
3687 struct scarlett2_data *private = mixer->private_data;
3688
3689 private->sync_updated = 1;
3690
3691 snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
3692 &private->sync_ctl->id);
3693}
3694
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303695/* Notify on monitor change */
3696static void scarlett2_notify_monitor(
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303697 struct usb_mixer_interface *mixer)
3698{
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09303699 struct snd_card *card = mixer->chip->card;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303700 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennette840ee32021-06-22 03:39:20 +09303701 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303702 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303703 int num_line_out =
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303704 port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303705 int i;
3706
Geoffrey D. Bennette840ee32021-06-22 03:39:20 +09303707 /* if line_out_hw_vol is 0, there are no controls to update */
3708 if (!info->line_out_hw_vol)
3709 return;
3710
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303711 private->vol_updated = 1;
3712
3713 snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
3714 &private->master_vol_ctl->id);
3715
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09303716 for (i = 0; i < num_line_out; i++)
3717 if (private->vol_sw_hw_switch[line_out_remap(private, i)])
3718 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3719 &private->vol_ctls[i]->id);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303720}
3721
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303722/* Notify on dim/mute change */
3723static void scarlett2_notify_dim_mute(
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303724 struct usb_mixer_interface *mixer)
3725{
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09303726 struct snd_card *card = mixer->chip->card;
Geoffrey D. Bennette46f2192021-06-21 02:16:39 +09303727 struct scarlett2_data *private = mixer->private_data;
Geoffrey D. Bennett03bdbcf2021-06-21 02:16:34 +09303728 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303729 const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09303730 int num_line_out =
Geoffrey D. Bennette2cc91a2021-06-22 03:39:43 +09303731 port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303732 int i;
3733
3734 private->vol_updated = 1;
3735
Geoffrey D. Bennett03bdbcf2021-06-21 02:16:34 +09303736 if (!info->line_out_hw_vol)
3737 return;
3738
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303739 for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++)
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09303740 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303741 &private->dim_mute_ctls[i]->id);
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09303742
3743 for (i = 0; i < num_line_out; i++)
Geoffrey D. Bennett9cfe1272021-06-23 02:33:16 +09303744 if (private->vol_sw_hw_switch[line_out_remap(private, i)])
Geoffrey D. Bennett0c88f9d2021-06-22 03:39:39 +09303745 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3746 &private->mute_ctls[i]->id);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303747}
3748
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +09303749/* Notify on "input other" change (level/pad/air) */
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09303750static void scarlett2_notify_input_other(
3751 struct usb_mixer_interface *mixer)
3752{
3753 struct snd_card *card = mixer->chip->card;
3754 struct scarlett2_data *private = mixer->private_data;
3755 const struct scarlett2_device_info *info = private->info;
3756 int i;
3757
3758 private->input_other_updated = 1;
3759
3760 for (i = 0; i < info->level_input_count; i++)
3761 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3762 &private->level_ctls[i]->id);
3763 for (i = 0; i < info->pad_input_count; i++)
3764 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3765 &private->pad_ctls[i]->id);
Geoffrey D. Bennettdbbd4f92021-06-23 02:32:36 +09303766 for (i = 0; i < info->air_input_count; i++)
3767 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3768 &private->air_ctls[i]->id);
Geoffrey D. Bennettae58a1a2021-06-23 02:32:40 +09303769 for (i = 0; i < info->phantom_count; i++)
3770 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3771 &private->phantom_ctls[i]->id);
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09303772}
3773
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09303774/* Notify on "monitor other" change (direct monitor, speaker
3775 * switching, talkback)
3776 */
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09303777static void scarlett2_notify_monitor_other(
3778 struct usb_mixer_interface *mixer)
3779{
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09303780 struct snd_card *card = mixer->chip->card;
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09303781 struct scarlett2_data *private = mixer->private_data;
3782 const struct scarlett2_device_info *info = private->info;
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09303783
3784 private->monitor_other_updated = 1;
3785
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09303786 if (info->direct_monitor) {
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09303787 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3788 &private->direct_monitor_ctl->id);
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09303789 return;
3790 }
3791
3792 if (info->has_speaker_switching)
3793 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3794 &private->speaker_switching_ctl->id);
3795
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09303796 if (info->has_talkback)
3797 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3798 &private->talkback_ctl->id);
3799
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09303800 /* if speaker switching was recently enabled or disabled,
3801 * invalidate the dim/mute and mux enum controls
3802 */
3803 if (private->speaker_switching_switched) {
3804 int i;
3805
3806 scarlett2_notify_dim_mute(mixer);
3807
3808 private->speaker_switching_switched = 0;
3809 private->mux_updated = 1;
3810
3811 for (i = 0; i < private->num_mux_dsts; i++)
3812 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
3813 &private->mux_ctls[i]->id);
3814 }
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09303815}
3816
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303817/* Interrupt callback */
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303818static void scarlett2_notify(struct urb *urb)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303819{
3820 struct usb_mixer_interface *mixer = urb->context;
3821 int len = urb->actual_length;
3822 int ustatus = urb->status;
3823 u32 data;
3824
Geoffrey D. Bennett411b22e2021-06-21 02:16:32 +09303825 if (ustatus != 0 || len != 8)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303826 goto requeue;
3827
Geoffrey D. Bennett411b22e2021-06-21 02:16:32 +09303828 data = le32_to_cpu(*(__le32 *)urb->transfer_buffer);
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +09303829 if (data & SCARLETT2_USB_NOTIFY_SYNC)
3830 scarlett2_notify_sync(mixer);
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303831 if (data & SCARLETT2_USB_NOTIFY_MONITOR)
3832 scarlett2_notify_monitor(mixer);
3833 if (data & SCARLETT2_USB_NOTIFY_DIM_MUTE)
3834 scarlett2_notify_dim_mute(mixer);
Geoffrey D. Bennetta5b36122021-06-23 02:31:44 +09303835 if (data & SCARLETT2_USB_NOTIFY_INPUT_OTHER)
3836 scarlett2_notify_input_other(mixer);
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09303837 if (data & SCARLETT2_USB_NOTIFY_MONITOR_OTHER)
3838 scarlett2_notify_monitor_other(mixer);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303839
3840requeue:
3841 if (ustatus != -ENOENT &&
3842 ustatus != -ECONNRESET &&
3843 ustatus != -ESHUTDOWN) {
3844 urb->dev = mixer->chip->dev;
3845 usb_submit_urb(urb, GFP_ATOMIC);
3846 }
3847}
3848
Geoffrey D. Bennettdbd82c02021-06-21 02:16:36 +09303849static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303850{
3851 struct usb_device *dev = mixer->chip->dev;
Geoffrey D. Bennett6c0a2072021-06-21 02:16:52 +09303852 struct scarlett2_data *private = mixer->private_data;
3853 unsigned int pipe = usb_rcvintpipe(dev, private->bEndpointAddress);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303854 void *transfer_buffer;
3855
3856 if (mixer->urb) {
3857 usb_audio_err(mixer->chip,
3858 "%s: mixer urb already in use!\n", __func__);
3859 return 0;
3860 }
3861
Greg Kroah-Hartmanfcc2cc12020-09-14 17:37:46 +02003862 if (usb_pipe_type_check(dev, pipe))
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303863 return -EINVAL;
3864
3865 mixer->urb = usb_alloc_urb(0, GFP_KERNEL);
3866 if (!mixer->urb)
3867 return -ENOMEM;
3868
Geoffrey D. Bennett6c0a2072021-06-21 02:16:52 +09303869 transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303870 if (!transfer_buffer)
3871 return -ENOMEM;
3872
3873 usb_fill_int_urb(mixer->urb, dev, pipe,
Geoffrey D. Bennett6c0a2072021-06-21 02:16:52 +09303874 transfer_buffer, private->wMaxPacketSize,
3875 scarlett2_notify, mixer, private->bInterval);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303876
3877 return usb_submit_urb(mixer->urb, GFP_KERNEL);
3878}
3879
Geoffrey D. Bennett6fd9d692021-06-22 03:39:33 +09303880static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303881{
Geoffrey D. Bennett6fd9d692021-06-22 03:39:33 +09303882 const struct scarlett2_device_info **info = scarlett2_devices;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303883 int err;
3884
Geoffrey D. Bennett6fd9d692021-06-22 03:39:33 +09303885 /* Find device in scarlett2_devices */
3886 while (*info && (*info)->usb_id != mixer->chip->usb_id)
3887 info++;
3888 if (!*info)
3889 return -EINVAL;
3890
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +09303891 /* Initialise private data */
Geoffrey D. Bennett6fd9d692021-06-22 03:39:33 +09303892 err = scarlett2_init_private(mixer, *info);
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303893 if (err < 0)
3894 return err;
3895
Geoffrey D. Bennettacf91b82021-06-22 03:39:13 +09303896 /* Send proprietary USB initialisation sequence */
3897 err = scarlett2_usb_init(mixer);
3898 if (err < 0)
3899 return err;
3900
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303901 /* Read volume levels and controls from the interface */
3902 err = scarlett2_read_configs(mixer);
3903 if (err < 0)
3904 return err;
3905
Geoffrey D. Bennett303f2042021-06-23 02:31:52 +09303906 /* Create the MSD control */
3907 err = scarlett2_add_msd_ctl(mixer);
3908 if (err < 0)
3909 return err;
3910
3911 /* If MSD mode is enabled, don't create any other controls */
3912 if (((struct scarlett2_data *)mixer->private_data)->msd_switch)
3913 return 0;
3914
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303915 /* Create the analogue output controls */
3916 err = scarlett2_add_line_out_ctls(mixer);
3917 if (err < 0)
3918 return err;
3919
3920 /* Create the analogue input controls */
3921 err = scarlett2_add_line_in_ctls(mixer);
3922 if (err < 0)
3923 return err;
3924
3925 /* Create the input, output, and mixer mux input selections */
3926 err = scarlett2_add_mux_enums(mixer);
3927 if (err < 0)
3928 return err;
3929
3930 /* Create the matrix mixer controls */
3931 err = scarlett2_add_mixer_ctls(mixer);
3932 if (err < 0)
3933 return err;
3934
3935 /* Create the level meter controls */
3936 err = scarlett2_add_meter_ctl(mixer);
3937 if (err < 0)
3938 return err;
3939
Geoffrey D. Bennettf3c61042021-06-22 03:39:24 +09303940 /* Create the sync control */
3941 err = scarlett2_add_sync_ctl(mixer);
3942 if (err < 0)
3943 return err;
3944
Geoffrey D. Bennett6ef9fa42021-06-23 02:33:08 +09303945 /* Create the direct monitor control */
3946 err = scarlett2_add_direct_monitor_ctl(mixer);
3947 if (err < 0)
3948 return err;
3949
Geoffrey D. Bennette914d842021-06-23 02:33:58 +09303950 /* Create the speaker switching control */
3951 err = scarlett2_add_speaker_switch_ctl(mixer);
3952 if (err < 0)
3953 return err;
3954
Geoffrey D. Bennettd5bda7e2021-06-23 02:34:13 +09303955 /* Create the talkback controls */
3956 err = scarlett2_add_talkback_ctls(mixer);
3957 if (err < 0)
3958 return err;
3959
Geoffrey D. Bennette840ee32021-06-22 03:39:20 +09303960 /* Set up the interrupt polling */
3961 err = scarlett2_init_notify(mixer);
3962 if (err < 0)
3963 return err;
Geoffrey D. Bennett9e4d5c12019-07-29 00:42:45 +09303964
3965 return 0;
3966}
Geoffrey D. Bennett265d1a92021-05-21 17:50:13 +09303967
3968int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
3969{
3970 struct snd_usb_audio *chip = mixer->chip;
Geoffrey D. Bennett265d1a92021-05-21 17:50:13 +09303971 int err;
3972
3973 /* only use UAC_VERSION_2 */
3974 if (!mixer->protocol)
3975 return 0;
3976
Geoffrey D. Bennett265d1a92021-05-21 17:50:13 +09303977 if (!(chip->setup & SCARLETT2_ENABLE)) {
3978 usb_audio_info(chip,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +09303979 "Focusrite Scarlett Gen 2/3 Mixer Driver disabled; "
Geoffrey D. Bennett265d1a92021-05-21 17:50:13 +09303980 "use options snd_usb_audio vid=0x%04x pid=0x%04x "
3981 "device_setup=1 to enable and report any issues "
3982 "to g@b4.vu",
3983 USB_ID_VENDOR(chip->usb_id),
3984 USB_ID_PRODUCT(chip->usb_id));
3985 return 0;
3986 }
3987
3988 usb_audio_info(chip,
Geoffrey D. Bennett4be47792021-06-23 02:31:37 +09303989 "Focusrite Scarlett Gen 2/3 Mixer Driver enabled pid=0x%04x",
Geoffrey D. Bennett265d1a92021-05-21 17:50:13 +09303990 USB_ID_PRODUCT(chip->usb_id));
3991
Geoffrey D. Bennett6fd9d692021-06-22 03:39:33 +09303992 err = snd_scarlett_gen2_controls_create(mixer);
Geoffrey D. Bennett265d1a92021-05-21 17:50:13 +09303993 if (err < 0)
3994 usb_audio_err(mixer->chip,
3995 "Error initialising Scarlett Mixer Driver: %d",
3996 err);
3997
3998 return err;
3999}