Skip to content

Commit 4a2c8cc

Browse files
geoffreybennetttiwai
authored andcommitted
ALSA: scarlett2: Add PCM Input Switch for Solo Gen 4
When the Direct button on the Solo Gen 4 is held for 3 seconds, the PCM 1 and 2 inputs are toggled between DSP Outputs 1 and 2, and Mixer Outputs E and F. This patch adds the corresponding ALSA control. Signed-off-by: Geoffrey D. Bennett <g@b4.vu> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://lore.kernel.org/r/8c67c6131c459588ac4edab11e1fbc40a8297328.1703612638.git.g@b4.vu
1 parent 4e809a2 commit 4a2c8cc

1 file changed

Lines changed: 151 additions & 0 deletions

File tree

sound/usb/mixer_scarlett2.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ static void scarlett2_notify_input_safe(struct usb_mixer_interface *mixer);
324324
static void scarlett2_notify_monitor_other(struct usb_mixer_interface *mixer);
325325
static void scarlett2_notify_direct_monitor(struct usb_mixer_interface *mixer);
326326
static void scarlett2_notify_power_status(struct usb_mixer_interface *mixer);
327+
static void scarlett2_notify_pcm_input_switch(
328+
struct usb_mixer_interface *mixer);
327329

328330
/* Arrays of notification callback functions */
329331

@@ -351,6 +353,7 @@ static const struct scarlett2_notification scarlett4_solo_notifications[] = {
351353
{ 0x00800000, scarlett2_notify_direct_monitor },
352354
{ 0x01000000, scarlett2_notify_input_level },
353355
{ 0x02000000, scarlett2_notify_input_phantom },
356+
{ 0x04000000, scarlett2_notify_pcm_input_switch },
354357
{ 0, NULL }
355358
};
356359

@@ -413,6 +416,7 @@ enum {
413416
SCARLETT2_CONFIG_INPUT_LINK_SWITCH,
414417
SCARLETT2_CONFIG_POWER_EXT,
415418
SCARLETT2_CONFIG_POWER_STATUS,
419+
SCARLETT2_CONFIG_PCM_INPUT_SWITCH,
416420
SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN,
417421
SCARLETT2_CONFIG_COUNT
418422
};
@@ -624,6 +628,9 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_solo = {
624628
[SCARLETT2_CONFIG_AIR_SWITCH] = {
625629
.offset = 0x3e, .activate = 11 },
626630

631+
[SCARLETT2_CONFIG_PCM_INPUT_SWITCH] = {
632+
.offset = 0x206, .activate = 25 },
633+
627634
[SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = {
628635
.offset = 0x232, .size = 16, .activate = 26 }
629636
}
@@ -955,6 +962,7 @@ struct scarlett2_data {
955962
u8 input_gain_updated;
956963
u8 autogain_updated;
957964
u8 input_safe_updated;
965+
u8 pcm_input_switch_updated;
958966
u8 monitor_other_updated;
959967
u8 direct_monitor_updated;
960968
u8 mux_updated;
@@ -979,6 +987,7 @@ struct scarlett2_data {
979987
u8 autogain_switch[SCARLETT2_INPUT_GAIN_MAX];
980988
u8 autogain_status[SCARLETT2_INPUT_GAIN_MAX];
981989
u8 safe_switch[SCARLETT2_INPUT_GAIN_MAX];
990+
u8 pcm_input_switch;
982991
u8 direct_monitor_switch;
983992
u8 speaker_switching_switch;
984993
u8 talkback_switch;
@@ -1004,6 +1013,7 @@ struct scarlett2_data {
10041013
struct snd_kcontrol *autogain_ctls[SCARLETT2_INPUT_GAIN_MAX];
10051014
struct snd_kcontrol *autogain_status_ctls[SCARLETT2_INPUT_GAIN_MAX];
10061015
struct snd_kcontrol *safe_ctls[SCARLETT2_INPUT_GAIN_MAX];
1016+
struct snd_kcontrol *pcm_input_switch_ctl;
10071017
struct snd_kcontrol *mux_ctls[SCARLETT2_MUX_MAX];
10081018
struct snd_kcontrol *mix_ctls[SCARLETT2_MIX_MAX];
10091019
struct snd_kcontrol *direct_monitor_ctl;
@@ -3633,6 +3643,101 @@ static const struct snd_kcontrol_new scarlett2_safe_ctl = {
36333643
.put = scarlett2_safe_ctl_put,
36343644
};
36353645

3646+
/*** PCM Input Control ***/
3647+
3648+
static int scarlett2_update_pcm_input_switch(struct usb_mixer_interface *mixer)
3649+
{
3650+
struct scarlett2_data *private = mixer->private_data;
3651+
int err;
3652+
3653+
private->pcm_input_switch_updated = 0;
3654+
3655+
err = scarlett2_usb_get_config(
3656+
mixer, SCARLETT2_CONFIG_PCM_INPUT_SWITCH,
3657+
1, &private->pcm_input_switch);
3658+
if (err < 0)
3659+
return err;
3660+
3661+
return 0;
3662+
}
3663+
3664+
static int scarlett2_pcm_input_switch_ctl_get(
3665+
struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
3666+
{
3667+
struct usb_mixer_elem_info *elem = kctl->private_data;
3668+
struct usb_mixer_interface *mixer = elem->head.mixer;
3669+
struct scarlett2_data *private = elem->head.mixer->private_data;
3670+
int err = 0;
3671+
3672+
mutex_lock(&private->data_mutex);
3673+
3674+
if (private->pcm_input_switch_updated) {
3675+
err = scarlett2_update_pcm_input_switch(mixer);
3676+
if (err < 0)
3677+
goto unlock;
3678+
}
3679+
ucontrol->value.enumerated.item[0] = private->pcm_input_switch;
3680+
3681+
unlock:
3682+
mutex_unlock(&private->data_mutex);
3683+
return err;
3684+
}
3685+
3686+
static int scarlett2_pcm_input_switch_ctl_put(
3687+
struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
3688+
{
3689+
struct usb_mixer_elem_info *elem = kctl->private_data;
3690+
struct usb_mixer_interface *mixer = elem->head.mixer;
3691+
struct scarlett2_data *private = mixer->private_data;
3692+
3693+
int oval, val, err = 0;
3694+
3695+
mutex_lock(&private->data_mutex);
3696+
3697+
if (private->hwdep_in_use) {
3698+
err = -EBUSY;
3699+
goto unlock;
3700+
}
3701+
3702+
oval = private->pcm_input_switch;
3703+
val = !!ucontrol->value.integer.value[0];
3704+
3705+
if (oval == val)
3706+
goto unlock;
3707+
3708+
private->pcm_input_switch = val;
3709+
3710+
/* Send switch change to the device */
3711+
err = scarlett2_usb_set_config(
3712+
mixer, SCARLETT2_CONFIG_PCM_INPUT_SWITCH,
3713+
0, val);
3714+
if (err == 0)
3715+
err = 1;
3716+
3717+
unlock:
3718+
mutex_unlock(&private->data_mutex);
3719+
return err;
3720+
}
3721+
3722+
static int scarlett2_pcm_input_switch_ctl_info(
3723+
struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
3724+
{
3725+
static const char *const values[2] = {
3726+
"Direct", "Mixer"
3727+
};
3728+
3729+
return snd_ctl_enum_info(
3730+
uinfo, 1, 2, values);
3731+
}
3732+
3733+
static const struct snd_kcontrol_new scarlett2_pcm_input_switch_ctl = {
3734+
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3735+
.name = "",
3736+
.info = scarlett2_pcm_input_switch_ctl_info,
3737+
.get = scarlett2_pcm_input_switch_ctl_get,
3738+
.put = scarlett2_pcm_input_switch_ctl_put
3739+
};
3740+
36363741
/*** Analogue Line Out Volume Controls ***/
36373742

36383743
/* Update hardware volume controls after receiving notification that
@@ -5419,6 +5524,17 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer)
54195524
}
54205525
}
54215526

5527+
/* Add PCM Input Switch control */
5528+
if (scarlett2_has_config_item(private,
5529+
SCARLETT2_CONFIG_PCM_INPUT_SWITCH)) {
5530+
err = scarlett2_add_new_ctl(
5531+
mixer, &scarlett2_pcm_input_switch_ctl, 0, 1,
5532+
"PCM Input Capture Switch",
5533+
&private->pcm_input_switch_ctl);
5534+
if (err < 0)
5535+
return err;
5536+
}
5537+
54225538
return 0;
54235539
}
54245540

@@ -6650,6 +6766,13 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
66506766
if (err < 0)
66516767
return err;
66526768

6769+
if (scarlett2_has_config_item(private,
6770+
SCARLETT2_CONFIG_PCM_INPUT_SWITCH)) {
6771+
err = scarlett2_update_pcm_input_switch(mixer);
6772+
if (err < 0)
6773+
return err;
6774+
}
6775+
66536776
err = scarlett2_update_mix(mixer);
66546777
if (err < 0)
66556778
return err;
@@ -6946,6 +7069,34 @@ static void scarlett2_notify_power_status(struct usb_mixer_interface *mixer)
69467069
&private->power_status_ctl->id);
69477070
}
69487071

7072+
/* Notify on mux change */
7073+
static void scarlett2_notify_mux(struct usb_mixer_interface *mixer)
7074+
{
7075+
struct snd_card *card = mixer->chip->card;
7076+
struct scarlett2_data *private = mixer->private_data;
7077+
int i;
7078+
7079+
private->mux_updated = 1;
7080+
7081+
for (i = 0; i < private->num_mux_dsts; i++)
7082+
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
7083+
&private->mux_ctls[i]->id);
7084+
}
7085+
7086+
/* Notify on PCM input switch change */
7087+
static void scarlett2_notify_pcm_input_switch(struct usb_mixer_interface *mixer)
7088+
{
7089+
struct snd_card *card = mixer->chip->card;
7090+
struct scarlett2_data *private = mixer->private_data;
7091+
7092+
private->pcm_input_switch_updated = 1;
7093+
7094+
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
7095+
&private->pcm_input_switch_ctl->id);
7096+
7097+
scarlett2_notify_mux(mixer);
7098+
}
7099+
69497100
/* Interrupt callback */
69507101
static void scarlett2_notify(struct urb *urb)
69517102
{

0 commit comments

Comments
 (0)