Skip to content

Commit 2ecca0d

Browse files
geoffreybennetttiwai
authored andcommitted
ALSA: scarlett2: Add R/O headphone volume control
The Scarlett 4i4 Gen 4 adds a R/O headphone volume control in addition to a R/O master volume control (which is already supported). Mark the new scarlett2_notify_volume() function with __always_unused until it gets used when the Gen 4 notification callback function arrays are added. Signed-off-by: Geoffrey D. Bennett <g@b4.vu> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://lore.kernel.org/r/bd4a76da157f8cc3fbfa02eba96d02bdb86817c5.1703612638.git.g@b4.vu
1 parent f6a817e commit 2ecca0d

1 file changed

Lines changed: 81 additions & 1 deletion

File tree

sound/usb/mixer_scarlett2.c

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ enum {
332332
SCARLETT2_CONFIG_MUTE_SWITCH,
333333
SCARLETT2_CONFIG_SW_HW_SWITCH,
334334
SCARLETT2_CONFIG_MASTER_VOLUME,
335+
SCARLETT2_CONFIG_HEADPHONE_VOLUME,
335336
SCARLETT2_CONFIG_LEVEL_SWITCH,
336337
SCARLETT2_CONFIG_PAD_SWITCH,
337338
SCARLETT2_CONFIG_MSD_SWITCH,
@@ -784,6 +785,7 @@ struct scarlett2_data {
784785
u8 power_status_updated;
785786
u8 sync;
786787
u8 master_vol;
788+
u8 headphone_vol;
787789
u8 vol[SCARLETT2_ANALOGUE_MAX];
788790
u8 vol_sw_hw_switch[SCARLETT2_ANALOGUE_MAX];
789791
u8 mute_switch[SCARLETT2_ANALOGUE_MAX];
@@ -809,6 +811,7 @@ struct scarlett2_data {
809811
u8 meter_level_map[SCARLETT2_MAX_METERS];
810812
struct snd_kcontrol *sync_ctl;
811813
struct snd_kcontrol *master_vol_ctl;
814+
struct snd_kcontrol *headphone_vol_ctl;
812815
struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX];
813816
struct snd_kcontrol *sw_hw_ctls[SCARLETT2_ANALOGUE_MAX];
814817
struct snd_kcontrol *mute_ctls[SCARLETT2_ANALOGUE_MAX];
@@ -3324,6 +3327,18 @@ static int scarlett2_update_volumes(struct usb_mixer_interface *mixer)
33243327
private->vol[i] = private->master_vol;
33253328
}
33263329

3330+
if (scarlett2_has_config_item(private,
3331+
SCARLETT2_CONFIG_HEADPHONE_VOLUME)) {
3332+
err = scarlett2_usb_get_config(
3333+
mixer, SCARLETT2_CONFIG_HEADPHONE_VOLUME,
3334+
1, &vol);
3335+
if (err < 0)
3336+
return err;
3337+
3338+
private->headphone_vol = clamp(vol + SCARLETT2_VOLUME_BIAS,
3339+
0, SCARLETT2_VOLUME_BIAS);
3340+
}
3341+
33273342
return 0;
33283343
}
33293344

@@ -3367,6 +3382,34 @@ static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl,
33673382
return err;
33683383
}
33693384

3385+
static int scarlett2_headphone_volume_ctl_get(
3386+
struct snd_kcontrol *kctl,
3387+
struct snd_ctl_elem_value *ucontrol)
3388+
{
3389+
struct usb_mixer_elem_info *elem = kctl->private_data;
3390+
struct usb_mixer_interface *mixer = elem->head.mixer;
3391+
struct scarlett2_data *private = mixer->private_data;
3392+
int err = 0;
3393+
3394+
mutex_lock(&private->data_mutex);
3395+
3396+
if (private->hwdep_in_use) {
3397+
err = -EBUSY;
3398+
goto unlock;
3399+
}
3400+
3401+
if (private->vol_updated) {
3402+
err = scarlett2_update_volumes(mixer);
3403+
if (err < 0)
3404+
goto unlock;
3405+
}
3406+
ucontrol->value.integer.value[0] = private->headphone_vol;
3407+
3408+
unlock:
3409+
mutex_unlock(&private->data_mutex);
3410+
return err;
3411+
}
3412+
33703413
static int line_out_remap(struct scarlett2_data *private, int index)
33713414
{
33723415
const struct scarlett2_device_info *info = private->info;
@@ -3456,6 +3499,17 @@ static const struct snd_kcontrol_new scarlett2_master_volume_ctl = {
34563499
.tlv = { .p = db_scale_scarlett2_volume }
34573500
};
34583501

3502+
static const struct snd_kcontrol_new scarlett2_headphone_volume_ctl = {
3503+
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3504+
.access = SNDRV_CTL_ELEM_ACCESS_READ |
3505+
SNDRV_CTL_ELEM_ACCESS_TLV_READ,
3506+
.name = "",
3507+
.info = scarlett2_volume_ctl_info,
3508+
.get = scarlett2_headphone_volume_ctl_get,
3509+
.private_value = 0, /* max value */
3510+
.tlv = { .p = db_scale_scarlett2_volume }
3511+
};
3512+
34593513
static const struct snd_kcontrol_new scarlett2_line_out_volume_ctl = {
34603514
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
34613515
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -4806,6 +4860,18 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer)
48064860
return err;
48074861
}
48084862

4863+
/* Add R/O headphone volume control */
4864+
if (scarlett2_has_config_item(private,
4865+
SCARLETT2_CONFIG_HEADPHONE_VOLUME)) {
4866+
snprintf(s, sizeof(s), "Headphone Playback Volume");
4867+
err = scarlett2_add_new_ctl(mixer,
4868+
&scarlett2_headphone_volume_ctl,
4869+
0, 1, s,
4870+
&private->headphone_vol_ctl);
4871+
if (err < 0)
4872+
return err;
4873+
}
4874+
48094875
/* Remaining controls are only applicable if the device
48104876
* has per-channel line-out volume controls.
48114877
*/
@@ -6265,7 +6331,7 @@ static void scarlett2_notify_sync(struct usb_mixer_interface *mixer)
62656331
&private->sync_ctl->id);
62666332
}
62676333

6268-
/* Notify on monitor change */
6334+
/* Notify on monitor change (Gen 2/3) */
62696335
static void scarlett2_notify_monitor(struct usb_mixer_interface *mixer)
62706336
{
62716337
struct snd_card *card = mixer->chip->card;
@@ -6286,6 +6352,20 @@ static void scarlett2_notify_monitor(struct usb_mixer_interface *mixer)
62866352
&private->vol_ctls[i]->id);
62876353
}
62886354

6355+
/* Notify on volume change (Gen 4) */
6356+
static __always_unused void scarlett2_notify_volume(
6357+
struct usb_mixer_interface *mixer)
6358+
{
6359+
struct scarlett2_data *private = mixer->private_data;
6360+
6361+
private->vol_updated = 1;
6362+
6363+
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
6364+
&private->master_vol_ctl->id);
6365+
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
6366+
&private->headphone_vol_ctl->id);
6367+
}
6368+
62896369
/* Notify on dim/mute change */
62906370
static void scarlett2_notify_dim_mute(struct usb_mixer_interface *mixer)
62916371
{

0 commit comments

Comments
 (0)