* [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on firmware 2417
@ 2026-04-25 21:07 Geoffrey D. Bennett
2026-04-25 21:16 ` [PATCH 1/3] ALSA: scarlett2: Allow selecting config_set by firmware version Geoffrey D. Bennett
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Geoffrey D. Bennett @ 2026-04-25 21:07 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound
Hi Takashi,
Firmware 2417 for the Scarlett 4th Gen 2i2 moved the direct monitor
gain parameters, breaking that control's functionality.
The driver already has per-device scarlett2_config_set tables
describing each parameter's offset, but only one table per device, so
there was no way to express "this offset changed at firmware version
N". This series adds that capability and uses it to fix the 2i2 Gen 4.
Patches
-------
1/3: Replace the device info's single config_set pointer with a
config_sets array of {from_firmware_version, config_set} entries, and
resolve the running config_set at probe time once the firmware version
has been read. Each device gets a single entry matching its previous
min_firmware_version (or 0), so this is a no-op preparation step.
2/3: Drop the now-redundant min_firmware_version field from
scarlett2_device_info; config_sets[0].from_firmware_version carries
the same meaning. No functional change.
3/3: Add a second 2i2 Gen 4 config_set with DIRECT_MONITOR_GAIN at the
new offset, gated on firmware >= 2417. All other offsets are
unchanged.
Patch 1 is a prerequisite for patch 3. Patch 2 isn't a strict
dependency, but it removes a now-redundant field, so patch 3's Cc:
stable trailer names both 1 and 2 as prereqs by subject (please
substitute SHAs at apply time). Patch 2 can be dropped from the stable
backport if you'd prefer.
Tested
------
Verified on a Scarlett 2i2 4th Gen by writing to Monitor 1 Mix A Input
01 and observing with usbmon:
- Firmware 2128, patched driver: write targets offset 0x2A0
- Firmware 2417, patched driver: write targets offset 0x2A4
- Firmware 2417, unpatched driver: write targets offset 0x2A0 (bug)
Regards,
Geoffrey
Geoffrey D. Bennett (3):
ALSA: scarlett2: Allow selecting config_set by firmware version
ALSA: scarlett2: Fold min_firmware_version into config_sets
ALSA: scarlett2: Update offsets for 2i2 Gen 4 firmware 2417
sound/usb/mixer_scarlett2.c | 222 ++++++++++++++++++++++++++++++------
1 file changed, 188 insertions(+), 34 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] ALSA: scarlett2: Allow selecting config_set by firmware version
2026-04-25 21:07 [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on firmware 2417 Geoffrey D. Bennett
@ 2026-04-25 21:16 ` Geoffrey D. Bennett
2026-04-25 21:16 ` [PATCH 2/3] ALSA: scarlett2: Fold min_firmware_version into config_sets Geoffrey D. Bennett
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Geoffrey D. Bennett @ 2026-04-25 21:16 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound
The Scarlett 2i2 Gen 4 firmware 2417 moved the direct monitor gain
parameters, so we now need to allow each device to list multiple
scarlett2_config_set entries, one per applicable firmware version
range, and pick the matching one at probe time.
No functional change yet: each device gets a single config_sets
entry whose from_firmware_version matches the existing
min_firmware_version (0 where none was set). This both prepares for
selection and lets a follow-up commit remove the now-redundant
min_firmware_version field.
scarlett2_count_io() depends on the resolved config_set so it moves
out of scarlett2_init_private() into snd_scarlett2_controls_create()
after the firmware version has been read.
Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
sound/usb/mixer_scarlett2.c | 143 ++++++++++++++++++++++++++++++------
1 file changed, 121 insertions(+), 22 deletions(-)
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 7b31504c5f24..15abca6d34ef 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -612,6 +612,20 @@ struct scarlett2_config_set {
const struct scarlett2_config items[SCARLETT2_CONFIG_COUNT];
};
+/* Map firmware versions to config sets per-device.
+ *
+ * Each device lists one or more entries, sorted in ascending order of
+ * from_firmware_version. At probe time the running firmware version
+ * is looked up against this list and the last entry whose
+ * from_firmware_version is <= the running version is selected.
+ *
+ * The list is terminated by a sentinel entry with config_set == NULL.
+ */
+struct scarlett2_config_set_entry {
+ u16 from_firmware_version;
+ const struct scarlett2_config_set *config_set;
+};
+
/* Input gain TLV dB ranges */
static const DECLARE_TLV_DB_MINMAX(
@@ -1100,8 +1114,8 @@ struct scarlett2_meter_entry {
};
struct scarlett2_device_info {
- /* which set of configuration parameters the device uses */
- const struct scarlett2_config_set *config_set;
+ /* which sets of configuration parameters the device uses */
+ const struct scarlett2_config_set_entry *config_sets;
/* minimum firmware version required */
u16 min_firmware_version;
@@ -1343,7 +1357,10 @@ struct scarlett2_data {
/*** Model-specific data ***/
static const struct scarlett2_device_info s6i6_gen2_info = {
- .config_set = &scarlett2_config_set_gen2a,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen2a },
+ { }
+ },
.level_input_count = 2,
.pad_input_count = 2,
@@ -1393,7 +1410,10 @@ static const struct scarlett2_device_info s6i6_gen2_info = {
};
static const struct scarlett2_device_info s18i8_gen2_info = {
- .config_set = &scarlett2_config_set_gen2a,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen2a },
+ { }
+ },
.level_input_count = 2,
.pad_input_count = 4,
@@ -1446,7 +1466,10 @@ static const struct scarlett2_device_info s18i8_gen2_info = {
};
static const struct scarlett2_device_info s18i20_gen2_info = {
- .config_set = &scarlett2_config_set_gen2b,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen2b },
+ { }
+ },
.line_out_descrs = {
"Monitor L",
@@ -1503,7 +1526,10 @@ static const struct scarlett2_device_info s18i20_gen2_info = {
};
static const struct scarlett2_device_info solo_gen3_info = {
- .config_set = &scarlett2_config_set_gen3a,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3a },
+ { }
+ },
.level_input_count = 1,
.level_input_first = 1,
.air_input_count = 1,
@@ -1513,7 +1539,10 @@ static const struct scarlett2_device_info solo_gen3_info = {
};
static const struct scarlett2_device_info s2i2_gen3_info = {
- .config_set = &scarlett2_config_set_gen3a,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3a },
+ { }
+ },
.level_input_count = 2,
.air_input_count = 2,
.phantom_count = 1,
@@ -1522,7 +1551,10 @@ static const struct scarlett2_device_info s2i2_gen3_info = {
};
static const struct scarlett2_device_info s4i4_gen3_info = {
- .config_set = &scarlett2_config_set_gen3b,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3b },
+ { }
+ },
.level_input_count = 2,
.pad_input_count = 2,
.air_input_count = 2,
@@ -1571,7 +1603,10 @@ static const struct scarlett2_device_info s4i4_gen3_info = {
};
static const struct scarlett2_device_info s8i6_gen3_info = {
- .config_set = &scarlett2_config_set_gen3b,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3b },
+ { }
+ },
.level_input_count = 2,
.pad_input_count = 2,
.air_input_count = 2,
@@ -1637,7 +1672,10 @@ static const char * const scarlett2_spdif_s18i8_gen3_texts[] = {
};
static const struct scarlett2_device_info s18i8_gen3_info = {
- .config_set = &scarlett2_config_set_gen3c,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3c },
+ { }
+ },
.has_speaker_switching = 1,
.level_input_count = 2,
.pad_input_count = 4,
@@ -1729,7 +1767,10 @@ static const char * const scarlett2_spdif_s18i20_gen3_texts[] = {
};
static const struct scarlett2_device_info s18i20_gen3_info = {
- .config_set = &scarlett2_config_set_gen3c,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3c },
+ { }
+ },
.has_speaker_switching = 1,
.has_talkback = 1,
.level_input_count = 2,
@@ -1803,7 +1844,10 @@ static const struct scarlett2_device_info s18i20_gen3_info = {
};
static const struct scarlett2_device_info vocaster_one_info = {
- .config_set = &scarlett2_config_set_vocaster,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 1769, &scarlett2_config_set_vocaster },
+ { }
+ },
.min_firmware_version = 1769,
.has_devmap = 1,
@@ -1847,7 +1891,10 @@ static const struct scarlett2_device_info vocaster_one_info = {
};
static const struct scarlett2_device_info vocaster_two_info = {
- .config_set = &scarlett2_config_set_vocaster,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 1769, &scarlett2_config_set_vocaster },
+ { }
+ },
.min_firmware_version = 1769,
.has_devmap = 1,
@@ -1892,7 +1939,10 @@ static const struct scarlett2_device_info vocaster_two_info = {
};
static const struct scarlett2_device_info solo_gen4_info = {
- .config_set = &scarlett2_config_set_gen4_solo,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 2115, &scarlett2_config_set_gen4_solo },
+ { }
+ },
.min_firmware_version = 2115,
.has_devmap = 1,
@@ -1947,7 +1997,10 @@ static const struct scarlett2_device_info solo_gen4_info = {
};
static const struct scarlett2_device_info s2i2_gen4_info = {
- .config_set = &scarlett2_config_set_gen4_2i2,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 2115, &scarlett2_config_set_gen4_2i2 },
+ { }
+ },
.min_firmware_version = 2115,
.has_devmap = 1,
@@ -2002,7 +2055,10 @@ static const struct scarlett2_device_info s2i2_gen4_info = {
};
static const struct scarlett2_device_info s4i4_gen4_info = {
- .config_set = &scarlett2_config_set_gen4_4i4,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 2089, &scarlett2_config_set_gen4_4i4 },
+ { }
+ },
.min_firmware_version = 2089,
.has_devmap = 1,
@@ -2051,7 +2107,10 @@ static const struct scarlett2_device_info s4i4_gen4_info = {
};
static const struct scarlett2_device_info clarett_2pre_info = {
- .config_set = &scarlett2_config_set_clarett,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_clarett },
+ { }
+ },
.level_input_count = 2,
.air_input_count = 2,
@@ -2107,7 +2166,10 @@ static const char * const scarlett2_spdif_clarett_texts[] = {
};
static const struct scarlett2_device_info clarett_4pre_info = {
- .config_set = &scarlett2_config_set_clarett,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_clarett },
+ { }
+ },
.level_input_count = 2,
.air_input_count = 4,
@@ -2163,7 +2225,10 @@ static const struct scarlett2_device_info clarett_4pre_info = {
};
static const struct scarlett2_device_info clarett_8pre_info = {
- .config_set = &scarlett2_config_set_clarett,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_clarett },
+ { }
+ },
.level_input_count = 2,
.air_input_count = 8,
@@ -8184,10 +8249,32 @@ static void scarlett2_private_suspend(struct usb_mixer_interface *mixer)
/*** Initialisation ***/
+/* Select the config_set matching the running firmware version.
+ *
+ * The device info's config_sets array is ordered by ascending
+ * from_firmware_version; pick the last entry whose version is <= the
+ * running firmware version. If the running firmware is older than the
+ * first entry's from_firmware_version (i.e. older than the driver's
+ * minimum supported version for this device), the first entry's
+ * config_set is selected anyway so firmware updates can still be done
+ * (requires only the ACK handler), but the usual mixer controls
+ * aren't created.
+ */
+static void scarlett2_resolve_config_set(struct scarlett2_data *private)
+{
+ const struct scarlett2_config_set_entry *entry =
+ private->info->config_sets;
+
+ private->config_set = entry->config_set;
+ for (entry++; entry->config_set; entry++)
+ if (entry->from_firmware_version <= private->firmware_version)
+ private->config_set = entry->config_set;
+}
+
static void scarlett2_count_io(struct scarlett2_data *private)
{
const struct scarlett2_device_info *info = private->info;
- const struct scarlett2_config_set *config_set = info->config_set;
+ const struct scarlett2_config_set *config_set = private->config_set;
const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
int port_type, srcs = 0, dsts = 0, i;
@@ -8282,9 +8369,14 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer,
mixer->private_suspend = scarlett2_private_suspend;
private->info = entry->info;
- private->config_set = entry->info->config_set;
+
+ /* Set config_set to the first entry's config_set so the
+ * notify handler has a valid pointer while USB init runs; it
+ * is re-resolved once the firmware version has been read.
+ */
+ private->config_set = entry->info->config_sets[0].config_set;
+
private->series_name = entry->series_name;
- scarlett2_count_io(private);
private->scarlett2_seq = 0;
private->mixer = mixer;
@@ -8688,6 +8780,13 @@ static int snd_scarlett2_controls_create(
if (err < 0)
return err;
+ /* Now that the firmware version is known, pick the matching
+ * config_set
+ */
+ scarlett2_resolve_config_set(private);
+
+ scarlett2_count_io(private);
+
/* Get the upgrade & settings flash segment numbers */
err = scarlett2_get_flash_segment_nums(mixer);
if (err < 0)
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] ALSA: scarlett2: Fold min_firmware_version into config_sets
2026-04-25 21:07 [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on firmware 2417 Geoffrey D. Bennett
2026-04-25 21:16 ` [PATCH 1/3] ALSA: scarlett2: Allow selecting config_set by firmware version Geoffrey D. Bennett
@ 2026-04-25 21:16 ` Geoffrey D. Bennett
2026-04-25 21:17 ` [PATCH 3/3] ALSA: scarlett2: Update offsets for 2i2 Gen 4 firmware 2417 Geoffrey D. Bennett
2026-04-27 12:20 ` [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on " Takashi Iwai
3 siblings, 0 replies; 5+ messages in thread
From: Geoffrey D. Bennett @ 2026-04-25 21:16 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound
The device info's min_firmware_version field encoded the oldest
firmware the driver supports on each device. With the config_sets
array in place, the first entry's from_firmware_version carries the
same meaning (it's the oldest firmware range any config_set applies
to). Merge the two by dropping min_firmware_version from
scarlett2_device_info and reading config_sets[0].from_firmware_version
at the three call sites that used it.
No functional change.
Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
sound/usb/mixer_scarlett2.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 15abca6d34ef..68adec4f21d9 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -1117,9 +1117,6 @@ struct scarlett2_device_info {
/* which sets of configuration parameters the device uses */
const struct scarlett2_config_set_entry *config_sets;
- /* minimum firmware version required */
- u16 min_firmware_version;
-
/* has a downloadable device map */
u8 has_devmap;
@@ -1848,7 +1845,6 @@ static const struct scarlett2_device_info vocaster_one_info = {
{ 1769, &scarlett2_config_set_vocaster },
{ }
},
- .min_firmware_version = 1769,
.has_devmap = 1,
.phantom_count = 1,
@@ -1895,7 +1891,6 @@ static const struct scarlett2_device_info vocaster_two_info = {
{ 1769, &scarlett2_config_set_vocaster },
{ }
},
- .min_firmware_version = 1769,
.has_devmap = 1,
.phantom_count = 2,
@@ -1943,7 +1938,6 @@ static const struct scarlett2_device_info solo_gen4_info = {
{ 2115, &scarlett2_config_set_gen4_solo },
{ }
},
- .min_firmware_version = 2115,
.has_devmap = 1,
.level_input_count = 1,
@@ -2001,7 +1995,6 @@ static const struct scarlett2_device_info s2i2_gen4_info = {
{ 2115, &scarlett2_config_set_gen4_2i2 },
{ }
},
- .min_firmware_version = 2115,
.has_devmap = 1,
.level_input_count = 2,
@@ -2059,7 +2052,6 @@ static const struct scarlett2_device_info s4i4_gen4_info = {
{ 2089, &scarlett2_config_set_gen4_4i4 },
{ }
},
- .min_firmware_version = 2089,
.has_devmap = 1,
.level_input_count = 2,
@@ -3341,7 +3333,8 @@ static int scarlett2_min_firmware_version_ctl_get(
struct usb_mixer_elem_info *elem = kctl->private_data;
struct scarlett2_data *private = elem->head.mixer->private_data;
- ucontrol->value.integer.value[0] = private->info->min_firmware_version;
+ ucontrol->value.integer.value[0] =
+ private->info->config_sets[0].from_firmware_version;
return 0;
}
@@ -8566,6 +8559,7 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
{
struct scarlett2_data *private = mixer->private_data;
const struct scarlett2_device_info *info = private->info;
+ u16 min_firmware_version = info->config_sets[0].from_firmware_version;
int err, i;
if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_MSD_SWITCH)) {
@@ -8576,13 +8570,13 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
return err;
}
- if (private->firmware_version < info->min_firmware_version) {
+ if (private->firmware_version < min_firmware_version) {
usb_audio_err(mixer->chip,
"Focusrite %s firmware version %d is too old; "
"need %d",
private->series_name,
private->firmware_version,
- info->min_firmware_version);
+ min_firmware_version);
return 0;
}
@@ -8766,6 +8760,7 @@ static int snd_scarlett2_controls_create(
const struct scarlett2_device_entry *entry)
{
struct scarlett2_data *private;
+ u16 min_firmware_version;
int err;
/* Initialise private data */
@@ -8774,6 +8769,8 @@ static int snd_scarlett2_controls_create(
return err;
private = mixer->private_data;
+ min_firmware_version =
+ private->info->config_sets[0].from_firmware_version;
/* Send proprietary USB initialisation sequence */
err = scarlett2_usb_init(mixer);
@@ -8816,7 +8813,7 @@ static int snd_scarlett2_controls_create(
* old, don't create any other controls
*/
if (private->msd_switch ||
- private->firmware_version < private->info->min_firmware_version)
+ private->firmware_version < min_firmware_version)
return 0;
/* Create the analogue output controls */
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] ALSA: scarlett2: Update offsets for 2i2 Gen 4 firmware 2417
2026-04-25 21:07 [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on firmware 2417 Geoffrey D. Bennett
2026-04-25 21:16 ` [PATCH 1/3] ALSA: scarlett2: Allow selecting config_set by firmware version Geoffrey D. Bennett
2026-04-25 21:16 ` [PATCH 2/3] ALSA: scarlett2: Fold min_firmware_version into config_sets Geoffrey D. Bennett
@ 2026-04-25 21:17 ` Geoffrey D. Bennett
2026-04-27 12:20 ` [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on " Takashi Iwai
3 siblings, 0 replies; 5+ messages in thread
From: Geoffrey D. Bennett @ 2026-04-25 21:17 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound
Firmware 2417 for the Scarlett 4th Gen 2i2 moved the direct monitor gain
parameters, so add a second config_set with the shifted offset and
select it for firmware versions >= 2417.
Fixes: 4e809a299677 ("ALSA: scarlett2: Add support for Solo, 2i2, and 4i4 Gen 4")
Cc: <stable@vger.kernel.org> # ALSA: scarlett2: Allow selecting config_set by firmware version
Cc: <stable@vger.kernel.org> # ALSA: scarlett2: Fold min_firmware_version into config_sets
Cc: <stable@vger.kernel.org>
Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
sound/usb/mixer_scarlett2.c | 58 +++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 68adec4f21d9..bb7373fac63a 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -937,6 +937,63 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = {
}
};
+/* 2i2 Gen 4, firmware version 2417 and above
+ *
+ * Firmware 2417 shifted DIRECT_MONITOR_GAIN by 4 bytes; all other
+ * offsets are unchanged from scarlett2_config_set_gen4_2i2.
+ */
+static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2_2417 = {
+ .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 = 0x2a4, .size = 16, .activate = 36 }
+ }
+};
+
/* 4i4 Gen 4 */
static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = {
.notifications = scarlett4_4i4_notifications,
@@ -1993,6 +2050,7 @@ static const struct scarlett2_device_info solo_gen4_info = {
static const struct scarlett2_device_info s2i2_gen4_info = {
.config_sets = (const struct scarlett2_config_set_entry[]) {
{ 2115, &scarlett2_config_set_gen4_2i2 },
+ { 2417, &scarlett2_config_set_gen4_2i2_2417 },
{ }
},
.has_devmap = 1,
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on firmware 2417
2026-04-25 21:07 [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on firmware 2417 Geoffrey D. Bennett
` (2 preceding siblings ...)
2026-04-25 21:17 ` [PATCH 3/3] ALSA: scarlett2: Update offsets for 2i2 Gen 4 firmware 2417 Geoffrey D. Bennett
@ 2026-04-27 12:20 ` Takashi Iwai
3 siblings, 0 replies; 5+ messages in thread
From: Takashi Iwai @ 2026-04-27 12:20 UTC (permalink / raw)
To: Geoffrey D. Bennett; +Cc: Takashi Iwai, Takashi Iwai, linux-sound
On Sat, 25 Apr 2026 23:07:30 +0200,
Geoffrey D. Bennett wrote:
>
> Hi Takashi,
>
> Firmware 2417 for the Scarlett 4th Gen 2i2 moved the direct monitor
> gain parameters, breaking that control's functionality.
>
> The driver already has per-device scarlett2_config_set tables
> describing each parameter's offset, but only one table per device, so
> there was no way to express "this offset changed at firmware version
> N". This series adds that capability and uses it to fix the 2i2 Gen 4.
>
> Patches
> -------
>
> 1/3: Replace the device info's single config_set pointer with a
> config_sets array of {from_firmware_version, config_set} entries, and
> resolve the running config_set at probe time once the firmware version
> has been read. Each device gets a single entry matching its previous
> min_firmware_version (or 0), so this is a no-op preparation step.
>
> 2/3: Drop the now-redundant min_firmware_version field from
> scarlett2_device_info; config_sets[0].from_firmware_version carries
> the same meaning. No functional change.
>
> 3/3: Add a second 2i2 Gen 4 config_set with DIRECT_MONITOR_GAIN at the
> new offset, gated on firmware >= 2417. All other offsets are
> unchanged.
>
> Patch 1 is a prerequisite for patch 3. Patch 2 isn't a strict
> dependency, but it removes a now-redundant field, so patch 3's Cc:
> stable trailer names both 1 and 2 as prereqs by subject (please
> substitute SHAs at apply time). Patch 2 can be dropped from the stable
> backport if you'd prefer.
>
> Tested
> ------
>
> Verified on a Scarlett 2i2 4th Gen by writing to Monitor 1 Mix A Input
> 01 and observing with usbmon:
>
> - Firmware 2128, patched driver: write targets offset 0x2A0
> - Firmware 2417, patched driver: write targets offset 0x2A4
> - Firmware 2417, unpatched driver: write targets offset 0x2A0 (bug)
>
> Regards,
> Geoffrey
>
> Geoffrey D. Bennett (3):
> ALSA: scarlett2: Allow selecting config_set by firmware version
> ALSA: scarlett2: Fold min_firmware_version into config_sets
> ALSA: scarlett2: Update offsets for 2i2 Gen 4 firmware 2417
Applied all to for-next branch now. Thanks.
Takashi
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-27 12:20 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-25 21:07 [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on firmware 2417 Geoffrey D. Bennett
2026-04-25 21:16 ` [PATCH 1/3] ALSA: scarlett2: Allow selecting config_set by firmware version Geoffrey D. Bennett
2026-04-25 21:16 ` [PATCH 2/3] ALSA: scarlett2: Fold min_firmware_version into config_sets Geoffrey D. Bennett
2026-04-25 21:17 ` [PATCH 3/3] ALSA: scarlett2: Update offsets for 2i2 Gen 4 firmware 2417 Geoffrey D. Bennett
2026-04-27 12:20 ` [PATCH 0/3] ALSA: scarlett2: Fix 2i2 Gen 4 direct monitor on " Takashi Iwai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox