ALSA: scarlett2: Gen 4 firmware 2417 follow-up
Subsystems (2)
Geoffrey D. Bennett
maintainercover ALSA: scarlett2: Gen 4 firmware 2417 follow-up
Hi Takashi,
This is a small follow-up to the "Fix 2i2 Gen 4 direct monitor on firmware 2417" series, exposing two features added by that firmware:
a new autogain exit code, and the front-panel brightness/sleep controls.
Depends on the prior series for the config_sets[] machinery.
Tested on Scarlett 4th Gen Solo, 2i2, and 4i4 with firmware 2417.
Regards,
Geoffrey
Geoffrey D. Bennett (2):
ALSA: scarlett2: Add Gen 4 firmware 2417 autogain status text
ALSA: scarlett2: Add Gen 4 firmware 2417 front-panel controls
sound/usb/mixer_scarlett2.c | 299 +++++++++++++++++++++++++++++++++++- 1 file changed, 296 insertions(+), 3 deletions(-)
Signature · 1 line
2.53.0
Geoffrey D. Bennett
maintainerPATCH 1/2 ALSA: scarlett2: Add Gen 4 firmware 2417 autogain status text
Firmware 2417 for the Scarlett 4th Gen 2i2 and 4i4 added a new autogain exit code ("Root"). Without this entry the new status is reported as "Invalid".
--- sound/usb/mixer_scarlett2.c | 1 + 1 file changed, 1 insertion(+)
sound/usb/mixer_scarlett2.c +1 -0
@@ -398,6 +398,7 @@ static const char *const scarlett2_autogain_status_gen4[] = {"FailMaxGainLimit" ,"FailClipped" ,"Cancelled" , +"Root" ,"Invalid" , NULL };
Signature · 1 line
2.53.0
Geoffrey D. Bennett
maintainerPATCH 2/2 ALSA: scarlett2: Add Gen 4 firmware 2417 front-panel controls
In reply to Geoffrey D. BennettFirmware 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)
--- sound/usb/mixer_scarlett2.c | 298 +++++++++++++++++++++++++++++++++++- 1 file changed, 295 insertions(+), 3 deletions(-)
sound/usb/mixer_scarlett2.c +295 -3
@@ -192,6 +192,9 @@/* maximum Bluetooth volume value */ #define SCARLETT2_MAX_BLUETOOTH_VOLUME 30 +/* maximum front-panel sleep time in seconds (24 hours) */ +#define SCARLETT2_MAX_FP_SLEEP_TIME 86400 +/* 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)
@@ -568,6 +571,8 @@ enum {SCARLETT2_CONFIG_BLUETOOTH_VOLUME ,SCARLETT2_CONFIG_SPDIF_MODE ,SCARLETT2_CONFIG_SP_HP_MUTE , +SCARLETT2_CONFIG_FP_BRIGHTNESS , +SCARLETT2_CONFIG_FP_SLEEP_TIME , SCARLETT2_CONFIG_COUNT };
@@ -885,6 +890,42 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_solo = { } }; +/* Solo Gen 4, firmware version 2417 and above */ +static const struct scarlett2_config_set scarlett2_config_set_gen4_solo_2417 = { + .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 }, + + [SCARLETT2_CONFIG_FP_BRIGHTNESS ] = { + .offset =0x243 , .size =8 , .activate =27 , .pbuf =1 }, + + [SCARLETT2_CONFIG_FP_SLEEP_TIME ] = { + .offset =0x248 , .size =32 , .activate =29 } + } +}; +/* 2i2 Gen 4 */ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = { .notifications = scarlett4_2i2_notifications,
@@ -940,8 +981,9 @@ 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. +* Firmware 2417 shifted DIRECT_MONITOR_GAIN by 4 bytes and added +* front-panel brightness and sleep controls; 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,
@@ -991,7 +1033,13 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2_2417 = { .offset = 0x14e, .size = 8, .activate = 18, .pbuf = 1 }, [SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = { - .offset = 0x2a4, .size = 16, .activate = 36 } + .offset = 0x2a4, .size = 16, .activate = 36 }, + + [SCARLETT2_CONFIG_FP_BRIGHTNESS] = { + .offset = 0x2c7, .size = 8, .activate = 37, .pbuf = 1 }, + + [SCARLETT2_CONFIG_FP_SLEEP_TIME] = { + .offset = 0x2cc, .size = 32, .activate = 39 } } };
@@ -1054,6 +1102,71 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = { } }; +/* 4i4 Gen 4, firmware version 2417 and above */ +static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4_2417 = { + .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 }, + + [SCARLETT2_CONFIG_FP_BRIGHTNESS ] = { + .offset =0x3a9 , .size =8 , .activate =36 , .pbuf =1 }, + + [SCARLETT2_CONFIG_FP_SLEEP_TIME ] = { + .offset =0x3ac , .size =32 , .activate =38 } + } +}; +/* Clarett USB and Clarett+ devices: 2Pre, 4Pre, 8Pre */ static const struct scarlett2_config_set scarlett2_config_set_clarett = { .notifications = scarlett2_notifications,
@@ -1404,6 +1517,8 @@ struct scarlett2_data {struct snd_kcontrol *talkback_ctl;struct snd_kcontrol *power_status_ctl;struct snd_kcontrol *bluetooth_volume_ctl; +u8 fp_brightness; +u32 fp_sleep_time;u8 mux[SCARLETT2_MUX_MAX ];u8 mix[SCARLETT2_MIX_MAX ];u8 monitor_mix[SCARLETT2_MONITOR_MIX_MAX ];
@@ -1994,6 +2109,7 @@ static const struct scarlett2_device_info vocaster_two_info = {static const struct scarlett2_device_info solo_gen4_info = { .config_sets = (const struct scarlett2_config_set_entry []) { {2115 , &scarlett2_config_set_gen4_solo }, + {2417 , &scarlett2_config_set_gen4_solo_2417 }, { } }, .has_devmap =1 ,
@@ -2109,6 +2225,7 @@ static const struct scarlett2_device_info s2i2_gen4_info = {static const struct scarlett2_device_info s4i4_gen4_info = { .config_sets = (const struct scarlett2_config_set_entry []) { {2089 , &scarlett2_config_set_gen4_4i4 }, + {2417 , &scarlett2_config_set_gen4_4i4_2417 }, { } }, .has_devmap =1 ,
@@ -7743,6 +7860,172 @@ static int scarlett2_add_bluetooth_volume_ctl( &private->bluetooth_volume_ctl); } +/*** Front Panel Brightness/Sleep Controls ***/ + +static int scarlett2_update_fp (struct usb_mixer_interface *mixer) +{ +struct scarlett2_data *private = mixer->private_data; +int err; + +if (scarlett2_has_config_item (private,SCARLETT2_CONFIG_FP_BRIGHTNESS )) { + err =scarlett2_usb_get_config ( + mixer,SCARLETT2_CONFIG_FP_BRIGHTNESS , +1 , &private->fp_brightness); +if (err <0 ) +return err; + } + +if (scarlett2_has_config_item (private,SCARLETT2_CONFIG_FP_SLEEP_TIME )) { + err =scarlett2_usb_get_config ( + mixer,SCARLETT2_CONFIG_FP_SLEEP_TIME , +1 , &private->fp_sleep_time); +if (err <0 ) +return err; + } + +return 0 ; +} + +static const char *const scarlett2_fp_brightness_texts[] = { +"High" ,"Medium" ,"Low" +}; + +static int scarlett2_fp_brightness_ctl_info ( +struct snd_kcontrol *kctl,struct snd_ctl_elem_info *uinfo) +{ +return snd_ctl_enum_info (uinfo,1 , +ARRAY_SIZE (scarlett2_fp_brightness_texts), + scarlett2_fp_brightness_texts); +} + +static int scarlett2_fp_brightness_ctl_get ( +struct snd_kcontrol *kctl,struct snd_ctl_elem_value *ucontrol) +{ +struct usb_mixer_elem_info *elem = kctl->private_data; +struct scarlett2_data *private = elem->head.mixer->private_data; + + ucontrol->value.enumerated.item[0 ] = private->fp_brightness; +return 0 ; +} + +static int scarlett2_fp_brightness_ctl_put ( +struct snd_kcontrol *kctl,struct snd_ctl_elem_value *ucontrol) +{ +struct usb_mixer_elem_info *elem = kctl->private_data; +struct usb_mixer_interface *mixer = elem->head.mixer; +struct scarlett2_data *private = mixer->private_data; +int oval, val, err; + +guard (mutex)(&private->data_mutex); + +if (private->hwdep_in_use) +return -EBUSY ; + + oval = private->fp_brightness; + val =min (ucontrol->value.enumerated.item[0 ], +ARRAY_SIZE (scarlett2_fp_brightness_texts) -1 ); + +if (oval == val) +return 0 ; + + private->fp_brightness = val; + + err =scarlett2_usb_set_config ( + mixer,SCARLETT2_CONFIG_FP_BRIGHTNESS ,0 , val); + +return err <0 ? err :1 ; +} + +static const struct snd_kcontrol_new scarlett2_fp_brightness_ctl = { + .iface =SNDRV_CTL_ELEM_IFACE_CARD , + .name ="" , + .info = scarlett2_fp_brightness_ctl_info, + .get = scarlett2_fp_brightness_ctl_get, + .put = scarlett2_fp_brightness_ctl_put, +}; + +static int scarlett2_fp_sleep_time_ctl_info ( +struct snd_kcontrol *kctl,struct snd_ctl_elem_info *uinfo) +{ + uinfo->type =SNDRV_CTL_ELEM_TYPE_INTEGER ; + uinfo->count =1 ; + uinfo->value.integer.min =0 ; + uinfo->value.integer.max =SCARLETT2_MAX_FP_SLEEP_TIME ; + uinfo->value.integer.step =1 ; +return 0 ; +} + +static int scarlett2_fp_sleep_time_ctl_get ( +struct snd_kcontrol *kctl,struct snd_ctl_elem_value *ucontrol) +{ +struct usb_mixer_elem_info *elem = kctl->private_data; +struct scarlett2_data *private = elem->head.mixer->private_data; + + ucontrol->value.integer.value[0 ] = private->fp_sleep_time; +return 0 ; +} + +static int scarlett2_fp_sleep_time_ctl_put ( +struct snd_kcontrol *kctl,struct snd_ctl_elem_value *ucontrol) +{ +struct usb_mixer_elem_info *elem = kctl->private_data; +struct usb_mixer_interface *mixer = elem->head.mixer; +struct scarlett2_data *private = mixer->private_data; +u32 oval, val; +int err; + +guard (mutex)(&private->data_mutex); + +if (private->hwdep_in_use) +return -EBUSY ; + + oval = private->fp_sleep_time; + val =clamp (ucontrol->value.integer.value[0 ], +0L , (long )SCARLETT2_MAX_FP_SLEEP_TIME ); + +if (oval == val) +return 0 ; + + private->fp_sleep_time = val; + + err =scarlett2_usb_set_config ( + mixer,SCARLETT2_CONFIG_FP_SLEEP_TIME ,0 , val); + +return err <0 ? err :1 ; +} + +static const struct snd_kcontrol_new scarlett2_fp_sleep_time_ctl = { + .iface =SNDRV_CTL_ELEM_IFACE_CARD , + .name ="" , + .info = scarlett2_fp_sleep_time_ctl_info, + .get = scarlett2_fp_sleep_time_ctl_get, + .put = scarlett2_fp_sleep_time_ctl_put, +}; + +static int scarlett2_add_fp_ctls (struct usb_mixer_interface *mixer) +{ +struct scarlett2_data *private = mixer->private_data; +int err; + +if (scarlett2_has_config_item (private,SCARLETT2_CONFIG_FP_BRIGHTNESS )) { + err =scarlett2_add_new_ctl ( + mixer, &scarlett2_fp_brightness_ctl,0 ,1 , +"Front Panel Brightness" ,NULL ); +if (err <0 ) +return err; + } + +if (scarlett2_has_config_item (private,SCARLETT2_CONFIG_FP_SLEEP_TIME )) { + err =scarlett2_add_new_ctl ( + mixer, &scarlett2_fp_sleep_time_ctl,0 ,1 , +"Front Panel Sleep Time" ,NULL ); +if (err <0 ) +return err; + } + +return 0 ; +} +/*** S/PDIF Mode Controls ***/ static int scarlett2_update_spdif_mode (struct usb_mixer_interface *mixer)
@@ -8789,6 +9072,10 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)if (err <0 )return err; + err =scarlett2_update_fp (mixer); +if (err <0 ) +return err; + err =scarlett2_update_spdif_mode (mixer);if (err <0 )return err;
@@ -8935,6 +9222,11 @@ static int snd_scarlett2_controls_create(if (err <0 )return err; +/* Create the front-panel brightness/sleep controls */ + err =scarlett2_add_fp_ctls (mixer); +if (err <0 ) +return err; +/* Create the S/PDIF mode control */ err =scarlett2_add_spdif_mode_ctl (mixer);if (err <0 )
Signature · 1 line
2.53.0
Takashi Iwai
AppliedQuoted 10 lines · Geoffrey D. Bennett
Hi Takashi,
This is a small follow-up to the "Fix 2i2 Gen 4 direct monitor on firmware 2417" series, exposing two features added by that firmware:
a new autogain exit code, and the front-panel brightness/sleep controls.Depends on the prior series for the config_sets[] machinery.
Quoted 8 lines
Tested on Scarlett 4th Gen Solo, 2i2, and 4i4 with firmware 2417.
Regards,
GeoffreyGeoffrey D. Bennett (2):
ALSA: scarlett2: Add Gen 4 firmware 2417 autogain status text
ALSA: scarlett2: Add Gen 4 firmware 2417 front-panel controls
Applied to for-next branch. Thanks.
Takashi