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