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(
};
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;
/*** 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,
};
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,
};
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",
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
};
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,
/*** 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;
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;
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)