ALSA: scarlett2: Add additional input configuration parameters

The 4th Gen Scarlett interfaces added software-controllable input gain
along with channel select, channel link, auto-gain, and "safe" mode.
Vocaster has software-controllable input gain and auto-gain but not
channel select, channel link, or safe mode.

Add a device info field safe_input_count to indicate how many channels
have a safe mode control, and use the presence of the input select and
input link switch configuration parameters to determine if those
controls should be created.

Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Message-ID: <167f04a37d0fb23f3077705df835adbc4f2b6a8e.1710264833.git.g@b4.vu>
This commit is contained in:
Geoffrey D. Bennett 2024-03-13 05:05:47 +10:30 committed by Takashi Iwai
parent b1b3b25824
commit 1e48ddb7d7

View File

@ -916,6 +916,9 @@ struct scarlett2_device_info {
/* the number of inputs with software-controllable gain */ /* the number of inputs with software-controllable gain */
u8 gain_input_count; u8 gain_input_count;
/* the number of inputs with safe mode */
u8 safe_input_count;
/* the number of direct monitor options /* the number of direct monitor options
* (0 = none, 1 = mono only, 2 = mono/stereo) * (0 = none, 1 = mono only, 2 = mono/stereo)
*/ */
@ -1550,6 +1553,7 @@ static const struct scarlett2_device_info s2i2_gen4_info = {
.phantom_count = 1, .phantom_count = 1,
.inputs_per_phantom = 2, .inputs_per_phantom = 2,
.gain_input_count = 2, .gain_input_count = 2,
.safe_input_count = 2,
.direct_monitor = 2, .direct_monitor = 2,
.dsp_count = 2, .dsp_count = 2,
@ -1603,6 +1607,7 @@ static const struct scarlett2_device_info s4i4_gen4_info = {
.phantom_count = 2, .phantom_count = 2,
.inputs_per_phantom = 1, .inputs_per_phantom = 1,
.gain_input_count = 2, .gain_input_count = 2,
.safe_input_count = 2,
.dsp_count = 2, .dsp_count = 2,
.port_count = { .port_count = {
@ -2937,13 +2942,18 @@ static void scarlett2_autogain_update_access(struct usb_mixer_interface *mixer)
int val = !scarlett2_autogain_is_running(private); int val = !scarlett2_autogain_is_running(private);
int i; int i;
scarlett2_set_ctl_access(private->input_select_ctl, val); if (scarlett2_has_config_item(private,
for (i = 0; i < info->gain_input_count / 2; i++) SCARLETT2_CONFIG_INPUT_SELECT_SWITCH))
scarlett2_set_ctl_access(private->input_link_ctls[i], val); scarlett2_set_ctl_access(private->input_select_ctl, val);
for (i = 0; i < info->gain_input_count; i++) { if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_LINK_SWITCH))
for (i = 0; i < info->gain_input_count / 2; i++)
scarlett2_set_ctl_access(private->input_link_ctls[i],
val);
for (i = 0; i < info->gain_input_count; i++)
scarlett2_set_ctl_access(private->input_gain_ctls[i], val); scarlett2_set_ctl_access(private->input_gain_ctls[i], val);
for (i = 0; i < info->safe_input_count; i++)
scarlett2_set_ctl_access(private->safe_ctls[i], val); scarlett2_set_ctl_access(private->safe_ctls[i], val);
}
for (i = 0; i < info->level_input_count; i++) for (i = 0; i < info->level_input_count; i++)
scarlett2_set_ctl_access(private->level_ctls[i], val); scarlett2_set_ctl_access(private->level_ctls[i], val);
for (i = 0; i < info->air_input_count; i++) for (i = 0; i < info->air_input_count; i++)
@ -2962,17 +2972,21 @@ static void scarlett2_autogain_notify_access(struct usb_mixer_interface *mixer)
const struct scarlett2_device_info *info = private->info; const struct scarlett2_device_info *info = private->info;
int i; int i;
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, if (scarlett2_has_config_item(private,
&private->input_select_ctl->id); SCARLETT2_CONFIG_INPUT_SELECT_SWITCH))
for (i = 0; i < info->gain_input_count / 2; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
&private->input_link_ctls[i]->id); &private->input_select_ctl->id);
for (i = 0; i < info->gain_input_count; i++) { if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_LINK_SWITCH))
for (i = 0; i < info->gain_input_count / 2; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
&private->input_link_ctls[i]->id);
for (i = 0; i < info->gain_input_count; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
&private->input_gain_ctls[i]->id); &private->input_gain_ctls[i]->id);
for (i = 0; i < info->safe_input_count; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
&private->safe_ctls[i]->id); &private->safe_ctls[i]->id);
}
for (i = 0; i < info->level_input_count; i++) for (i = 0; i < info->level_input_count; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
&private->level_ctls[i]->id); &private->level_ctls[i]->id);
@ -3183,7 +3197,9 @@ static int scarlett2_update_input_select(struct usb_mixer_interface *mixer)
private->input_select_updated = 0; private->input_select_updated = 0;
if (!link_count) if (!scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_SELECT_SWITCH) ||
!link_count)
return 0; return 0;
err = scarlett2_usb_get_config( err = scarlett2_usb_get_config(
@ -3596,12 +3612,12 @@ static int scarlett2_update_input_safe(struct usb_mixer_interface *mixer)
private->input_safe_updated = 0; private->input_safe_updated = 0;
if (!info->gain_input_count) if (!info->safe_input_count)
return 0; return 0;
return scarlett2_usb_get_config( return scarlett2_usb_get_config(
mixer, SCARLETT2_CONFIG_SAFE_SWITCH, mixer, SCARLETT2_CONFIG_SAFE_SWITCH,
info->gain_input_count, private->safe_switch); info->safe_input_count, private->safe_switch);
} }
static int scarlett2_safe_ctl_get(struct snd_kcontrol *kctl, static int scarlett2_safe_ctl_get(struct snd_kcontrol *kctl,
@ -5507,60 +5523,67 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer)
return err; return err;
} }
/* Add software-controllable input gain controls */ /* Add input select/link controls */
if (info->gain_input_count) { if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_SELECT_SWITCH)) {
err = scarlett2_add_new_ctl( err = scarlett2_add_new_ctl(
mixer, &scarlett2_input_select_ctl, 0, 1, mixer, &scarlett2_input_select_ctl, 0, 1,
"Input Select Capture Enum", "Input Select Capture Enum",
&private->input_select_ctl); &private->input_select_ctl);
if (err < 0) if (err < 0)
return err; return err;
}
for (i = 0; i < info->gain_input_count; i++) { if (scarlett2_has_config_item(private,
if (i % 2) { SCARLETT2_CONFIG_INPUT_LINK_SWITCH)) {
scnprintf(s, sizeof(s), for (i = 0; i < info->gain_input_count / 2; i++) {
"Line In %d-%d Link Capture Switch", scnprintf(s, sizeof(s),
i, i + 1); "Line In %d-%d Link Capture Switch",
err = scarlett2_add_new_ctl( (i * 2) + 1, (i * 2) + 2);
mixer, &scarlett2_input_link_ctl,
i / 2, 1, s,
&private->input_link_ctls[i / 2]);
if (err < 0)
return err;
}
scnprintf(s, sizeof(s), fmt, i + 1,
"Gain", "Volume");
err = scarlett2_add_new_ctl( err = scarlett2_add_new_ctl(
mixer, &scarlett2_input_gain_ctl, mixer, &scarlett2_input_link_ctl,
i, 1, s, &private->input_gain_ctls[i]); i, 1, s, &private->input_link_ctls[i]);
if (err < 0)
return err;
scnprintf(s, sizeof(s), fmt, i + 1,
"Autogain", "Switch");
err = scarlett2_add_new_ctl(
mixer, &scarlett2_autogain_switch_ctl,
i, 1, s, &private->autogain_ctls[i]);
if (err < 0)
return err;
scnprintf(s, sizeof(s), fmt, i + 1,
"Autogain Status", "Enum");
err = scarlett2_add_new_ctl(
mixer, &scarlett2_autogain_status_ctl,
i, 1, s, &private->autogain_status_ctls[i]);
scnprintf(s, sizeof(s), fmt, i + 1,
"Safe", "Switch");
err = scarlett2_add_new_ctl(
mixer, &scarlett2_safe_ctl,
i, 1, s, &private->safe_ctls[i]);
if (err < 0) if (err < 0)
return err; return err;
} }
} }
/* Add software-controllable input gain controls */
for (i = 0; i < info->gain_input_count; i++) {
scnprintf(s, sizeof(s), fmt, i + 1,
"Gain", "Volume");
err = scarlett2_add_new_ctl(
mixer, &scarlett2_input_gain_ctl,
i, 1, s, &private->input_gain_ctls[i]);
if (err < 0)
return err;
scnprintf(s, sizeof(s), fmt, i + 1,
"Autogain", "Switch");
err = scarlett2_add_new_ctl(
mixer, &scarlett2_autogain_switch_ctl,
i, 1, s, &private->autogain_ctls[i]);
if (err < 0)
return err;
scnprintf(s, sizeof(s), fmt, i + 1,
"Autogain Status", "Enum");
err = scarlett2_add_new_ctl(
mixer, &scarlett2_autogain_status_ctl,
i, 1, s, &private->autogain_status_ctls[i]);
}
/* Add safe-mode input switch controls */
for (i = 0; i < info->safe_input_count; i++) {
scnprintf(s, sizeof(s), fmt, i + 1,
"Safe", "Switch");
err = scarlett2_add_new_ctl(
mixer, &scarlett2_safe_ctl,
i, 1, s, &private->safe_ctls[i]);
if (err < 0)
return err;
}
/* Add PCM Input Switch control */ /* Add PCM Input Switch control */
if (scarlett2_has_config_item(private, if (scarlett2_has_config_item(private,
SCARLETT2_CONFIG_PCM_INPUT_SWITCH)) { SCARLETT2_CONFIG_PCM_INPUT_SWITCH)) {
@ -6557,7 +6580,8 @@ static void scarlett2_notify_input_select(struct usb_mixer_interface *mixer)
const struct scarlett2_device_info *info = private->info; const struct scarlett2_device_info *info = private->info;
int i; int i;
if (!info->gain_input_count) if (!scarlett2_has_config_item(private,
SCARLETT2_CONFIG_INPUT_SELECT_SWITCH))
return; return;
private->input_select_updated = 1; private->input_select_updated = 1;
@ -6620,12 +6644,12 @@ static void scarlett2_notify_input_safe(struct usb_mixer_interface *mixer)
const struct scarlett2_device_info *info = private->info; const struct scarlett2_device_info *info = private->info;
int i; int i;
if (!info->gain_input_count) if (!info->safe_input_count)
return; return;
private->input_safe_updated = 1; private->input_safe_updated = 1;
for (i = 0; i < info->gain_input_count; i++) for (i = 0; i < info->safe_input_count; i++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
&private->safe_ctls[i]->id); &private->safe_ctls[i]->id);
} }