|
192 | 192 | /* maximum Bluetooth volume value */ |
193 | 193 | #define SCARLETT2_MAX_BLUETOOTH_VOLUME 30 |
194 | 194 |
|
| 195 | +/* maximum front-panel sleep time in seconds (24 hours) */ |
| 196 | +#define SCARLETT2_MAX_FP_SLEEP_TIME 86400 |
| 197 | + |
195 | 198 | /* mixer range from -80dB to +12dB in 0.5dB steps */ |
196 | 199 | #define SCARLETT2_MIXER_MIN_DB -80 |
197 | 200 | #define SCARLETT2_MIXER_BIAS (-SCARLETT2_MIXER_MIN_DB * 2) |
@@ -568,6 +571,8 @@ enum { |
568 | 571 | SCARLETT2_CONFIG_BLUETOOTH_VOLUME, |
569 | 572 | SCARLETT2_CONFIG_SPDIF_MODE, |
570 | 573 | SCARLETT2_CONFIG_SP_HP_MUTE, |
| 574 | + SCARLETT2_CONFIG_FP_BRIGHTNESS, |
| 575 | + SCARLETT2_CONFIG_FP_SLEEP_TIME, |
571 | 576 | SCARLETT2_CONFIG_COUNT |
572 | 577 | }; |
573 | 578 |
|
@@ -885,6 +890,42 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_solo = { |
885 | 890 | } |
886 | 891 | }; |
887 | 892 |
|
| 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 | + |
888 | 929 | /* 2i2 Gen 4 */ |
889 | 930 | static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = { |
890 | 931 | .notifications = scarlett4_2i2_notifications, |
@@ -940,8 +981,9 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = { |
940 | 981 |
|
941 | 982 | /* 2i2 Gen 4, firmware version 2417 and above |
942 | 983 | * |
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. |
945 | 987 | */ |
946 | 988 | static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2_2417 = { |
947 | 989 | .notifications = scarlett4_2i2_notifications, |
@@ -991,7 +1033,13 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2_2417 = { |
991 | 1033 | .offset = 0x14e, .size = 8, .activate = 18, .pbuf = 1 }, |
992 | 1034 |
|
993 | 1035 | [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 } |
995 | 1043 | } |
996 | 1044 | }; |
997 | 1045 |
|
@@ -1054,6 +1102,71 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = { |
1054 | 1102 | } |
1055 | 1103 | }; |
1056 | 1104 |
|
| 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 | + |
1057 | 1170 | /* Clarett USB and Clarett+ devices: 2Pre, 4Pre, 8Pre */ |
1058 | 1171 | static const struct scarlett2_config_set scarlett2_config_set_clarett = { |
1059 | 1172 | .notifications = scarlett2_notifications, |
@@ -1404,6 +1517,8 @@ struct scarlett2_data { |
1404 | 1517 | struct snd_kcontrol *talkback_ctl; |
1405 | 1518 | struct snd_kcontrol *power_status_ctl; |
1406 | 1519 | struct snd_kcontrol *bluetooth_volume_ctl; |
| 1520 | + u8 fp_brightness; |
| 1521 | + u32 fp_sleep_time; |
1407 | 1522 | u8 mux[SCARLETT2_MUX_MAX]; |
1408 | 1523 | u8 mix[SCARLETT2_MIX_MAX]; |
1409 | 1524 | u8 monitor_mix[SCARLETT2_MONITOR_MIX_MAX]; |
@@ -1994,6 +2109,7 @@ static const struct scarlett2_device_info vocaster_two_info = { |
1994 | 2109 | static const struct scarlett2_device_info solo_gen4_info = { |
1995 | 2110 | .config_sets = (const struct scarlett2_config_set_entry[]) { |
1996 | 2111 | { 2115, &scarlett2_config_set_gen4_solo }, |
| 2112 | + { 2417, &scarlett2_config_set_gen4_solo_2417 }, |
1997 | 2113 | { } |
1998 | 2114 | }, |
1999 | 2115 | .has_devmap = 1, |
@@ -2109,6 +2225,7 @@ static const struct scarlett2_device_info s2i2_gen4_info = { |
2109 | 2225 | static const struct scarlett2_device_info s4i4_gen4_info = { |
2110 | 2226 | .config_sets = (const struct scarlett2_config_set_entry[]) { |
2111 | 2227 | { 2089, &scarlett2_config_set_gen4_4i4 }, |
| 2228 | + { 2417, &scarlett2_config_set_gen4_4i4_2417 }, |
2112 | 2229 | { } |
2113 | 2230 | }, |
2114 | 2231 | .has_devmap = 1, |
@@ -7743,6 +7860,172 @@ static int scarlett2_add_bluetooth_volume_ctl( |
7743 | 7860 | &private->bluetooth_volume_ctl); |
7744 | 7861 | } |
7745 | 7862 |
|
| 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 | + |
7746 | 8029 | /*** S/PDIF Mode Controls ***/ |
7747 | 8030 |
|
7748 | 8031 | 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) |
8791 | 9074 | if (err < 0) |
8792 | 9075 | return err; |
8793 | 9076 |
|
| 9077 | + err = scarlett2_update_fp(mixer); |
| 9078 | + if (err < 0) |
| 9079 | + return err; |
| 9080 | + |
8794 | 9081 | err = scarlett2_update_spdif_mode(mixer); |
8795 | 9082 | if (err < 0) |
8796 | 9083 | return err; |
@@ -8937,6 +9224,11 @@ static int snd_scarlett2_controls_create( |
8937 | 9224 | if (err < 0) |
8938 | 9225 | return err; |
8939 | 9226 |
|
| 9227 | + /* Create the front-panel brightness/sleep controls */ |
| 9228 | + err = scarlett2_add_fp_ctls(mixer); |
| 9229 | + if (err < 0) |
| 9230 | + return err; |
| 9231 | + |
8940 | 9232 | /* Create the S/PDIF mode control */ |
8941 | 9233 | err = scarlett2_add_spdif_mode_ctl(mixer); |
8942 | 9234 | if (err < 0) |
|
0 commit comments