Skip to content

Commit a895279

Browse files
geoffreybennetttiwai
authored andcommitted
ALSA: scarlett2: Add Gen 4 firmware 2417 front-panel controls
Firmware 2417 for the Scarlett 4th Gen Solo, 2i2, and 4i4 added two new front-panel features: a LED brightness setting (High/Medium/Low) and an idle sleep timeout. Add ALSA controls to expose them: - "Front Panel Brightness": enum (High/Medium/Low) - "Front Panel Sleep Time": integer, seconds, capped at 86400 (24h) Signed-off-by: Geoffrey D. Bennett <g@b4.vu> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/1f9785ef76b9e97f785dfa4b91876a19f3c20c8e.1777153011.git.g@b4.vu
1 parent 4cb0317 commit a895279

1 file changed

Lines changed: 295 additions & 3 deletions

File tree

sound/usb/mixer_scarlett2.c

Lines changed: 295 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@
192192
/* maximum Bluetooth volume value */
193193
#define SCARLETT2_MAX_BLUETOOTH_VOLUME 30
194194

195+
/* maximum front-panel sleep time in seconds (24 hours) */
196+
#define SCARLETT2_MAX_FP_SLEEP_TIME 86400
197+
195198
/* mixer range from -80dB to +12dB in 0.5dB steps */
196199
#define SCARLETT2_MIXER_MIN_DB -80
197200
#define SCARLETT2_MIXER_BIAS (-SCARLETT2_MIXER_MIN_DB * 2)
@@ -568,6 +571,8 @@ enum {
568571
SCARLETT2_CONFIG_BLUETOOTH_VOLUME,
569572
SCARLETT2_CONFIG_SPDIF_MODE,
570573
SCARLETT2_CONFIG_SP_HP_MUTE,
574+
SCARLETT2_CONFIG_FP_BRIGHTNESS,
575+
SCARLETT2_CONFIG_FP_SLEEP_TIME,
571576
SCARLETT2_CONFIG_COUNT
572577
};
573578

@@ -885,6 +890,42 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_solo = {
885890
}
886891
};
887892

893+
/* Solo Gen 4, firmware version 2417 and above */
894+
static const struct scarlett2_config_set scarlett2_config_set_gen4_solo_2417 = {
895+
.notifications = scarlett4_solo_notifications,
896+
.param_buf_addr = 0xd8,
897+
.items = {
898+
[SCARLETT2_CONFIG_MSD_SWITCH] = {
899+
.offset = 0x47, .size = 8, .activate = 4 },
900+
901+
[SCARLETT2_CONFIG_DIRECT_MONITOR] = {
902+
.offset = 0x108, .size = 8, .activate = 12, .pbuf = 1 },
903+
904+
[SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
905+
.offset = 0x46, .size = 8, .activate = 9, .pbuf = 1,
906+
.mute = 1 },
907+
908+
[SCARLETT2_CONFIG_LEVEL_SWITCH] = {
909+
.offset = 0x3d, .size = 8, .activate = 10, .pbuf = 1,
910+
.mute = 1 },
911+
912+
[SCARLETT2_CONFIG_AIR_SWITCH] = {
913+
.offset = 0x3e, .size = 8, .activate = 11, .pbuf = 1 },
914+
915+
[SCARLETT2_CONFIG_PCM_INPUT_SWITCH] = {
916+
.offset = 0x206, .size = 8, .activate = 25, .pbuf = 1 },
917+
918+
[SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = {
919+
.offset = 0x232, .size = 16, .activate = 26 },
920+
921+
[SCARLETT2_CONFIG_FP_BRIGHTNESS] = {
922+
.offset = 0x243, .size = 8, .activate = 27, .pbuf = 1 },
923+
924+
[SCARLETT2_CONFIG_FP_SLEEP_TIME] = {
925+
.offset = 0x248, .size = 32, .activate = 29 }
926+
}
927+
};
928+
888929
/* 2i2 Gen 4 */
889930
static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = {
890931
.notifications = scarlett4_2i2_notifications,
@@ -940,8 +981,9 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = {
940981

941982
/* 2i2 Gen 4, firmware version 2417 and above
942983
*
943-
* Firmware 2417 shifted DIRECT_MONITOR_GAIN by 4 bytes; all other
944-
* offsets are unchanged from scarlett2_config_set_gen4_2i2.
984+
* Firmware 2417 shifted DIRECT_MONITOR_GAIN by 4 bytes and added
985+
* front-panel brightness and sleep controls; all other offsets are
986+
* unchanged from scarlett2_config_set_gen4_2i2.
945987
*/
946988
static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2_2417 = {
947989
.notifications = scarlett4_2i2_notifications,
@@ -991,7 +1033,13 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2_2417 = {
9911033
.offset = 0x14e, .size = 8, .activate = 18, .pbuf = 1 },
9921034

9931035
[SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = {
994-
.offset = 0x2a4, .size = 16, .activate = 36 }
1036+
.offset = 0x2a4, .size = 16, .activate = 36 },
1037+
1038+
[SCARLETT2_CONFIG_FP_BRIGHTNESS] = {
1039+
.offset = 0x2c7, .size = 8, .activate = 37, .pbuf = 1 },
1040+
1041+
[SCARLETT2_CONFIG_FP_SLEEP_TIME] = {
1042+
.offset = 0x2cc, .size = 32, .activate = 39 }
9951043
}
9961044
};
9971045

@@ -1054,6 +1102,71 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = {
10541102
}
10551103
};
10561104

1105+
/* 4i4 Gen 4, firmware version 2417 and above */
1106+
static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4_2417 = {
1107+
.notifications = scarlett4_4i4_notifications,
1108+
.param_buf_addr = 0x130,
1109+
.input_gain_tlv = db_scale_gen4_gain,
1110+
.autogain_status_texts = scarlett2_autogain_status_gen4,
1111+
.items = {
1112+
[SCARLETT2_CONFIG_MSD_SWITCH] = {
1113+
.offset = 0x5c, .size = 8, .activate = 4 },
1114+
1115+
[SCARLETT2_CONFIG_AUTOGAIN_SWITCH] = {
1116+
.offset = 0x13e, .size = 8, .activate = 10, .pbuf = 1 },
1117+
1118+
[SCARLETT2_CONFIG_AUTOGAIN_STATUS] = {
1119+
.offset = 0x140, .size = 8 },
1120+
1121+
[SCARLETT2_CONFIG_AG_MEAN_TARGET] = {
1122+
.offset = 0x13a, .size = 8, .activate = 23, .pbuf = 1 },
1123+
1124+
[SCARLETT2_CONFIG_AG_PEAK_TARGET] = {
1125+
.offset = 0x13b, .size = 8, .activate = 24, .pbuf = 1 },
1126+
1127+
[SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
1128+
.offset = 0x5a, .size = 8, .activate = 11, .pbuf = 1,
1129+
.mute = 1 },
1130+
1131+
[SCARLETT2_CONFIG_INPUT_GAIN] = {
1132+
.offset = 0x5e, .size = 8, .activate = 12, .pbuf = 1 },
1133+
1134+
[SCARLETT2_CONFIG_LEVEL_SWITCH] = {
1135+
.offset = 0x4e, .size = 8, .activate = 13, .pbuf = 1,
1136+
.mute = 1 },
1137+
1138+
[SCARLETT2_CONFIG_SAFE_SWITCH] = {
1139+
.offset = 0x150, .size = 8, .activate = 14, .pbuf = 1 },
1140+
1141+
[SCARLETT2_CONFIG_AIR_SWITCH] = {
1142+
.offset = 0x50, .size = 8, .activate = 15, .pbuf = 1 },
1143+
1144+
[SCARLETT2_CONFIG_INPUT_SELECT_SWITCH] = {
1145+
.offset = 0x153, .size = 8, .activate = 16, .pbuf = 1 },
1146+
1147+
[SCARLETT2_CONFIG_INPUT_LINK_SWITCH] = {
1148+
.offset = 0x156, .size = 8, .activate = 17, .pbuf = 1 },
1149+
1150+
[SCARLETT2_CONFIG_MASTER_VOLUME] = {
1151+
.offset = 0x32, .size = 16 },
1152+
1153+
[SCARLETT2_CONFIG_HEADPHONE_VOLUME] = {
1154+
.offset = 0x3a, .size = 16 },
1155+
1156+
[SCARLETT2_CONFIG_POWER_EXT] = {
1157+
.offset = 0x168, .size = 8 },
1158+
1159+
[SCARLETT2_CONFIG_POWER_LOW] = {
1160+
.offset = 0x16d, .size = 8 },
1161+
1162+
[SCARLETT2_CONFIG_FP_BRIGHTNESS] = {
1163+
.offset = 0x3a9, .size = 8, .activate = 36, .pbuf = 1 },
1164+
1165+
[SCARLETT2_CONFIG_FP_SLEEP_TIME] = {
1166+
.offset = 0x3ac, .size = 32, .activate = 38 }
1167+
}
1168+
};
1169+
10571170
/* Clarett USB and Clarett+ devices: 2Pre, 4Pre, 8Pre */
10581171
static const struct scarlett2_config_set scarlett2_config_set_clarett = {
10591172
.notifications = scarlett2_notifications,
@@ -1404,6 +1517,8 @@ struct scarlett2_data {
14041517
struct snd_kcontrol *talkback_ctl;
14051518
struct snd_kcontrol *power_status_ctl;
14061519
struct snd_kcontrol *bluetooth_volume_ctl;
1520+
u8 fp_brightness;
1521+
u32 fp_sleep_time;
14071522
u8 mux[SCARLETT2_MUX_MAX];
14081523
u8 mix[SCARLETT2_MIX_MAX];
14091524
u8 monitor_mix[SCARLETT2_MONITOR_MIX_MAX];
@@ -1994,6 +2109,7 @@ static const struct scarlett2_device_info vocaster_two_info = {
19942109
static const struct scarlett2_device_info solo_gen4_info = {
19952110
.config_sets = (const struct scarlett2_config_set_entry[]) {
19962111
{ 2115, &scarlett2_config_set_gen4_solo },
2112+
{ 2417, &scarlett2_config_set_gen4_solo_2417 },
19972113
{ }
19982114
},
19992115
.has_devmap = 1,
@@ -2109,6 +2225,7 @@ static const struct scarlett2_device_info s2i2_gen4_info = {
21092225
static const struct scarlett2_device_info s4i4_gen4_info = {
21102226
.config_sets = (const struct scarlett2_config_set_entry[]) {
21112227
{ 2089, &scarlett2_config_set_gen4_4i4 },
2228+
{ 2417, &scarlett2_config_set_gen4_4i4_2417 },
21122229
{ }
21132230
},
21142231
.has_devmap = 1,
@@ -7743,6 +7860,172 @@ static int scarlett2_add_bluetooth_volume_ctl(
77437860
&private->bluetooth_volume_ctl);
77447861
}
77457862

7863+
/*** Front Panel Brightness/Sleep Controls ***/
7864+
7865+
static int scarlett2_update_fp(struct usb_mixer_interface *mixer)
7866+
{
7867+
struct scarlett2_data *private = mixer->private_data;
7868+
int err;
7869+
7870+
if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_BRIGHTNESS)) {
7871+
err = scarlett2_usb_get_config(
7872+
mixer, SCARLETT2_CONFIG_FP_BRIGHTNESS,
7873+
1, &private->fp_brightness);
7874+
if (err < 0)
7875+
return err;
7876+
}
7877+
7878+
if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_SLEEP_TIME)) {
7879+
err = scarlett2_usb_get_config(
7880+
mixer, SCARLETT2_CONFIG_FP_SLEEP_TIME,
7881+
1, &private->fp_sleep_time);
7882+
if (err < 0)
7883+
return err;
7884+
}
7885+
7886+
return 0;
7887+
}
7888+
7889+
static const char * const scarlett2_fp_brightness_texts[] = {
7890+
"High", "Medium", "Low"
7891+
};
7892+
7893+
static int scarlett2_fp_brightness_ctl_info(
7894+
struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
7895+
{
7896+
return snd_ctl_enum_info(uinfo, 1,
7897+
ARRAY_SIZE(scarlett2_fp_brightness_texts),
7898+
scarlett2_fp_brightness_texts);
7899+
}
7900+
7901+
static int scarlett2_fp_brightness_ctl_get(
7902+
struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
7903+
{
7904+
struct usb_mixer_elem_info *elem = kctl->private_data;
7905+
struct scarlett2_data *private = elem->head.mixer->private_data;
7906+
7907+
ucontrol->value.enumerated.item[0] = private->fp_brightness;
7908+
return 0;
7909+
}
7910+
7911+
static int scarlett2_fp_brightness_ctl_put(
7912+
struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
7913+
{
7914+
struct usb_mixer_elem_info *elem = kctl->private_data;
7915+
struct usb_mixer_interface *mixer = elem->head.mixer;
7916+
struct scarlett2_data *private = mixer->private_data;
7917+
int oval, val, err;
7918+
7919+
guard(mutex)(&private->data_mutex);
7920+
7921+
if (private->hwdep_in_use)
7922+
return -EBUSY;
7923+
7924+
oval = private->fp_brightness;
7925+
val = min(ucontrol->value.enumerated.item[0],
7926+
ARRAY_SIZE(scarlett2_fp_brightness_texts) - 1);
7927+
7928+
if (oval == val)
7929+
return 0;
7930+
7931+
private->fp_brightness = val;
7932+
7933+
err = scarlett2_usb_set_config(
7934+
mixer, SCARLETT2_CONFIG_FP_BRIGHTNESS, 0, val);
7935+
7936+
return err < 0 ? err : 1;
7937+
}
7938+
7939+
static const struct snd_kcontrol_new scarlett2_fp_brightness_ctl = {
7940+
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
7941+
.name = "",
7942+
.info = scarlett2_fp_brightness_ctl_info,
7943+
.get = scarlett2_fp_brightness_ctl_get,
7944+
.put = scarlett2_fp_brightness_ctl_put,
7945+
};
7946+
7947+
static int scarlett2_fp_sleep_time_ctl_info(
7948+
struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
7949+
{
7950+
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
7951+
uinfo->count = 1;
7952+
uinfo->value.integer.min = 0;
7953+
uinfo->value.integer.max = SCARLETT2_MAX_FP_SLEEP_TIME;
7954+
uinfo->value.integer.step = 1;
7955+
return 0;
7956+
}
7957+
7958+
static int scarlett2_fp_sleep_time_ctl_get(
7959+
struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
7960+
{
7961+
struct usb_mixer_elem_info *elem = kctl->private_data;
7962+
struct scarlett2_data *private = elem->head.mixer->private_data;
7963+
7964+
ucontrol->value.integer.value[0] = private->fp_sleep_time;
7965+
return 0;
7966+
}
7967+
7968+
static int scarlett2_fp_sleep_time_ctl_put(
7969+
struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
7970+
{
7971+
struct usb_mixer_elem_info *elem = kctl->private_data;
7972+
struct usb_mixer_interface *mixer = elem->head.mixer;
7973+
struct scarlett2_data *private = mixer->private_data;
7974+
u32 oval, val;
7975+
int err;
7976+
7977+
guard(mutex)(&private->data_mutex);
7978+
7979+
if (private->hwdep_in_use)
7980+
return -EBUSY;
7981+
7982+
oval = private->fp_sleep_time;
7983+
val = clamp(ucontrol->value.integer.value[0],
7984+
0L, (long)SCARLETT2_MAX_FP_SLEEP_TIME);
7985+
7986+
if (oval == val)
7987+
return 0;
7988+
7989+
private->fp_sleep_time = val;
7990+
7991+
err = scarlett2_usb_set_config(
7992+
mixer, SCARLETT2_CONFIG_FP_SLEEP_TIME, 0, val);
7993+
7994+
return err < 0 ? err : 1;
7995+
}
7996+
7997+
static const struct snd_kcontrol_new scarlett2_fp_sleep_time_ctl = {
7998+
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
7999+
.name = "",
8000+
.info = scarlett2_fp_sleep_time_ctl_info,
8001+
.get = scarlett2_fp_sleep_time_ctl_get,
8002+
.put = scarlett2_fp_sleep_time_ctl_put,
8003+
};
8004+
8005+
static int scarlett2_add_fp_ctls(struct usb_mixer_interface *mixer)
8006+
{
8007+
struct scarlett2_data *private = mixer->private_data;
8008+
int err;
8009+
8010+
if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_BRIGHTNESS)) {
8011+
err = scarlett2_add_new_ctl(
8012+
mixer, &scarlett2_fp_brightness_ctl, 0, 1,
8013+
"Front Panel Brightness", NULL);
8014+
if (err < 0)
8015+
return err;
8016+
}
8017+
8018+
if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_SLEEP_TIME)) {
8019+
err = scarlett2_add_new_ctl(
8020+
mixer, &scarlett2_fp_sleep_time_ctl, 0, 1,
8021+
"Front Panel Sleep Time", NULL);
8022+
if (err < 0)
8023+
return err;
8024+
}
8025+
8026+
return 0;
8027+
}
8028+
77468029
/*** S/PDIF Mode Controls ***/
77478030

77488031
static int scarlett2_update_spdif_mode(struct usb_mixer_interface *mixer)
@@ -8791,6 +9074,10 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
87919074
if (err < 0)
87929075
return err;
87939076

9077+
err = scarlett2_update_fp(mixer);
9078+
if (err < 0)
9079+
return err;
9080+
87949081
err = scarlett2_update_spdif_mode(mixer);
87959082
if (err < 0)
87969083
return err;
@@ -8937,6 +9224,11 @@ static int snd_scarlett2_controls_create(
89379224
if (err < 0)
89389225
return err;
89399226

9227+
/* Create the front-panel brightness/sleep controls */
9228+
err = scarlett2_add_fp_ctls(mixer);
9229+
if (err < 0)
9230+
return err;
9231+
89409232
/* Create the S/PDIF mode control */
89419233
err = scarlett2_add_spdif_mode_ctl(mixer);
89429234
if (err < 0)

0 commit comments

Comments
 (0)