mirror of https://github.com/torvalds/linux.git
ALSA: scarlett2: Add Vocaster speaker/headphone mute controls
Add support for the speaker and headphone mute controls on Focusrite Vocaster interfaces. Unlike other Focusrite interfaces, these mute controls are per-output, not per-channel. Signed-off-by: Geoffrey D. Bennett <g@b4.vu> Link: https://patch.msgid.link/aLm2Dy6+O/eLTGVn@m.b4.vu Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
400f60b274
commit
cbd676874e
|
|
@ -10,8 +10,9 @@
|
|||
* - Solo/2i2/4i4 Gen 4
|
||||
* - Clarett 2Pre/4Pre/8Pre USB
|
||||
* - Clarett+ 2Pre/4Pre/8Pre
|
||||
* - Vocaster One/Two
|
||||
*
|
||||
* Copyright (c) 2018-2024 by Geoffrey D. Bennett <g at b4.vu>
|
||||
* Copyright (c) 2018-2025 by Geoffrey D. Bennett <g at b4.vu>
|
||||
* Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com>
|
||||
* Copyright (c) 2022 by Christian Colglazier <christian@cacolglazier.com>
|
||||
*
|
||||
|
|
@ -75,6 +76,9 @@
|
|||
* to many LinuxMusicians people and to Focusrite for hardware
|
||||
* donations).
|
||||
*
|
||||
* Support for Vocaster One and Two added in Mar 2024 (thanks to many
|
||||
* LinuxMusicians people and to Focusrite for hardware donations).
|
||||
*
|
||||
* This ALSA mixer gives access to (model-dependent):
|
||||
* - input, output, mixer-matrix muxes
|
||||
* - mixer-matrix gain stages
|
||||
|
|
@ -364,6 +368,21 @@ static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = {
|
|||
"Mute Playback Switch", "Dim Playback Switch"
|
||||
};
|
||||
|
||||
/* Vocaster One speaker/headphone mute names */
|
||||
static const char *const vocaster_one_sp_hp_mute_names[] = {
|
||||
"Speaker Mute Playback Switch",
|
||||
"Headphones Mute Playback Switch",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Vocaster Two speaker/headphone mute names */
|
||||
static const char *const vocaster_two_sp_hp_mute_names[] = {
|
||||
"Speaker Mute Playback Switch",
|
||||
"Headphones 1 Mute Playback Switch",
|
||||
"Headphones 2 Mute Playback Switch",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* The autogain_status is set based on the autogain_switch and
|
||||
* raw_autogain_status values.
|
||||
*
|
||||
|
|
@ -547,6 +566,7 @@ enum {
|
|||
SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN,
|
||||
SCARLETT2_CONFIG_BLUETOOTH_VOLUME,
|
||||
SCARLETT2_CONFIG_SPDIF_MODE,
|
||||
SCARLETT2_CONFIG_SP_HP_MUTE,
|
||||
SCARLETT2_CONFIG_COUNT
|
||||
};
|
||||
|
||||
|
|
@ -814,6 +834,9 @@ static const struct scarlett2_config_set scarlett2_config_set_vocaster = {
|
|||
|
||||
[SCARLETT2_CONFIG_BLUETOOTH_VOLUME] = {
|
||||
.offset = 0xbf, .size = 8, .activate = 28 },
|
||||
|
||||
[SCARLETT2_CONFIG_SP_HP_MUTE] = {
|
||||
.offset = 0xab, .size = 8, .activate = 10 },
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1177,6 +1200,9 @@ struct scarlett2_device_info {
|
|||
/* additional description for the line out volume controls */
|
||||
const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX];
|
||||
|
||||
/* Vocaster speaker/headphone mute control names */
|
||||
const char * const *sp_hp_mute_names;
|
||||
|
||||
/* number of sources/destinations of each port type */
|
||||
const int port_count[SCARLETT2_PORT_TYPE_COUNT][SCARLETT2_PORT_DIRNS];
|
||||
|
||||
|
|
@ -1249,6 +1275,7 @@ struct scarlett2_data {
|
|||
u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX];
|
||||
u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX];
|
||||
u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT];
|
||||
u8 sp_hp_mute;
|
||||
u8 air_switch[SCARLETT2_AIR_SWITCH_MAX];
|
||||
u8 dsp_switch[SCARLETT2_DSP_SWITCH_MAX];
|
||||
s32 compressor_values[SCARLETT2_COMPRESSOR_CTLS_MAX];
|
||||
|
|
@ -1791,6 +1818,7 @@ static const struct scarlett2_device_info vocaster_one_info = {
|
|||
.peq_flt_total_count = 4,
|
||||
.mute_input_count = 1,
|
||||
.gain_input_count = 1,
|
||||
.sp_hp_mute_names = vocaster_one_sp_hp_mute_names,
|
||||
|
||||
.port_count = {
|
||||
[SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
|
||||
|
|
@ -1835,6 +1863,7 @@ static const struct scarlett2_device_info vocaster_two_info = {
|
|||
.mute_input_count = 2,
|
||||
.gain_input_count = 2,
|
||||
.has_bluetooth = 1,
|
||||
.sp_hp_mute_names = vocaster_two_sp_hp_mute_names,
|
||||
|
||||
.port_count = {
|
||||
[SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
|
||||
|
|
@ -6293,6 +6322,61 @@ static const struct snd_kcontrol_new scarlett2_dim_mute_ctl = {
|
|||
.put = scarlett2_dim_mute_ctl_put
|
||||
};
|
||||
|
||||
/*** Vocaster Speaker/Headphone Mute Controls ***/
|
||||
|
||||
static int scarlett2_sp_hp_mute_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->sp_hp_mute & (1 << elem->control));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scarlett2_sp_hp_mute_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 index = elem->control;
|
||||
int val, err;
|
||||
|
||||
guard(mutex)(&private->data_mutex);
|
||||
|
||||
if (private->hwdep_in_use)
|
||||
return -EBUSY;
|
||||
|
||||
val = private->sp_hp_mute;
|
||||
|
||||
if (ucontrol->value.integer.value[0])
|
||||
val |= (1 << index);
|
||||
else
|
||||
val &= ~(1 << index);
|
||||
|
||||
if (val == private->sp_hp_mute)
|
||||
return 0;
|
||||
|
||||
private->sp_hp_mute = val;
|
||||
|
||||
/* Send change to the device */
|
||||
err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SP_HP_MUTE,
|
||||
0, val);
|
||||
|
||||
return err < 0 ? err : 1;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new scarlett2_sp_hp_mute_ctl = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "",
|
||||
.info = snd_ctl_boolean_mono_info,
|
||||
.get = scarlett2_sp_hp_mute_ctl_get,
|
||||
.put = scarlett2_sp_hp_mute_ctl_put
|
||||
};
|
||||
|
||||
/*** Create the analogue output controls ***/
|
||||
|
||||
static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer)
|
||||
|
|
@ -6325,6 +6409,17 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Add Vocaster speaker/headphone mute controls */
|
||||
if (private->info->sp_hp_mute_names)
|
||||
for (i = 0; private->info->sp_hp_mute_names[i]; i++) {
|
||||
err = scarlett2_add_new_ctl(
|
||||
mixer, &scarlett2_sp_hp_mute_ctl,
|
||||
i, 1, private->info->sp_hp_mute_names[i],
|
||||
NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Remaining controls are only applicable if the device
|
||||
* has per-channel line-out volume controls.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue