Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  mixer_scarlett2.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 *   Focusrite Scarlett 2 Protocol Driver for ALSA
 *   (including Scarlett 2nd Gen, 3rd Gen, 4th Gen, Clarett USB, and
 *   Clarett+ series products)
 *
 *   Supported models:
 *   - 6i6/18i8/18i20 Gen 2
 *   - Solo/2i2/4i4/8i6/18i8/18i20 Gen 3
 *   - Solo/2i2/4i4 Gen 4
 *   - Clarett 2Pre/4Pre/8Pre USB
 *   - Clarett+ 2Pre/4Pre/8Pre
 *
 *   Copyright (c) 2018-2024 by Geoffrey D. Bennett <g at b4.vu>
 *   Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com>
 *   Copyright (c) 2022 by Christian Colglazier <christian@cacolglazier.com>
 *
 *   Based on the Scarlett (Gen 1) Driver for ALSA:
 *
 *   Copyright (c) 2013 by Tobias Hoffmann
 *   Copyright (c) 2013 by Robin Gareus <robin at gareus.org>
 *   Copyright (c) 2002 by Takashi Iwai <tiwai at suse.de>
 *   Copyright (c) 2014 by Chris J Arges <chris.j.arges at canonical.com>
 *
 *   Many codes borrowed from audio.c by
 *     Alan Cox (alan at lxorguk.ukuu.org.uk)
 *     Thomas Sailer (sailer at ife.ee.ethz.ch)
 *
 *   Code cleanup:
 *   David Henningsson <david.henningsson at canonical.com>
 */


/* The protocol was reverse engineered by looking at the communication
 * between Focusrite Control 2.3.4 and the Focusrite(R) Scarlett 18i20
 * (firmware 1083) using usbmon in July-August 2018.
 *
 * Scarlett 18i8 support added in April 2019.
 *
 * Scarlett 6i6 support added in June 2019 (thanks to Martin Wittmann
 * for providing usbmon output and testing).
 *
 * Scarlett 4i4/8i6 Gen 3 support added in May 2020 (thanks to Laurent
 * Debricon for donating a 4i4 and to Fredrik Unger for providing 8i6
 * usbmon output and testing).
 *
 * Scarlett 18i8/18i20 Gen 3 support added in June 2020 (thanks to
 * Darren Jaeckel, Alex Sedlack, and Clovis Lunel for providing usbmon
 * output, protocol traces and testing).
 *
 * Support for loading mixer volume and mux configuration from the
 * interface during driver initialisation added in May 2021 (thanks to
 * Vladimir Sadovnikov for figuring out how).
 *
 * Support for Solo/2i2 Gen 3 added in May 2021 (thanks to Alexander
 * Vorona for 2i2 protocol traces).
 *
 * Support for phantom power, direct monitoring, speaker switching,
 * and talkback added in May-June 2021.
 *
 * Support for Clarett+ 8Pre added in Aug 2022 by Christian
 * Colglazier.
 *
 * Support for Clarett 8Pre USB added in Sep 2023 (thanks to Philippe
 * Perrot for confirmation).
 *
 * Support for Clarett+ 4Pre and 2Pre added in Sep 2023 (thanks to
 * Gregory Rozzo for donating a 4Pre, and David Sherwood and Patrice
 * Peterson for usbmon output).
 *
 * Support for Clarett 2Pre and 4Pre USB added in Oct 2023.
 *
 * Support for firmware updates added in Dec 2023.
 *
 * Support for Scarlett Solo/2i2/4i4 Gen 4 added in Dec 2023 (thanks
 * to many LinuxMusicians people and to Focusrite for hardware
 * donations).
 *
 * This ALSA mixer gives access to (model-dependent):
 *  - input, output, mixer-matrix muxes
 *  - mixer-matrix gain stages
 *  - gain/volume/mute controls
 *  - level meters
 *  - line/inst level, pad, and air controls
 *  - phantom power, direct monitor, speaker switching, and talkback
 *    controls
 *  - disable/enable MSD mode
 *  - disable/enable standalone mode
 *  - input mute, gain, autogain, safe mode
 *  - direct monitor mixes
 *  - compressor and EQ
 *  - Bluetooth volume
 *
 * <ditaa>
 *    /--------------\    18chn            20chn     /--------------\
 *    | Hardware  in +--+------\    /-------------+--+ ALSA PCM out |
 *    \--------------/  |      |    |             |  \--------------/
 *                      |      |    |    /-----\  |
 *                      |      |    |    |     |  |
 *                      |      v    v    v     |  |
 *                      |   +---------------+  |  |
 *                      |    \ Matrix  Mux /   |  |
 *                      |     +-----+-----+    |  |
 *                      |           |          |  |
 *                      |           |18chn     |  |
 *                      |           |          |  |
 *                      |           |     10chn|  |
 *                      |           v          |  |
 *                      |     +------------+   |  |
 *                      |     | Mixer      |   |  |
 *                      |     |     Matrix |   |  |
 *                      |     |            |   |  |
 *                      |     | 18x10 Gain |   |  |
 *                      |     |   stages   |   |  |
 *                      |     +-----+------+   |  |
 *                      |           |          |  |
 *                      |18chn      |10chn     |  |20chn
 *                      |           |          |  |
 *                      |           +----------/  |
 *                      |           |             |
 *                      v           v             v
 *                      ===========================
 *               +---------------+       +--—------------+
 *                \ Output  Mux /         \ Capture Mux /
 *                 +---+---+---+           +-----+-----+
 *                     |   |                     |
 *                10chn|   |                     |18chn
 *                     |   |                     |
 *  /--------------\   |   |                     |   /--------------\
 *  | S/PDIF, ADAT |<--/   |10chn                \-->| ALSA PCM in  |
 *  | Hardware out |       |                         \--------------/
 *  \--------------/       |
 *                         v
 *                  +-------------+    Software gain per channel.
 *                  | Master Gain |<-- 18i20 only: Switch per channel
 *                  +------+------+    to select HW or SW gain control.
 *                         |
 *                         |10chn
 *  /--------------\       |
 *  | Analogue     |<------/
 *  | Hardware out |
 *  \--------------/
 * </ditaa>
 *
 * Gen 3/4 devices have a Mass Storage Device (MSD) mode where a small
 * disk with registration and driver download information is presented
 * to the host. To access the full functionality of the device without
 * proprietary software, MSD mode can be disabled by:
 * - holding down the 48V button for five seconds while powering on
 *   the device, or
 * - using this driver and alsamixer to change the "MSD Mode" setting
 *   to Off and power-cycling the device
 */


#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/moduleparam.h>

#include <sound/control.h>
#include <sound/tlv.h>
#include <sound/hwdep.h>

#include <uapi/sound/scarlett2.h>

#include "usbaudio.h"
#include "mixer.h"
#include "helper.h"

#include "mixer_scarlett2.h"
#include "fcp.h"

/* device_setup value to allow turning MSD mode back on */
#define SCARLETT2_MSD_ENABLE 0x02

/* device_setup value to disable this mixer driver */
#define SCARLETT2_DISABLE 0x04

/* device_setup value to use the FCP driver instead */
#define SCARLETT2_USE_FCP_DRIVER 0x08

/* some gui mixers can't handle negative ctl values */
#define SCARLETT2_VOLUME_BIAS 127

/* maximum preamp input gain value
 * (the corresponding value in dB is per-device)
 */

#define SCARLETT2_MAX_GAIN_VALUE 70

/* maximum Bluetooth volume value */
#define SCARLETT2_MAX_BLUETOOTH_VOLUME 30

/* mixer range from -80dB to +12dB in 0.5dB steps */
#define SCARLETT2_MIXER_MIN_DB -80
#define SCARLETT2_MIXER_BIAS (-SCARLETT2_MIXER_MIN_DB * 2)
#define SCARLETT2_MIXER_MAX_DB 12
#define SCARLETT2_MIXER_MAX_VALUE \
 ((SCARLETT2_MIXER_MAX_DB - SCARLETT2_MIXER_MIN_DB) * 2)
#define SCARLETT2_MIXER_VALUE_COUNT (SCARLETT2_MIXER_MAX_VALUE + 1)

/* map from (dB + 80) * 2 to mixer value
 * for dB in 0 .. 184: int(8192 * pow(10, ((dB - 160) / 2 / 20)))
 */

static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = {
 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8,
 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
 23, 24, 25, 27, 29, 30, 32, 34, 36, 38, 41, 43, 46, 48, 51,
 54, 57, 61, 65, 68, 73, 77, 81, 86, 91, 97, 103, 109, 115,
 122, 129, 137, 145, 154, 163, 173, 183, 194, 205, 217, 230,
 244, 259, 274, 290, 307, 326, 345, 365, 387, 410, 434, 460,
 487, 516, 547, 579, 614, 650, 689, 730, 773, 819, 867, 919,
 973, 1031, 1092, 1157, 1225, 1298, 1375, 1456, 1543, 1634,
 1731, 1833, 1942, 2057, 2179, 2308, 2445, 2590, 2744, 2906,
 3078, 3261, 3454, 3659, 3876, 4105, 4349, 4606, 4879, 5168,
 5475, 5799, 6143, 6507, 6892, 7301, 7733, 8192, 8677, 9191,
 9736, 10313, 10924, 11571, 12257, 12983, 13752, 14567, 15430,
 16345, 17313, 18339, 19426, 20577, 21796, 23088, 24456, 25905,
 27440, 29066, 30788, 32612
};

/* Maximum number of analogue outputs */
#define SCARLETT2_ANALOGUE_MAX 10

/* Maximum number of various input controls */
#define SCARLETT2_LEVEL_SWITCH_MAX 2
#define SCARLETT2_PAD_SWITCH_MAX 8
#define SCARLETT2_AIR_SWITCH_MAX 8
#define SCARLETT2_DSP_SWITCH_MAX 2
#define SCARLETT2_INPUT_MUTE_SWITCH_MAX 2
#define SCARLETT2_PHANTOM_SWITCH_MAX 2
#define SCARLETT2_INPUT_GAIN_MAX 2

/* Maximum number of inputs to the mixer */
#define SCARLETT2_INPUT_MIX_MAX 25

/* Maximum number of outputs from the mixer */
#define SCARLETT2_OUTPUT_MIX_MAX 12

/* Maximum number of mixer gain controls */
#define SCARLETT2_MIX_MAX (SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX)

/* Maximum number of direct monitor mixer gain controls
 * 1 (Solo) or 2 (2i2) direct monitor selections (Mono & Stereo)
 * 2 Mix outputs (A/Left & B/Right)
 * 4 Mix inputs
 */

#define SCARLETT2_MONITOR_MIX_MAX (2 * 2 * 4)

/* Maximum size of the data in the USB mux assignment message:
 * 20 inputs, 20 outputs, 25 matrix inputs, 12 spare
 */

#define SCARLETT2_MUX_MAX 77

/* Maximum number of sources (sum of input port counts) */
#define SCARLETT2_MAX_SRCS 52

/* Maximum number of meters (sum of output port counts) */
#define SCARLETT2_MAX_METERS 65

/* Compressor parameter data
 *
 * The compressor parameters are 32-bit fixed point values with 24
 * bits of fraction. Integer values are sufficient for the parameters
 * except for ratio which we can set in 0.5:1 steps.
 */

struct compressor_param {
 const char          *name;
 snd_ctl_elem_type_t  type;
 s32                  min;
 s32                  max;
 int                  scale_bits;
};

/* The available compressor parameters on the Vocaster:
 * - Enable: Off, On
 * - Threshold: -40dB to 0dB
 * - Ratio: 1:1 to 50:1 in 0.5:1 steps
 * - Knee Width: 0dB to 10dB
 * - Attack: 30ms to 127ms
 * - Release: 30ms to 127ms
 * - Makeup Gain: 0dB to 24dB
 */

static const struct compressor_param compressor_params[] = {
 { "Enable",      SNDRV_CTL_ELEM_TYPE_BOOLEAN,   0,   1,  0 },
 { "Threshold",   SNDRV_CTL_ELEM_TYPE_INTEGER, -40,   0, 24 },
 { "Ratio",       SNDRV_CTL_ELEM_TYPE_INTEGER,   2, 100, 23 },
 { "Knee Width",  SNDRV_CTL_ELEM_TYPE_INTEGER,   0,  10, 24 },
 { "Attack",      SNDRV_CTL_ELEM_TYPE_INTEGER,  30, 127, 24 },
 { "Release",     SNDRV_CTL_ELEM_TYPE_INTEGER,  30, 127, 24 },
 { "Makeup Gain", SNDRV_CTL_ELEM_TYPE_INTEGER,   0,  24, 24 },
};

#define SCARLETT2_COMPRESSOR_PARAM_COUNT ARRAY_SIZE(compressor_params)
#define SCARLETT2_COMPRESSOR_CTLS_MAX \
 (SCARLETT2_COMPRESSOR_PARAM_COUNT * SCARLETT2_DSP_SWITCH_MAX)

/* Maximum number of filter controls */
#define SCARLETT2_PRECOMP_FLT_CTLS_MAX (2 * SCARLETT2_DSP_SWITCH_MAX)
#define SCARLETT2_PEQ_FLT_CTLS_MAX (3 * SCARLETT2_DSP_SWITCH_MAX)

/* Number of biquad filter coefficients */
#define SCARLETT2_BIQUAD_COEFFS 5

/* Maximum number of filter coefficient values */
#define SCARLETT2_PRECOMP_FLT_VALUES_MAX \
 (SCARLETT2_PRECOMP_FLT_CTLS_MAX * SCARLETT2_BIQUAD_COEFFS)
#define SCARLETT2_PEQ_FLT_VALUES_MAX \
 (SCARLETT2_PEQ_FLT_CTLS_MAX * SCARLETT2_BIQUAD_COEFFS)

/* Maximum number of PEQ filter slots */
#define SCARLETT2_PEQ_FLT_SLOTS_MAX 4

/* Hardware port types:
 * - None (no input to mux)
 * - Analogue I/O
 * - S/PDIF I/O
 * - ADAT I/O
 * - Mixer I/O
 * - PCM I/O
 */

enum {
 SCARLETT2_PORT_TYPE_NONE,
 SCARLETT2_PORT_TYPE_ANALOGUE,
 SCARLETT2_PORT_TYPE_SPDIF,
 SCARLETT2_PORT_TYPE_ADAT,
 SCARLETT2_PORT_TYPE_MIX,
 SCARLETT2_PORT_TYPE_PCM,
 SCARLETT2_PORT_TYPE_COUNT
};

/* I/O count of each port type kept in struct scarlett2_ports */
enum {
 SCARLETT2_PORT_IN,
 SCARLETT2_PORT_OUT,
 SCARLETT2_PORT_DIRNS
};

/* Dim/Mute buttons on the 18i20 */
enum {
 SCARLETT2_BUTTON_MUTE,
 SCARLETT2_BUTTON_DIM,
 SCARLETT2_DIM_MUTE_COUNT
};

/* Autogain target values */

#define SCARLETT2_AG_TARGET_MIN (-30)

enum {
 SCARLETT2_AG_HOT_TARGET,
 SCARLETT2_AG_MEAN_TARGET,
 SCARLETT2_AG_PEAK_TARGET,
 SCARLETT2_AG_TARGET_COUNT
};

/* Flash Write State */
enum {
 SCARLETT2_FLASH_WRITE_STATE_IDLE,
 SCARLETT2_FLASH_WRITE_STATE_SELECTED,
 SCARLETT2_FLASH_WRITE_STATE_ERASING,
 SCARLETT2_FLASH_WRITE_STATE_WRITE
};

static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = {
 "Mute Playback Switch""Dim Playback Switch"
};

/* The autogain_status is set based on the autogain_switch and
 * raw_autogain_status values.
 *
 * If autogain_switch is set, autogain_status is set to 0 (Running).
 * The other status values are from the raw_autogain_status value + 1.
 */

static const char *const scarlett2_autogain_status_gen4[] = {
 "Running",
 "Success",
 "SuccessDRover",
 "WarnMinGainLimit",
 "FailDRunder",
 "FailMaxGainLimit",
 "FailClipped",
 "Cancelled",
 "Invalid",
 NULL
};

static const char *const scarlett2_autogain_status_vocaster[] = {
 "Running",
 "Success",
 "FailPG",
 "FailRange",
 "WarnMaxCap",
 "WarnMinCap",
 "Cancelled",
 "Invalid",
 NULL
};

/* Power Status Values */
enum {
 SCARLETT2_POWER_STATUS_EXT,
 SCARLETT2_POWER_STATUS_BUS,
 SCARLETT2_POWER_STATUS_FAIL,
 SCARLETT2_POWER_STATUS_COUNT
};

/* Notification callback functions */
struct scarlett2_notification {
 u32 mask;
 void (*func)(struct usb_mixer_interface *mixer);
};

static void scarlett2_notify_ack(struct usb_mixer_interface *mixer);
static void scarlett2_notify_sync(struct usb_mixer_interface *mixer);
static void scarlett2_notify_dim_mute(struct usb_mixer_interface *mixer);
static void scarlett2_notify_monitor(struct usb_mixer_interface *mixer);
static void scarlett2_notify_volume(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_level(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_pad(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_air(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_dsp(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_mute(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_phantom(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_other(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_select(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_gain(struct usb_mixer_interface *mixer);
static void scarlett2_notify_autogain(struct usb_mixer_interface *mixer);
static void scarlett2_notify_input_safe(struct usb_mixer_interface *mixer);
static void scarlett2_notify_monitor_other(struct usb_mixer_interface *mixer);
static void scarlett2_notify_direct_monitor(struct usb_mixer_interface *mixer);
static void scarlett2_notify_power_status(struct usb_mixer_interface *mixer);
static void scarlett2_notify_pcm_input_switch(
     struct usb_mixer_interface *mixer);
static void scarlett2_notify_bluetooth(struct usb_mixer_interface *mixer);

/* Arrays of notification callback functions */

static const struct scarlett2_notification scarlett2_notifications[] = {
 { 0x00000001, scarlett2_notify_ack },
 { 0x00000008, scarlett2_notify_sync },
 { 0x00200000, scarlett2_notify_dim_mute },
 { 0x00400000, scarlett2_notify_monitor },
 { 0x00800000, scarlett2_notify_input_other },
 { 0x01000000, scarlett2_notify_monitor_other },
 { 0, NULL }
};

static const struct scarlett2_notification scarlett3a_notifications[] = {
 { 0x00000001, scarlett2_notify_ack },
 { 0x00800000, scarlett2_notify_input_other },
 { 0x01000000, scarlett2_notify_direct_monitor },
 { 0, NULL }
};

static const struct scarlett2_notification vocaster_notifications[] = {
 { 0x00000001, scarlett2_notify_ack },
 { 0x00000008, scarlett2_notify_sync },
 { 0x00200000, scarlett2_notify_input_mute },
 { 0x00400000, scarlett2_notify_autogain },
 { 0x04000000, scarlett2_notify_input_dsp },
 { 0x08000000, scarlett2_notify_input_gain },
 { 0x10000000, scarlett2_notify_input_phantom },
 { 0x20000000, scarlett2_notify_bluetooth },
 { 0, NULL }
};

static const struct scarlett2_notification scarlett4_solo_notifications[] = {
 { 0x00000001, scarlett2_notify_ack },
 { 0x00000008, scarlett2_notify_sync },
 { 0x00400000, scarlett2_notify_input_air },
 { 0x00800000, scarlett2_notify_direct_monitor },
 { 0x01000000, scarlett2_notify_input_level },
 { 0x02000000, scarlett2_notify_input_phantom },
 { 0x04000000, scarlett2_notify_pcm_input_switch },
 { 0, NULL }
};

static const struct scarlett2_notification scarlett4_2i2_notifications[] = {
 { 0x00000001, scarlett2_notify_ack },
 { 0x00000008, scarlett2_notify_sync },
 { 0x00200000, scarlett2_notify_input_safe },
 { 0x00400000, scarlett2_notify_autogain },
 { 0x00800000, scarlett2_notify_input_air },
 { 0x01000000, scarlett2_notify_direct_monitor },
 { 0x02000000, scarlett2_notify_input_select },
 { 0x04000000, scarlett2_notify_input_level },
 { 0x08000000, scarlett2_notify_input_phantom },
 { 0x10000000, NULL }, /* power status, ignored */
 { 0x40000000, scarlett2_notify_input_gain },
 { 0x80000000, NULL }, /* power status, ignored */
 { 0, NULL }
};

static const struct scarlett2_notification scarlett4_4i4_notifications[] = {
 { 0x00000001, scarlett2_notify_ack },
 { 0x00000008, scarlett2_notify_sync },
 { 0x00200000, scarlett2_notify_input_safe },
 { 0x00400000, scarlett2_notify_autogain },
 { 0x00800000, scarlett2_notify_input_air },
 { 0x01000000, scarlett2_notify_input_select },
 { 0x02000000, scarlett2_notify_input_level },
 { 0x04000000, scarlett2_notify_input_phantom },
 { 0x08000000, scarlett2_notify_power_status }, /* power external */
 { 0x20000000, scarlett2_notify_input_gain },
 { 0x40000000, scarlett2_notify_power_status }, /* power status */
 { 0x80000000, scarlett2_notify_volume },
 { 0, NULL }
};

/* Configuration parameters that can be read and written */
enum {
 SCARLETT2_CONFIG_DIM_MUTE,
 SCARLETT2_CONFIG_LINE_OUT_VOLUME,
 SCARLETT2_CONFIG_MUTE_SWITCH,
 SCARLETT2_CONFIG_SW_HW_SWITCH,
 SCARLETT2_CONFIG_MASTER_VOLUME,
 SCARLETT2_CONFIG_HEADPHONE_VOLUME,
 SCARLETT2_CONFIG_LEVEL_SWITCH,
 SCARLETT2_CONFIG_PAD_SWITCH,
 SCARLETT2_CONFIG_MSD_SWITCH,
 SCARLETT2_CONFIG_AIR_SWITCH,
 SCARLETT2_CONFIG_DSP_SWITCH,
 SCARLETT2_CONFIG_COMPRESSOR_PARAMS,
 SCARLETT2_CONFIG_PRECOMP_FLT_SWITCH,
 SCARLETT2_CONFIG_PRECOMP_FLT_PARAMS,
 SCARLETT2_CONFIG_PEQ_FLT_SWITCH,
 SCARLETT2_CONFIG_PEQ_FLT_PARAMS,
 SCARLETT2_CONFIG_INPUT_MUTE_SWITCH,
 SCARLETT2_CONFIG_STANDALONE_SWITCH,
 SCARLETT2_CONFIG_PHANTOM_SWITCH,
 SCARLETT2_CONFIG_PHANTOM_PERSISTENCE,
 SCARLETT2_CONFIG_DIRECT_MONITOR,
 SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH,
 SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE,
 SCARLETT2_CONFIG_TALKBACK_MAP,
 SCARLETT2_CONFIG_AUTOGAIN_SWITCH,
 SCARLETT2_CONFIG_AUTOGAIN_STATUS,
 SCARLETT2_CONFIG_AG_HOT_TARGET,
 SCARLETT2_CONFIG_AG_MEAN_TARGET,
 SCARLETT2_CONFIG_AG_PEAK_TARGET,
 SCARLETT2_CONFIG_INPUT_GAIN,
 SCARLETT2_CONFIG_SAFE_SWITCH,
 SCARLETT2_CONFIG_INPUT_SELECT_SWITCH,
 SCARLETT2_CONFIG_INPUT_LINK_SWITCH,
 SCARLETT2_CONFIG_POWER_EXT,
 SCARLETT2_CONFIG_POWER_LOW,
 SCARLETT2_CONFIG_PCM_INPUT_SWITCH,
 SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN,
 SCARLETT2_CONFIG_BLUETOOTH_VOLUME,
 SCARLETT2_CONFIG_SPDIF_MODE,
 SCARLETT2_CONFIG_COUNT
};

/* Autogain target configuration parameters and names */

static const int scarlett2_ag_target_configs[] = {
 [SCARLETT2_AG_HOT_TARGET]  = SCARLETT2_CONFIG_AG_HOT_TARGET,
 [SCARLETT2_AG_MEAN_TARGET] = SCARLETT2_CONFIG_AG_MEAN_TARGET,
 [SCARLETT2_AG_PEAK_TARGET] = SCARLETT2_CONFIG_AG_PEAK_TARGET
};

static const char *const scarlett2_ag_target_names[] = {
 "Hot""Mean""Peak"
};

/* Location, size, and activation command number for the configuration
 * parameters. Size is in bits and may be 1, 8, 16, or 32.
 *
 * Vocaster and 4th Gen devices have a parameter buffer to set certain
 * configuration parameters. When pbuf is set, rather than writing to
 * the given offset, the channel and value are written to the
 * parameter buffer and the activate command is sent to the device.
 *
 * Some Gen 4 configuration parameters are written with 0x02 for a
 * desired value of 0x01, and 0x03 for 0x00. These are indicated with
 * mute set to 1. 0x02 and 0x03 are temporary values while the device
 * makes the change and the channel and/or corresponding DSP channel
 * output is muted.
 */

struct scarlett2_config {
 u16 offset;
 u8 size;
 u8 activate;
 u8 pbuf;
 u8 mute;
};

struct scarlett2_config_set {
 const struct scarlett2_notification *notifications;
 u16 param_buf_addr;
 const unsigned int *input_gain_tlv;
 const char *const *autogain_status_texts;
 const struct scarlett2_config items[SCARLETT2_CONFIG_COUNT];
};

/* Input gain TLV dB ranges */

static const DECLARE_TLV_DB_MINMAX(
 db_scale_vocaster_gain, 0, 70 * 100
);

static const DECLARE_TLV_DB_MINMAX(
 db_scale_gen4_gain, 0, 69 * 100
);

/* Gen 2 devices without SW/HW volume switch: 6i6, 18i8 */

static const struct scarlett2_config_set scarlett2_config_set_gen2a = {
 .notifications = scarlett2_notifications,
 .items = {
  [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
   .offset = 0x34, .size = 16, .activate = 1 },

  [SCARLETT2_CONFIG_MUTE_SWITCH] = {
   .offset = 0x5c, .size = 8, .activate = 1 },

  [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
   .offset = 0x7c, .size = 8, .activate = 7 },

  [SCARLETT2_CONFIG_PAD_SWITCH] = {
   .offset = 0x84, .size = 8, .activate = 8 },

  [SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
   .offset = 0x8d, .size = 8, .activate = 6 },
 }
};

/* Gen 2 devices with SW/HW volume switch: 18i20 */

static const struct scarlett2_config_set scarlett2_config_set_gen2b = {
 .notifications = scarlett2_notifications,
 .items = {
  [SCARLETT2_CONFIG_DIM_MUTE] = {
   .offset = 0x31, .size = 8, .activate = 2 },

  [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
   .offset = 0x34, .size = 16, .activate = 1 },

  [SCARLETT2_CONFIG_MUTE_SWITCH] = {
   .offset = 0x5c, .size = 8, .activate = 1 },

  [SCARLETT2_CONFIG_SW_HW_SWITCH] = {
   .offset = 0x66, .size = 8, .activate = 3 },

  [SCARLETT2_CONFIG_MASTER_VOLUME] = {
   .offset = 0x76, .size = 16 },

  [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
   .offset = 0x7c, .size = 8, .activate = 7 },

  [SCARLETT2_CONFIG_PAD_SWITCH] = {
   .offset = 0x84, .size = 8, .activate = 8 },

  [SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
   .offset = 0x8d, .size = 8, .activate = 6 },
 }
};

/* Gen 3 devices without a mixer (Solo and 2i2) */
static const struct scarlett2_config_set scarlett2_config_set_gen3a = {
 .notifications = scarlett3a_notifications,
 .items = {
  [SCARLETT2_CONFIG_MSD_SWITCH] = {
   .offset = 0x04, .size = 8, .activate = 6 },

  [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = {
   .offset = 0x05, .size = 8, .activate = 6 },

  [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
   .offset = 0x06, .size = 8, .activate = 3 },

  [SCARLETT2_CONFIG_DIRECT_MONITOR] = {
   .offset = 0x07, .size = 8, .activate = 4 },

  [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
   .offset = 0x08, .size = 1, .activate = 7 },

  [SCARLETT2_CONFIG_AIR_SWITCH] = {
   .offset = 0x09, .size = 1, .activate = 8 },
 }
};

/* Gen 3 devices without SW/HW volume switch: 4i4, 8i6 */
static const struct scarlett2_config_set scarlett2_config_set_gen3b = {
 .notifications = scarlett2_notifications,
 .items = {
  [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
   .offset = 0x34, .size = 16, .activate = 1 },

  [SCARLETT2_CONFIG_MUTE_SWITCH] = {
   .offset = 0x5c, .size = 8, .activate = 1 },

  [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
   .offset = 0x7c, .size = 8, .activate = 7 },

  [SCARLETT2_CONFIG_PAD_SWITCH] = {
   .offset = 0x84, .size = 8, .activate = 8 },

  [SCARLETT2_CONFIG_AIR_SWITCH] = {
   .offset = 0x8c, .size = 8, .activate = 8 },

  [SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
   .offset = 0x95, .size = 8, .activate = 6 },

  [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
   .offset = 0x9c, .size = 1, .activate = 8 },

  [SCARLETT2_CONFIG_MSD_SWITCH] = {
   .offset = 0x9d, .size = 8, .activate = 6 },

  [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = {
   .offset = 0x9e, .size = 8, .activate = 6 },
 }
};

/* Gen 3 devices with SW/HW volume switch: 18i8, 18i20 */
static const struct scarlett2_config_set scarlett2_config_set_gen3c = {
 .notifications = scarlett2_notifications,
 .items = {
  [SCARLETT2_CONFIG_DIM_MUTE] = {
   .offset = 0x31, .size = 8, .activate = 2 },

  [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
   .offset = 0x34, .size = 16, .activate = 1 },

  [SCARLETT2_CONFIG_MUTE_SWITCH] = {
   .offset = 0x5c, .size = 8, .activate = 1 },

  [SCARLETT2_CONFIG_SW_HW_SWITCH] = {
   .offset = 0x66, .size = 8, .activate = 3 },

  [SCARLETT2_CONFIG_MASTER_VOLUME] = {
   .offset = 0x76, .size = 16 },

  [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
   .offset = 0x7c, .size = 8, .activate = 7 },

  [SCARLETT2_CONFIG_PAD_SWITCH] = {
   .offset = 0x84, .size = 8, .activate = 8 },

  [SCARLETT2_CONFIG_AIR_SWITCH] = {
   .offset = 0x8c, .size = 8, .activate = 8 },

  [SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
   .offset = 0x95, .size = 8, .activate = 6 },

  [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
   .offset = 0x9c, .size = 1, .activate = 8 },

  [SCARLETT2_CONFIG_MSD_SWITCH] = {
   .offset = 0x9d, .size = 8, .activate = 6 },

  [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = {
   .offset = 0x9e, .size = 8, .activate = 6 },

  [SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH] = {
   .offset = 0x9f, .size = 1, .activate = 10 },

  [SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE] = {
   .offset = 0xa0, .size = 1, .activate = 10 },

  [SCARLETT2_CONFIG_TALKBACK_MAP] = {
   .offset = 0xb0, .size = 16, .activate = 10 },

  [SCARLETT2_CONFIG_SPDIF_MODE] = {
   .offset = 0x94, .size = 8, .activate = 6 },
 }
};

/* Vocaster */
static const struct scarlett2_config_set scarlett2_config_set_vocaster = {
 .notifications = vocaster_notifications,
 .param_buf_addr = 0x1bc,
 .input_gain_tlv = db_scale_vocaster_gain,
 .autogain_status_texts = scarlett2_autogain_status_vocaster,
 .items = {
  [SCARLETT2_CONFIG_MSD_SWITCH] = {
   .offset = 0x9d, .size = 8, .activate = 6 },

  [SCARLETT2_CONFIG_AUTOGAIN_SWITCH] = {
   .offset = 0x1c0, .size = 8, .activate = 19, .pbuf = 1 },

  [SCARLETT2_CONFIG_AUTOGAIN_STATUS] = {
   .offset = 0x1c2, .size = 8, },

  [SCARLETT2_CONFIG_AG_HOT_TARGET] = {
   .offset = 0xc1, .size = 8, .activate = 29, .pbuf = 1 },

  [SCARLETT2_CONFIG_INPUT_GAIN] = {
   .offset = 0x9f, .size = 8, .activate = 21, .pbuf = 1 },

  [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
   .offset = 0x9c, .size = 1, .activate = 20, .pbuf = 1 },

  [SCARLETT2_CONFIG_DSP_SWITCH] = {
   .offset = 0x1c4, .size = 8, .activate = 22, .pbuf = 1 },

  [SCARLETT2_CONFIG_COMPRESSOR_PARAMS] = {
   .offset = 0x1c8, .size = 32, .activate = 23 },

  [SCARLETT2_CONFIG_PRECOMP_FLT_SWITCH] = {
   .offset = 0x7c, .size = 32, .activate = 27 },

  [SCARLETT2_CONFIG_PRECOMP_FLT_PARAMS] = {
   .offset = 0x200, .size = 32, .activate = 27 },

  [SCARLETT2_CONFIG_PEQ_FLT_SWITCH] = {
   .offset = 0x84, .size = 32, .activate = 27 },

  [SCARLETT2_CONFIG_PEQ_FLT_PARAMS] = {
   .offset = 0x250, .size = 32, .activate = 27 },

  [SCARLETT2_CONFIG_INPUT_MUTE_SWITCH] = {
   .offset = 0x1be, .size = 8, .activate = 17, .pbuf = 1 },

  [SCARLETT2_CONFIG_BLUETOOTH_VOLUME] = {
   .offset = 0xbf, .size = 8, .activate = 28 },
 }
};

/* Solo Gen 4 */
static const struct scarlett2_config_set scarlett2_config_set_gen4_solo = {
 .notifications = scarlett4_solo_notifications,
 .param_buf_addr = 0xd8,
 .items = {
  [SCARLETT2_CONFIG_MSD_SWITCH] = {
   .offset = 0x47, .size = 8, .activate = 4 },

  [SCARLETT2_CONFIG_DIRECT_MONITOR] = {
   .offset = 0x108, .size = 8, .activate = 12, .pbuf = 1 },

  [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
   .offset = 0x46, .size = 8, .activate = 9, .pbuf = 1,
   .mute = 1 },

  [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
   .offset = 0x3d, .size = 8, .activate = 10, .pbuf = 1,
   .mute = 1 },

  [SCARLETT2_CONFIG_AIR_SWITCH] = {
   .offset = 0x3e, .size = 8, .activate = 11, .pbuf = 1 },

  [SCARLETT2_CONFIG_PCM_INPUT_SWITCH] = {
   .offset = 0x206, .size = 8, .activate = 25, .pbuf = 1 },

  [SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = {
   .offset = 0x232, .size = 16, .activate = 26 }
 }
};

/* 2i2 Gen 4 */
static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = {
 .notifications = scarlett4_2i2_notifications,
 .param_buf_addr = 0xfc,
 .input_gain_tlv = db_scale_gen4_gain,
 .autogain_status_texts = scarlett2_autogain_status_gen4,
 .items = {
  [SCARLETT2_CONFIG_MSD_SWITCH] = {
   .offset = 0x49, .size = 8, .activate = 4 },

  [SCARLETT2_CONFIG_DIRECT_MONITOR] = {
   .offset = 0x14a, .size = 8, .activate = 16, .pbuf = 1 },

  [SCARLETT2_CONFIG_AUTOGAIN_SWITCH] = {
   .offset = 0x135, .size = 8, .activate = 10, .pbuf = 1 },

  [SCARLETT2_CONFIG_AUTOGAIN_STATUS] = {
   .offset = 0x137, .size = 8 },

  [SCARLETT2_CONFIG_AG_MEAN_TARGET] = {
   .offset = 0x131, .size = 8, .activate = 29, .pbuf = 1 },

  [SCARLETT2_CONFIG_AG_PEAK_TARGET] = {
   .offset = 0x132, .size = 8, .activate = 30, .pbuf = 1 },

  [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
   .offset = 0x48, .size = 8, .activate = 11, .pbuf = 1,
   .mute = 1 },

  [SCARLETT2_CONFIG_INPUT_GAIN] = {
   .offset = 0x4b, .size = 8, .activate = 12, .pbuf = 1 },

  [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
   .offset = 0x3c, .size = 8, .activate = 13, .pbuf = 1,
   .mute = 1 },

  [SCARLETT2_CONFIG_SAFE_SWITCH] = {
   .offset = 0x147, .size = 8, .activate = 14, .pbuf = 1 },

  [SCARLETT2_CONFIG_AIR_SWITCH] = {
   .offset = 0x3e, .size = 8, .activate = 15, .pbuf = 1 },

  [SCARLETT2_CONFIG_INPUT_SELECT_SWITCH] = {
   .offset = 0x14b, .size = 8, .activate = 17, .pbuf = 1 },

  [SCARLETT2_CONFIG_INPUT_LINK_SWITCH] = {
   .offset = 0x14e, .size = 8, .activate = 18, .pbuf = 1 },

  [SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = {
   .offset = 0x2a0, .size = 16, .activate = 36 }
 }
};

/* 4i4 Gen 4 */
static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = {
 .notifications = scarlett4_4i4_notifications,
 .param_buf_addr = 0x130,
 .input_gain_tlv = db_scale_gen4_gain,
 .autogain_status_texts = scarlett2_autogain_status_gen4,
 .items = {
  [SCARLETT2_CONFIG_MSD_SWITCH] = {
   .offset = 0x5c, .size = 8, .activate = 4 },

  [SCARLETT2_CONFIG_AUTOGAIN_SWITCH] = {
   .offset = 0x13e, .size = 8, .activate = 10, .pbuf = 1 },

  [SCARLETT2_CONFIG_AUTOGAIN_STATUS] = {
   .offset = 0x140, .size = 8 },

  [SCARLETT2_CONFIG_AG_MEAN_TARGET] = {
   .offset = 0x13a, .size = 8, .activate = 23, .pbuf = 1 },

  [SCARLETT2_CONFIG_AG_PEAK_TARGET] = {
   .offset = 0x13b, .size = 8, .activate = 24, .pbuf = 1 },

  [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
   .offset = 0x5a, .size = 8, .activate = 11, .pbuf = 1,
   .mute = 1 },

  [SCARLETT2_CONFIG_INPUT_GAIN] = {
   .offset = 0x5e, .size = 8, .activate = 12, .pbuf = 1 },

  [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
   .offset = 0x4e, .size = 8, .activate = 13, .pbuf = 1,
   .mute = 1 },

  [SCARLETT2_CONFIG_SAFE_SWITCH] = {
   .offset = 0x150, .size = 8, .activate = 14, .pbuf = 1 },

  [SCARLETT2_CONFIG_AIR_SWITCH] = {
   .offset = 0x50, .size = 8, .activate = 15, .pbuf = 1 },

  [SCARLETT2_CONFIG_INPUT_SELECT_SWITCH] = {
   .offset = 0x153, .size = 8, .activate = 16, .pbuf = 1 },

  [SCARLETT2_CONFIG_INPUT_LINK_SWITCH] = {
   .offset = 0x156, .size = 8, .activate = 17, .pbuf = 1 },

  [SCARLETT2_CONFIG_MASTER_VOLUME] = {
   .offset = 0x32, .size = 16 },

  [SCARLETT2_CONFIG_HEADPHONE_VOLUME] = {
   .offset = 0x3a, .size = 16 },

  [SCARLETT2_CONFIG_POWER_EXT] = {
   .offset = 0x168, .size = 8 },

  [SCARLETT2_CONFIG_POWER_LOW] = {
   .offset = 0x16d, .size = 8 }
 }
};

/* Clarett USB and Clarett+ devices: 2Pre, 4Pre, 8Pre */
static const struct scarlett2_config_set scarlett2_config_set_clarett = {
 .notifications = scarlett2_notifications,
 .items = {
  [SCARLETT2_CONFIG_DIM_MUTE] = {
   .offset = 0x31, .size = 8, .activate = 2 },

  [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = {
   .offset = 0x34, .size = 16, .activate = 1 },

  [SCARLETT2_CONFIG_MUTE_SWITCH] = {
   .offset = 0x5c, .size = 8, .activate = 1 },

  [SCARLETT2_CONFIG_SW_HW_SWITCH] = {
   .offset = 0x66, .size = 8, .activate = 3 },

  [SCARLETT2_CONFIG_MASTER_VOLUME] = {
   .offset = 0x76, .size = 16 },

  [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
   .offset = 0x7c, .size = 8, .activate = 7 },

  [SCARLETT2_CONFIG_AIR_SWITCH] = {
   .offset = 0x95, .size = 8, .activate = 8 },

  [SCARLETT2_CONFIG_STANDALONE_SWITCH] = {
   .offset = 0x8d, .size = 8, .activate = 6 },

  [SCARLETT2_CONFIG_SPDIF_MODE] = {
   .offset = 0x9e, .size = 8, .activate = 4 },
 }
};

/* Description of each hardware port type:
 * - id: hardware ID of this port type
 * - src_descr: printf format string for mux input selections
 * - src_num_offset: added to channel number for the fprintf
 * - dst_descr: printf format string for mixer controls
 */

struct scarlett2_port {
 u16 id;
 const char * const src_descr;
 int src_num_offset;
 const char * const dst_descr;
 const char * const dsp_src_descr;
 const char * const dsp_dst_descr;
};

static const struct scarlett2_port scarlett2_ports[SCARLETT2_PORT_TYPE_COUNT] = {
 [SCARLETT2_PORT_TYPE_NONE] = {
  .id = 0x000,
  .src_descr = "Off"
 },
 [SCARLETT2_PORT_TYPE_ANALOGUE] = {
  .id = 0x080,
  .src_descr = "Analogue %d",
  .src_num_offset = 1,
  .dst_descr = "Analogue Output %02d Playback"
 },
 [SCARLETT2_PORT_TYPE_SPDIF] = {
  .id = 0x180,
  .src_descr = "S/PDIF %d",
  .src_num_offset = 1,
  .dst_descr = "S/PDIF Output %d Playback"
 },
 [SCARLETT2_PORT_TYPE_ADAT] = {
  .id = 0x200,
  .src_descr = "ADAT %d",
  .src_num_offset = 1,
  .dst_descr = "ADAT Output %d Playback"
 },
 [SCARLETT2_PORT_TYPE_MIX] = {
  .id = 0x300,
  .src_descr = "Mix %c",
  .src_num_offset = 'A',
  .dst_descr = "Mixer Input %02d Capture",
  .dsp_src_descr = "DSP %d",
  .dsp_dst_descr = "DSP Input %d Capture"
 },
 [SCARLETT2_PORT_TYPE_PCM] = {
  .id = 0x600,
  .src_descr = "PCM %d",
  .src_num_offset = 1,
  .dst_descr = "PCM %02d Capture"
 },
};

/* Number of mux tables: one for each band of sample rates
 * (44.1/48kHz, 88.2/96kHz, and 176.4/176kHz)
 */

#define SCARLETT2_MUX_TABLES 3

/* Maximum number of entries in a mux table */
#define SCARLETT2_MAX_MUX_ENTRIES 10

/* One entry within mux_assignment defines the port type and range of
 * ports to add to the set_mux message. The end of the list is marked
 * with count == 0.
 */

struct scarlett2_mux_entry {
 u8 port_type;
 u8 start;
 u8 count;
};

/* Maximum number of entries in a mux table */
#define SCARLETT2_MAX_METER_ENTRIES 9

/* One entry within meter_assignment defines the range of mux outputs
 * that consecutive meter entries are mapped to. The end of the list
 * is marked with count == 0.
 */

struct scarlett2_meter_entry {
 u8 start;
 u8 count;
};

struct scarlett2_device_info {
 /* which set of configuration parameters the device uses */
 const struct scarlett2_config_set *config_set;

 /* minimum firmware version required */
 u16 min_firmware_version;

 /* has a downloadable device map */
 u8 has_devmap;

 /* support for main/alt speaker switching */
 u8 has_speaker_switching;

 /* support for talkback microphone */
 u8 has_talkback;

 /* the number of analogue inputs with a software switchable
 * level control that can be set to line or instrument
 */

 u8 level_input_count;

 /* the first input with a level control (0-based) */
 u8 level_input_first;

 /* the number of analogue inputs with a software switchable
 * 10dB pad control
 */

 u8 pad_input_count;

 /* the number of analogue inputs with a software switchable
 * "air" control
 */

 u8 air_input_count;

 /* the first input with an air control (0-based) */
 u8 air_input_first;

 /* number of additional air options
 * 0 for air presence only (Gen 3)
 * 1 for air presence+drive (Gen 4)
 */

 u8 air_option;

 /* the number of analogue inputs with DSP control */
 u8 dsp_input_count;

 /* number of pre-compressor filters */
 u8 precomp_flt_count;

 /* number of parametric EQ filters */
 u8 peq_flt_count;

 /* number of PEQ filters plus unused slots */
 u8 peq_flt_total_count;

 /* the number of analogue inputs with a software switchable
 * mute control
 */

 u8 mute_input_count;

 /* the number of phantom (48V) software switchable controls */
 u8 phantom_count;

 /* the first input with phantom power control (0-based) */
 u8 phantom_first;

 /* the number of inputs each phantom switch controls */
 u8 inputs_per_phantom;

 /* the number of inputs with software-controllable gain */
 u8 gain_input_count;

 /* the number of inputs with safe mode */
 u8 safe_input_count;

 /* the number of direct monitor options
 * (0 = none, 1 = mono only, 2 = mono/stereo)
 */

 u8 direct_monitor;

 /* the number of DSP channels */
 u8 dsp_count;

 /* has a Bluetooth module with volume control */
 u8 has_bluetooth;

 /* S/PDIF Source/Digital I/O mode control */
 const char * const spdif_mode_control_name;
 const u8 *spdif_mode_values;
 const char * const *spdif_mode_texts;

 /* remap analogue outputs; 18i8 Gen 3 has "line 3/4" connected
 * internally to the analogue 7/8 outputs
 */

 u8 line_out_remap_enable;
 u8 line_out_remap[SCARLETT2_ANALOGUE_MAX];
 u8 line_out_unmap[SCARLETT2_ANALOGUE_MAX];

 /* additional description for the line out volume controls */
 const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX];

 /* number of sources/destinations of each port type */
 const int port_count[SCARLETT2_PORT_TYPE_COUNT][SCARLETT2_PORT_DIRNS];

 /* layout/order of the entries in the set_mux message */
 struct scarlett2_mux_entry mux_assignment[SCARLETT2_MUX_TABLES]
       [SCARLETT2_MAX_MUX_ENTRIES];

 /* map from meter level order returned by
 * SCARLETT2_USB_GET_METER to index into mux[] entries (same
 * as the order returned by scarlett2_meter_ctl_get())
 */

 struct scarlett2_meter_entry meter_map[SCARLETT2_MAX_METER_ENTRIES];
};

struct scarlett2_data {
 struct usb_mixer_interface *mixer;
 struct mutex usb_mutex; /* prevent sending concurrent USB requests */
 struct completion cmd_done;
 struct mutex data_mutex; /* lock access to this data */
 u8 running;
 u8 hwdep_in_use;
 u8 selected_flash_segment_id;
 u8 flash_write_state;
 struct delayed_work work;
 const struct scarlett2_device_info *info;
 const struct scarlett2_config_set *config_set;
 const char *series_name;
 __u8 bInterfaceNumber;
 __u8 bEndpointAddress;
 __u16 wMaxPacketSize;
 __u8 bInterval;
 u8 num_mux_srcs;
 u8 num_mux_dsts;
 u8 num_mix_in;
 u8 num_mix_out;
 u8 num_line_out;
 u8 num_monitor_mix_ctls;
 u8 num_autogain_status_texts;
 u32 firmware_version;
 u8 flash_segment_nums[SCARLETT2_SEGMENT_ID_COUNT];
 u8 flash_segment_blocks[SCARLETT2_SEGMENT_ID_COUNT];
 u16 scarlett2_seq;
 u8 sync_updated;
 u8 vol_updated;
 u8 dim_mute_updated;
 u8 input_level_updated;
 u8 input_pad_updated;
 u8 input_air_updated;
 u8 input_dsp_updated;
 u8 input_mute_updated;
 u8 input_phantom_updated;
 u8 input_select_updated;
 u8 input_gain_updated;
 u8 autogain_updated;
 u8 input_safe_updated;
 u8 pcm_input_switch_updated;
 u8 monitor_other_updated;
 u8 direct_monitor_updated;
 u8 mux_updated;
 u8 mix_updated;
 u8 speaker_switching_switched;
 u8 power_status_updated;
 u8 bluetooth_updated;
 u8 sync;
 u8 master_vol;
 u8 headphone_vol;
 u8 vol[SCARLETT2_ANALOGUE_MAX];
 u8 vol_sw_hw_switch[SCARLETT2_ANALOGUE_MAX];
 u8 mute_switch[SCARLETT2_ANALOGUE_MAX];
 u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX];
 u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX];
 u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT];
 u8 air_switch[SCARLETT2_AIR_SWITCH_MAX];
 u8 dsp_switch[SCARLETT2_DSP_SWITCH_MAX];
 s32 compressor_values[SCARLETT2_COMPRESSOR_CTLS_MAX];
 s32 precomp_flt_values[SCARLETT2_PRECOMP_FLT_VALUES_MAX];
 s32 peq_flt_values[SCARLETT2_PEQ_FLT_VALUES_MAX];
 u8 precomp_flt_switch[SCARLETT2_DSP_SWITCH_MAX];
 u8 peq_flt_switch[SCARLETT2_DSP_SWITCH_MAX];
 u8 input_mute_switch[SCARLETT2_INPUT_MUTE_SWITCH_MAX];
 u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX];
 u8 phantom_persistence;
 u8 input_select_switch;
 u8 input_link_switch[SCARLETT2_INPUT_GAIN_MAX];
 u8 gain[SCARLETT2_INPUT_GAIN_MAX];
 u8 autogain_switch[SCARLETT2_INPUT_GAIN_MAX];
 u8 autogain_status[SCARLETT2_INPUT_GAIN_MAX];
 s8 ag_targets[SCARLETT2_AG_TARGET_COUNT];
 u8 safe_switch[SCARLETT2_INPUT_GAIN_MAX];
 u8 pcm_input_switch;
 u8 direct_monitor_switch;
 u8 speaker_switching_switch;
 u8 talkback_switch;
 u8 talkback_map[SCARLETT2_OUTPUT_MIX_MAX];
 u8 msd_switch;
 u8 standalone_switch;
 u8 power_status;
 u8 bluetooth_volume;
 u8 spdif_mode;
 u8 meter_level_map[SCARLETT2_MAX_METERS];
 struct snd_kcontrol *sync_ctl;
 struct snd_kcontrol *master_vol_ctl;
 struct snd_kcontrol *headphone_vol_ctl;
 struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX];
 struct snd_kcontrol *sw_hw_ctls[SCARLETT2_ANALOGUE_MAX];
 struct snd_kcontrol *mute_ctls[SCARLETT2_ANALOGUE_MAX];
 struct snd_kcontrol *dim_mute_ctls[SCARLETT2_DIM_MUTE_COUNT];
 struct snd_kcontrol *level_ctls[SCARLETT2_LEVEL_SWITCH_MAX];
 struct snd_kcontrol *pad_ctls[SCARLETT2_PAD_SWITCH_MAX];
 struct snd_kcontrol *air_ctls[SCARLETT2_AIR_SWITCH_MAX];
 struct snd_kcontrol *dsp_ctls[SCARLETT2_DSP_SWITCH_MAX];
 struct snd_kcontrol *input_mute_ctls[SCARLETT2_INPUT_MUTE_SWITCH_MAX];
 struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX];
 struct snd_kcontrol *input_select_ctl;
 struct snd_kcontrol *input_link_ctls[SCARLETT2_INPUT_GAIN_MAX];
 struct snd_kcontrol *input_gain_ctls[SCARLETT2_INPUT_GAIN_MAX];
 struct snd_kcontrol *autogain_ctls[SCARLETT2_INPUT_GAIN_MAX];
 struct snd_kcontrol *autogain_status_ctls[SCARLETT2_INPUT_GAIN_MAX];
 struct snd_kcontrol *ag_target_ctls[SCARLETT2_AG_TARGET_COUNT];
 struct snd_kcontrol *safe_ctls[SCARLETT2_INPUT_GAIN_MAX];
 struct snd_kcontrol *pcm_input_switch_ctl;
 struct snd_kcontrol *mux_ctls[SCARLETT2_MUX_MAX];
 struct snd_kcontrol *mix_ctls[SCARLETT2_MIX_MAX];
 struct snd_kcontrol *compressor_ctls[SCARLETT2_COMPRESSOR_CTLS_MAX];
 struct snd_kcontrol *precomp_flt_ctls[SCARLETT2_PRECOMP_FLT_CTLS_MAX];
 struct snd_kcontrol *peq_flt_ctls[SCARLETT2_PEQ_FLT_CTLS_MAX];
 struct snd_kcontrol *precomp_flt_switch_ctls[SCARLETT2_DSP_SWITCH_MAX];
 struct snd_kcontrol *peq_flt_switch_ctls[SCARLETT2_DSP_SWITCH_MAX];
 struct snd_kcontrol *direct_monitor_ctl;
 struct snd_kcontrol *speaker_switching_ctl;
 struct snd_kcontrol *talkback_ctl;
 struct snd_kcontrol *power_status_ctl;
 struct snd_kcontrol *bluetooth_volume_ctl;
 u8 mux[SCARLETT2_MUX_MAX];
 u8 mix[SCARLETT2_MIX_MAX];
 u8 monitor_mix[SCARLETT2_MONITOR_MIX_MAX];
};

/*** Model-specific data ***/

static const struct scarlett2_device_info s6i6_gen2_info = {
 .config_set = &scarlett2_config_set_gen2a,
 .level_input_count = 2,
 .pad_input_count = 2,

 .line_out_descrs = {
  "Headphones 1 L",
  "Headphones 1 R",
  "Headphones 2 L",
  "Headphones 2 R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = {  4,  4 },
  [SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
  [SCARLETT2_PORT_TYPE_PCM]      = {  6,  6 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_PCM,      0,  6 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0,  6 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0,  6 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 } },

 .meter_map = {
  { 24,  6 },
  {  0, 24 },
  {  0,  0 },
 }
};

static const struct scarlett2_device_info s18i8_gen2_info = {
 .config_set = &scarlett2_config_set_gen2a,
 .level_input_count = 2,
 .pad_input_count = 4,

 .line_out_descrs = {
  "Monitor L",
  "Monitor R",
  "Headphones 1 L",
  "Headphones 1 R",
  "Headphones 2 L",
  "Headphones 2 R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = {  8,  6 },
  [SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
  [SCARLETT2_PORT_TYPE_ADAT]     = {  8,  0 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
  [SCARLETT2_PORT_TYPE_PCM]      = {  8, 18 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_PCM,      0, 18 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0, 14 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0, 10 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  4 },
  { 0,                            0,  0 },
 } },

 .meter_map = {
  { 26, 18 },
  {  0, 26 },
  {  0,  0 },
 }
};

static const struct scarlett2_device_info s18i20_gen2_info = {
 .config_set = &scarlett2_config_set_gen2b,

 .line_out_descrs = {
  "Monitor L",
  "Monitor R",
  NULL,
  NULL,
  NULL,
  NULL,
  "Headphones 1 L",
  "Headphones 1 R",
  "Headphones 2 L",
  "Headphones 2 R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = {  8, 10 },
  [SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
  [SCARLETT2_PORT_TYPE_ADAT]     = {  8,  8 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
  [SCARLETT2_PORT_TYPE_PCM]      = { 20, 18 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_PCM,      0, 18 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_ADAT,     0,  8 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0, 14 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_ADAT,     0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0, 10 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  6 },
  { 0,                            0,  0 },
 } },

 .meter_map = {
  { 38, 18 },
  {  0, 38 },
  {  0,  0 },
 }
};

static const struct scarlett2_device_info solo_gen3_info = {
 .config_set = &scarlett2_config_set_gen3a,
 .level_input_count = 1,
 .level_input_first = 1,
 .air_input_count = 1,
 .phantom_count = 1,
 .inputs_per_phantom = 1,
 .direct_monitor = 1,
};

static const struct scarlett2_device_info s2i2_gen3_info = {
 .config_set = &scarlett2_config_set_gen3a,
 .level_input_count = 2,
 .air_input_count = 2,
 .phantom_count = 1,
 .inputs_per_phantom = 2,
 .direct_monitor = 2,
};

static const struct scarlett2_device_info s4i4_gen3_info = {
 .config_set = &scarlett2_config_set_gen3b,
 .level_input_count = 2,
 .pad_input_count = 2,
 .air_input_count = 2,
 .phantom_count = 1,
 .inputs_per_phantom = 2,

 .line_out_descrs = {
  "Monitor L",
  "Monitor R",
  "Headphones L",
  "Headphones R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = { 1, 0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = { 4, 4 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 6, 8 },
  [SCARLETT2_PORT_TYPE_PCM]      = { 4, 6 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_PCM,      0,  6 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,      0,  8 },
  { SCARLETT2_PORT_TYPE_NONE,     0, 16 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0,  6 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,      0,  8 },
  { SCARLETT2_PORT_TYPE_NONE,     0, 16 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0,  6 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,      0,  8 },
  { SCARLETT2_PORT_TYPE_NONE,     0, 16 },
  { 0,                            0,  0 },
 } },

 .meter_map = {
  { 12,  6 },
  {  0, 12 },
  {  0,  0 },
 }
};

static const struct scarlett2_device_info s8i6_gen3_info = {
 .config_set = &scarlett2_config_set_gen3b,
 .level_input_count = 2,
 .pad_input_count = 2,
 .air_input_count = 2,
 .phantom_count = 1,
 .inputs_per_phantom = 2,

 .line_out_descrs = {
  "Headphones 1 L",
  "Headphones 1 R",
  "Headphones 2 L",
  "Headphones 2 R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = { 1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = { 6,  4 },
  [SCARLETT2_PORT_TYPE_SPDIF]    = { 2,  2 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 8,  8 },
  [SCARLETT2_PORT_TYPE_PCM]      = { 6, 10 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_PCM,      0,  8 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_PCM,      8,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0,  8 },
  { SCARLETT2_PORT_TYPE_NONE,     0, 18 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0,  8 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_PCM,      8,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0,  8 },
  { SCARLETT2_PORT_TYPE_NONE,     0, 18 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0,  8 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_PCM,      8,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0,  8 },
  { SCARLETT2_PORT_TYPE_NONE,     0, 18 },
  { 0,                            0,  0 },
 } },

 .meter_map = {
  { 14, 8 },
  {  0, 6 },
  { 22, 2 },
  {  6, 8 },
  {  0, 0 },
 }
};

static const u8 scarlett2_spdif_s18i8_gen3_values[] = { 0, 2, 0xff };

static const char * const scarlett2_spdif_s18i8_gen3_texts[] = {
 "RCA",
 "Optical",
 NULL
};

static const struct scarlett2_device_info s18i8_gen3_info = {
 .config_set = &scarlett2_config_set_gen3c,
 .has_speaker_switching = 1,
 .level_input_count = 2,
 .pad_input_count = 4,
 .air_input_count = 4,
 .phantom_count = 2,
 .inputs_per_phantom = 2,

 .spdif_mode_control_name = "S/PDIF Mode Capture Enum",
 .spdif_mode_values = scarlett2_spdif_s18i8_gen3_values,
 .spdif_mode_texts = scarlett2_spdif_s18i8_gen3_texts,

 .line_out_remap_enable = 1,
 .line_out_remap = { 0, 1, 6, 7, 2, 3, 4, 5 },
 .line_out_unmap = { 0, 1, 4, 5, 6, 7, 2, 3 },

 .line_out_descrs = {
  "Monitor L",
  "Monitor R",
  "Alt Monitor L",
  "Alt Monitor R",
  "Headphones 1 L",
  "Headphones 1 R",
  "Headphones 2 L",
  "Headphones 2 R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = {  8,  8 },
  [SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
  [SCARLETT2_PORT_TYPE_ADAT]     = {  8,  0 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 10, 20 },
  [SCARLETT2_PORT_TYPE_PCM]      = {  8, 20 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_PCM,       0, 10 },
  { SCARLETT2_PORT_TYPE_PCM,      12,  8 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  6,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  2,  4 },
  { SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
  { SCARLETT2_PORT_TYPE_PCM,      10,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       0, 20 },
  { SCARLETT2_PORT_TYPE_NONE,      0, 10 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,       0, 10 },
  { SCARLETT2_PORT_TYPE_PCM,      12,  4 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  6,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  2,  4 },
  { SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
  { SCARLETT2_PORT_TYPE_PCM,      10,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       0, 20 },
  { SCARLETT2_PORT_TYPE_NONE,      0, 10 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,       0, 10 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  6,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  2,  4 },
  { SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       0, 20 },
  { SCARLETT2_PORT_TYPE_NONE,      0, 10 },
  { 0,                             0,  0 },
 } },

 .meter_map = {
  { 30, 10 },
  { 42,  8 },
  {  0,  2 },
  {  6,  2 },
  {  2,  4 },
  {  8,  2 },
  { 40,  2 },
  { 10, 20 },
  {  0,  0 }
 }
};

static const u8 scarlett2_spdif_s18i20_gen3_values[] = { 0, 6, 1, 0xff };

static const char * const scarlett2_spdif_s18i20_gen3_texts[] = {
 "S/PDIF RCA",
 "S/PDIF Optical",
 "Dual ADAT",
 NULL
};

static const struct scarlett2_device_info s18i20_gen3_info = {
 .config_set = &scarlett2_config_set_gen3c,
 .has_speaker_switching = 1,
 .has_talkback = 1,
 .level_input_count = 2,
 .pad_input_count = 8,
 .air_input_count = 8,
 .phantom_count = 2,
 .inputs_per_phantom = 4,

 .spdif_mode_control_name = "Digital I/O Mode Capture Enum",
 .spdif_mode_values = scarlett2_spdif_s18i20_gen3_values,
 .spdif_mode_texts = scarlett2_spdif_s18i20_gen3_texts,

 .line_out_descrs = {
  "Monitor 1 L",
  "Monitor 1 R",
  "Monitor 2 L",
  "Monitor 2 R",
  NULL,
  NULL,
  "Headphones 1 L",
  "Headphones 1 R",
  "Headphones 2 L",
  "Headphones 2 R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = {  9, 10 },
  [SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
  [SCARLETT2_PORT_TYPE_ADAT]     = {  8,  8 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 12, 25 },
  [SCARLETT2_PORT_TYPE_PCM]      = { 20, 20 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_PCM,       0,  8 },
  { SCARLETT2_PORT_TYPE_PCM,      10, 10 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0, 10 },
  { SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
  { SCARLETT2_PORT_TYPE_ADAT,      0,  8 },
  { SCARLETT2_PORT_TYPE_PCM,       8,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       0, 25 },
  { SCARLETT2_PORT_TYPE_NONE,      0, 12 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,       0,  8 },
  { SCARLETT2_PORT_TYPE_PCM,      10,  8 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0, 10 },
  { SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
  { SCARLETT2_PORT_TYPE_ADAT,      0,  8 },
  { SCARLETT2_PORT_TYPE_PCM,       8,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       0, 25 },
  { SCARLETT2_PORT_TYPE_NONE,      0, 10 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,       0, 10 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0, 10 },
  { SCARLETT2_PORT_TYPE_SPDIF,     0,  2 },
  { SCARLETT2_PORT_TYPE_NONE,      0, 24 },
  { 0,                             0,  0 },
 } },

 .meter_map = {
  { 45,  8 },
  { 55, 10 },
  {  0, 20 },
  { 53,  2 },
  { 20, 25 },
  {  0,  0 },
 }
};

static const struct scarlett2_device_info vocaster_one_info = {
 .config_set = &scarlett2_config_set_vocaster,
 .min_firmware_version = 1769,
 .has_devmap = 1,

 .phantom_count = 1,
 .inputs_per_phantom = 1,
 .dsp_count = 1,
 .dsp_input_count = 1,
 .precomp_flt_count = 2,
 .peq_flt_count = 3,
 .peq_flt_total_count = 4,
 .mute_input_count = 1,
 .gain_input_count = 1,

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = { 1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = { 2,  4 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 9,  9 },
  [SCARLETT2_PORT_TYPE_PCM]      = { 4, 10 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_MIX,      8, 1 },
  { SCARLETT2_PORT_TYPE_PCM,      5, 5 },
  { SCARLETT2_PORT_TYPE_MIX,      6, 2 },
  { SCARLETT2_PORT_TYPE_PCM,      0, 5 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 6 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
  { 0, 0, 0 },
 } },

 .meter_map = {
  { 12, 1 },
  { 18, 5 },
  { 10, 2 },
  { 13, 5 },
  {  4, 6 },
  {  0, 4 },
  {  0, 0 }
 }
};

static const struct scarlett2_device_info vocaster_two_info = {
 .config_set = &scarlett2_config_set_vocaster,
 .min_firmware_version = 1769,
 .has_devmap = 1,

 .phantom_count = 2,
 .inputs_per_phantom = 1,
 .dsp_count = 2,
 .dsp_input_count = 2,
 .precomp_flt_count = 2,
 .peq_flt_count = 3,
 .peq_flt_total_count = 4,
 .mute_input_count = 2,
 .gain_input_count = 2,
 .has_bluetooth = 1,

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = {  6,  6 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 12, 14 },
  [SCARLETT2_PORT_TYPE_PCM]      = {  4, 14 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_MIX,      12,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       6,  8 },
  { SCARLETT2_PORT_TYPE_MIX,      10,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  6 },
  { SCARLETT2_PORT_TYPE_MIX,       0, 10 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  6 },
  { 0, 0, 0 },
 } },

 .meter_map = {
  { 18,  2 },
  { 26,  8 },
  { 16,  2 },
  { 20,  6 },
  {  6, 10 },
  {  0,  6 },
  {  0,  0 }
 }
};

static const struct scarlett2_device_info solo_gen4_info = {
 .config_set = &scarlett2_config_set_gen4_solo,
 .min_firmware_version = 2115,
 .has_devmap = 1,

 .level_input_count = 1,
 .air_input_count = 1,
 .air_input_first = 1,
 .air_option = 1,
 .phantom_count = 1,
 .phantom_first = 1,
 .inputs_per_phantom = 1,
 .direct_monitor = 1,
 .dsp_count = 2,

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = { 1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = { 2,  2 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 8,  6 },
  [SCARLETT2_PORT_TYPE_PCM]      = { 2,  4 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_MIX,       4,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       2,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,       0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_MIX,       4,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       2,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,       0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_MIX,       4,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       2,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,       0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
  { 0,                             0,  0 },
 } },

 .meter_map = {
  {  6,  2 },
  {  4,  2 },
  {  8,  4 },
  {  2,  2 },
  {  0,  2 },
  {  0,  0 }
 }
};

static const struct scarlett2_device_info s2i2_gen4_info = {
 .config_set = &scarlett2_config_set_gen4_2i2,
 .min_firmware_version = 2115,
 .has_devmap = 1,

 .level_input_count = 2,
 .air_input_count = 2,
 .air_option = 1,
 .phantom_count = 1,
 .inputs_per_phantom = 2,
 .gain_input_count = 2,
 .safe_input_count = 2,
 .direct_monitor = 2,
 .dsp_count = 2,

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = { 1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = { 2,  2 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 6,  6 },
  [SCARLETT2_PORT_TYPE_PCM]      = { 2,  4 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_MIX,       4,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       2,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,       0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_MIX,       4,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       2,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,       0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_MIX,       4,  2 },
  { SCARLETT2_PORT_TYPE_MIX,       2,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,       0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  2 },
  { 0,                             0,  0 },
 } },

 .meter_map = {
  {  6,  2 },
  {  4,  2 },
  {  8,  4 },
  {  2,  2 },
  {  0,  2 },
  {  0,  0 }
 }
};

static const struct scarlett2_device_info s4i4_gen4_info = {
 .config_set = &scarlett2_config_set_gen4_4i4,
 .min_firmware_version = 2089,
 .has_devmap = 1,

 .level_input_count = 2,
 .air_input_count = 2,
 .air_option = 1,
 .phantom_count = 2,
 .inputs_per_phantom = 1,
 .gain_input_count = 2,
 .safe_input_count = 2,
 .dsp_count = 2,

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = { 1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = { 4,  6 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 8, 12 },
  [SCARLETT2_PORT_TYPE_PCM]      = { 6,  6 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_MIX,      10,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  6 },
  { SCARLETT2_PORT_TYPE_MIX,       0, 10 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  6 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_MIX,      10,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  6 },
  { SCARLETT2_PORT_TYPE_MIX,       0, 10 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  6 },
  { 0,                             0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_MIX,      10,  2 },
  { SCARLETT2_PORT_TYPE_PCM,       0,  6 },
  { SCARLETT2_PORT_TYPE_MIX,       0, 10 },
  { SCARLETT2_PORT_TYPE_ANALOGUE,  0,  6 },
  { 0,                             0,  0 },
 } },

 .meter_map = {
  { 16,  8 },
  {  6, 10 },
  {  0,  6 },
  {  0,  0 }
 }
};

static const struct scarlett2_device_info clarett_2pre_info = {
 .config_set = &scarlett2_config_set_clarett,
 .level_input_count = 2,
 .air_input_count = 2,

 .line_out_descrs = {
  "Monitor L",
  "Monitor R",
  "Headphones L",
  "Headphones R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = {  2,  4 },
  [SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  0 },
  [SCARLETT2_PORT_TYPE_ADAT]     = {  8,  0 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
  [SCARLETT2_PORT_TYPE_PCM]      = {  4, 12 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_PCM,      0, 12 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0,  8 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0,  2 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  4 },
  { SCARLETT2_PORT_TYPE_NONE,     0, 26 },
  { 0,                            0,  0 },
 } },

 .meter_map = {
  { 22, 12 },
  {  0, 22 },
  {  0,  0 }
 }
};

static const u8 scarlett2_spdif_clarett_values[] = { 0, 1, 2, 0xff };

static const char * const scarlett2_spdif_clarett_texts[] = {
 "None",
 "Optical",
 "RCA",
 NULL
};

static const struct scarlett2_device_info clarett_4pre_info = {
 .config_set = &scarlett2_config_set_clarett,
 .level_input_count = 2,
 .air_input_count = 4,

 .spdif_mode_control_name = "S/PDIF Source Capture Enum",
 .spdif_mode_values = scarlett2_spdif_clarett_values,
 .spdif_mode_texts = scarlett2_spdif_clarett_texts,

 .line_out_descrs = {
  "Monitor L",
  "Monitor R",
  "Headphones 1 L",
  "Headphones 1 R",
  "Headphones 2 L",
  "Headphones 2 R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = {  8,  6 },
  [SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
  [SCARLETT2_PORT_TYPE_ADAT]     = {  8,  0 },
  [SCARLETT2_PORT_TYPE_MIX]      = { 10, 18 },
  [SCARLETT2_PORT_TYPE_PCM]      = {  8, 18 },
 },

 .mux_assignment = { {
  { SCARLETT2_PORT_TYPE_PCM,      0, 18 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0, 14 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_MIX,      0, 18 },
  { SCARLETT2_PORT_TYPE_NONE,     0,  8 },
  { 0,                            0,  0 },
 }, {
  { SCARLETT2_PORT_TYPE_PCM,      0, 12 },
  { SCARLETT2_PORT_TYPE_ANALOGUE, 0,  6 },
  { SCARLETT2_PORT_TYPE_SPDIF,    0,  2 },
  { SCARLETT2_PORT_TYPE_NONE,     0, 24 },
  { 0,                            0,  0 },
 } },

 .meter_map = {
  { 26, 18 },
  {  0, 26 },
  {  0,  0 }
 }
};

static const struct scarlett2_device_info clarett_8pre_info = {
 .config_set = &scarlett2_config_set_clarett,
 .level_input_count = 2,
 .air_input_count = 8,

 .spdif_mode_control_name = "S/PDIF Source Capture Enum",
 .spdif_mode_values = scarlett2_spdif_clarett_values,
 .spdif_mode_texts = scarlett2_spdif_clarett_texts,

 .line_out_descrs = {
  "Monitor L",
  "Monitor R",
  NULL,
  NULL,
  NULL,
  NULL,
  "Headphones 1 L",
  "Headphones 1 R",
  "Headphones 2 L",
  "Headphones 2 R",
 },

 .port_count = {
  [SCARLETT2_PORT_TYPE_NONE]     = {  1,  0 },
  [SCARLETT2_PORT_TYPE_ANALOGUE] = {  8, 10 },
  [SCARLETT2_PORT_TYPE_SPDIF]    = {  2,  2 },
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=97 G=96

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge