aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
authorSimon Wood <simon@mungewell.org>2026-05-11 15:24:58 -0600
committerTakashi Iwai <tiwai@suse.de>2026-05-15 08:55:20 +0200
commitda5e9f8e552128ba7f7b930986d31567f2b188a3 (patch)
tree65decead0ff6af0815c549e6224633d1bcd968e1 /sound
parentcb02416507bc0c31415f1527aefc280ae96260bd (diff)
downloadlinux-next-history-da5e9f8e552128ba7f7b930986d31567f2b188a3.tar.gz
ALSA: M-Audio C600 disable Output Gain Knob
The C400/C600 interfaces have a large output gain knob which attenuates the outputs as stereo pairs (1/2, 3/4 and 5/6). The Windows driver/app provides a control to disable this knob/behaviour on any/all outputs, forcing maximum gain on each. The 'disable behaviour' is desirable if any outputs are being used for aux/effects sends, or if interface is being used as a live/matrix mixer. This patch adds a control to select which output pairs are affected by the Output Gain Knob. Default behaviour is to select all outputs. Tested on the C600, likely also works for the C400. Signed-off-by: Simon Wood <simon@mungewell.org> Link: https://patch.msgid.link/20260511212458.44142-1-simon@mungewell.org Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/mixer_quirks.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 99975c3240a55..628f841b04aae 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -1301,7 +1301,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer,
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- pval & 0xff00,
+ (pval & 0xff00) | ((pval & 0xff0000) >> 16),
snd_usb_ctrl_intf(mixer->hostif) | ((pval & 0xff) << 8),
value, 2);
if (err < 0)
@@ -1334,7 +1334,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list)
usb_sndctrlpipe(chip->dev, 0),
UAC_SET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- pval & 0xff00,
+ (pval & 0xff00) | ((pval & 0xff0000) >> 16),
snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8),
value, 2);
}
@@ -1754,6 +1754,44 @@ static int snd_c400_create_effect_ret_vol_ctls(struct usb_mixer_interface *mixer
return 0;
}
+/* output gain knob selectively adjusts outputs as stereo pairs */
+/* reuses functions from FTU effect switch */
+static int snd_c400_knob_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char *const texts[8] = {
+ "None", "1/2", "3/4", "1/2 3/4",
+ "5/6", "1/2 5/6", "3/4 5/6", "1/2 3/4 5/6"
+ };
+
+ return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
+}
+
+static int snd_c400_create_knob_switch(struct usb_mixer_interface *mixer,
+ int validx, int bUnitID)
+{
+ static struct snd_kcontrol_new template = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Output Gain Knob",
+ .index = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_c400_knob_switch_info,
+ .get = snd_ftu_eff_switch_get,
+ .put = snd_ftu_eff_switch_put
+ };
+ struct usb_mixer_elem_list *list;
+ int err;
+
+ err = add_single_ctl_with_resume(mixer, bUnitID,
+ snd_ftu_eff_switch_update,
+ &template, &list);
+ if (err < 0)
+ return err;
+ list->kctl->private_value = (validx << 8) | bUnitID;
+ snd_ftu_eff_switch_init(mixer, list->kctl);
+ return 0;
+}
+
static int snd_c400_create_mixer(struct usb_mixer_interface *mixer)
{
int err;
@@ -1786,6 +1824,10 @@ static int snd_c400_create_mixer(struct usb_mixer_interface *mixer)
if (err < 0)
return err;
+ err = snd_c400_create_knob_switch(mixer, 0x0900, 0x20);
+ if (err < 0)
+ return err;
+
return 0;
}