* [PATCH 0/3] Add Audient EVO4 support
@ 2026-09-19 15:18 Christian Ruppert
2026-09-19 15:18 ` [PATCH 1/3] Fix Audient EVO4 master playback control name Christian Ruppert
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Christian Ruppert @ 2026-09-19 15:18 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai, linux-kernel, linux-sound
Cc: Christian Ruppert, Will Porter, Peter Drabik, Neil Andrews
This patch set adds support for advanced mixer features of the Audient
EVO4 audio interface. The code is structured so that support for the
EVO8 (and potentially other Audient devices) should be trivial to add
but I don't have access to the hardware and no way of testing them so
they are not supported by this patch set.
The third patch in the series (Add Kconfig option for Audient EVO4 mixer
quirks) is optional. Other mixer quirks are compiled in by default and
don't provide Kconfig options but as this one adds a few hundred lines
of code I decided to provide this last patch as an option and leave the
choice if such an option should be added to the subsystem maintainers.
Christian Ruppert (3):
Fix Audient EVO4 master playback control name
Add Audient EVO4 mixer quirks
Add Kconfig option for Audient EVO4 mixer quirks
MAINTAINERS | 7 +
sound/usb/Kconfig | 10 +
sound/usb/Makefile | 2 +
sound/usb/mixer_evo.c | 505 +++++++++++++++++++++++++++++++++++++++
sound/usb/mixer_evo.h | 12 +
sound/usb/mixer_maps.c | 13 +
sound/usb/mixer_quirks.c | 9 +
7 files changed, 558 insertions(+)
create mode 100644 sound/usb/mixer_evo.c
create mode 100644 sound/usb/mixer_evo.h
--
2.55.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 1/3] Fix Audient EVO4 master playback control name 2026-09-19 15:18 [PATCH 0/3] Add Audient EVO4 support Christian Ruppert @ 2026-09-19 15:18 ` Christian Ruppert 2026-09-19 15:18 ` [PATCH 2/3] Add Audient EVO4 mixer quirks Christian Ruppert ` (2 subsequent siblings) 3 siblings, 0 replies; 7+ messages in thread From: Christian Ruppert @ 2026-09-19 15:18 UTC (permalink / raw) To: Jaroslav Kysela, Takashi Iwai, linux-kernel, linux-sound Cc: Christian Ruppert, Will Porter, Peter Drabik, Neil Andrews The Audient EVO4 master volume mixer channel enumerates as 'EVO4 '. Rename it to 'Master' according to control-names.rst. Signed-off-by: Christian Ruppert <arc@gmx.li> --- sound/usb/mixer_maps.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index 41454cb403d0..1a6ad776126b 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c @@ -505,6 +505,14 @@ static const struct usbmix_connector_map gigabyte_b450_connector_map[] = { {} }; +/* Audient EVO4: Rename FU 10 from 'EVO4 ' to 'Master' according to the + * ALSA naming convention + */ +static const struct usbmix_name_map audient_evo4_map[] = { + { 10, "Master Playback" }, + {} +}; + /* Audient iD14 MkI and MkII: FU 12 sits on the monitor mixer branch but is * traced through to the Speaker output terminal, so it is named "Speaker * Playback Volume". On MkII it controls only 4 of 6 playback channels. MkI @@ -632,6 +640,11 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x2708, 0x0002), .map = audient_id14_map, }, + { + /* Audient EVO4 MkI */ + .id = USB_ID(0x2708, 0x0006), + .map = audient_evo4_map, + }, { /* Audient iD14 MkII */ .id = USB_ID(0x2708, 0x0008), -- 2.55.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/3] Add Audient EVO4 mixer quirks 2026-09-19 15:18 [PATCH 0/3] Add Audient EVO4 support Christian Ruppert 2026-09-19 15:18 ` [PATCH 1/3] Fix Audient EVO4 master playback control name Christian Ruppert @ 2026-09-19 15:18 ` Christian Ruppert 2026-09-19 15:18 ` [PATCH 3/3] Add Kconfig option for " Christian Ruppert 2026-09-25 10:18 ` [PATCH 0/3] Add Audient EVO4 support Faaris Ansari 3 siblings, 0 replies; 7+ messages in thread From: Christian Ruppert @ 2026-09-19 15:18 UTC (permalink / raw) To: Jaroslav Kysela, Takashi Iwai, linux-kernel, linux-sound Cc: Christian Ruppert, Will Porter, Peter Drabik, Neil Andrews The controls enumerated by the Audient EVO4 are incomplete. Add missing controls for * channel muting * the cross-fader * the recording mixer * phantom power The driver is structured so that it should be trivial to extend it to the EVO8 (and potentially other Audient devices) but we need a kind soul who has access to that hardware to correctly map the control names and test everything. Signed-off-by: Christian Ruppert <arc@gmx.li> --- MAINTAINERS | 7 + sound/usb/Makefile | 1 + sound/usb/mixer_evo.c | 505 +++++++++++++++++++++++++++++++++++++++ sound/usb/mixer_evo.h | 12 + sound/usb/mixer_quirks.c | 5 + 5 files changed, 530 insertions(+) create mode 100644 sound/usb/mixer_evo.c create mode 100644 sound/usb/mixer_evo.h diff --git a/MAINTAINERS b/MAINTAINERS index c2414447892c..5f8df442b1a5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4346,6 +4346,13 @@ F: drivers/net/ieee802154/at86rf230.h F: drivers/net/ieee802154/atusb.c F: drivers/net/ieee802154/atusb.h +AUDIENT EVO MIXER DRIVER +M: Christian Ruppert <arc@gmx.li> +L: linux-sound@vger.kernel.org +S: Maintained +F: sound/usb/mixer_evo.c +F: sound/usb/mixer_evo.h + AUDIT SUBSYSTEM M: Paul Moore <paul@paul-moore.com> M: Eric Paris <eparis@redhat.com> diff --git a/sound/usb/Makefile b/sound/usb/Makefile index e62794a87e73..2e842dcc73de 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -11,6 +11,7 @@ snd-usb-audio-y := card.o \ helper.o \ implicit.o \ mixer.o \ + mixer_evo.o \ mixer_quirks.o \ mixer_scarlett.o \ mixer_scarlett2.o \ diff --git a/sound/usb/mixer_evo.c b/sound/usb/mixer_evo.c new file mode 100644 index 000000000000..c327b82c8d2d --- /dev/null +++ b/sound/usb/mixer_evo.c @@ -0,0 +1,505 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Audient EVO driver for ALSA + * Copyright (C) 2026 Christian Ruppert <arc@gmx.li> + * + * Based on the work of Ivan Hazucha for audient-evo-py. + * https://github.com/vanzaho/audient-evo-py/ + */ + + +#include <asm/byteorder.h> +#include <linux/usb.h> +#include <linux/usb/audio-v2.h> +#include <linux/slab.h> +#include <sound/core.h> +#include <sound/control.h> + +#include "usbaudio.h" +#include "mixer.h" +#include "mixer_quirks.h" +#include "helper.h" +#include "mixer_evo.h" + + +enum snd_evo_type { + SND_EVO_TYPE_MONITOR = 0, + SND_EVO_TYPE_PHANTOM, + SND_EVO_TYPE_MUTE, + SND_EVO_TYPE_MUTE_OUT, + SND_EVO_TYPE_MIXER, + SND_EVO_TYPE_NCTYPES +}; + +static const struct snd_evo_ctrl_type { + snd_ctl_elem_type_t type; + bool invert; + union { + int integer; + } min; + union { + int integer; + } max; + u16 wValue; + u16 wIndex; +} snd_evo_ctypes[SND_EVO_TYPE_NCTYPES] = { + [SND_EVO_TYPE_MONITOR] = { + .type = SNDRV_CTL_ELEM_TYPE_INTEGER, + .min.integer = 0, + .max.integer = 127, + .wValue = 0x0000, + .wIndex = 0x3800, + }, + [SND_EVO_TYPE_PHANTOM] = { + .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, + .invert = false, + .min.integer = 0, + .max.integer = 1, + .wValue = 0x0000, + .wIndex = 0x3A00, + }, + [SND_EVO_TYPE_MUTE] = { + .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, + .invert = true, + .min.integer = 0, + .max.integer = 1, + .wValue = 0x0200, + .wIndex = 0x3A00, + }, + [SND_EVO_TYPE_MUTE_OUT] = { + .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, + .invert = true, + .min.integer = 0, + .max.integer = 1, + .wValue = 0x0100, + .wIndex = 0x3B00, + }, + [SND_EVO_TYPE_MIXER] = { + .type = SNDRV_CTL_ELEM_TYPE_INTEGER, + .min.integer = -128 * 256, + .max.integer = 6 * 256, + .wValue = 0x0100, + .wIndex = 0x3C00, + }, +}; + +#define SND_EVO_FLAGS_DIRECTION (1L<<0) +#define SND_EVO_FLAGS_CAPTURE (1L<<0) +#define SND_EVO_FLAGS_PLAYBACK (0L<<0) + +struct snd_evo_ctrl { + char *basename; + enum snd_evo_type type; + unsigned int channels; + unsigned int hwchannels; + unsigned int val_offs; + unsigned long flags; +}; + +static const struct snd_evo_ctrl evo4_controls[] = { + { + .basename = "Master", + .type = SND_EVO_TYPE_MUTE_OUT, + .channels = 1, + .hwchannels = 1, + .val_offs = 0, + .flags = SND_EVO_FLAGS_PLAYBACK, + }, + { + .basename = "Mic", + .type = SND_EVO_TYPE_MUTE, + .channels = 4, + .hwchannels = 2, + .val_offs = 0, + .flags = SND_EVO_FLAGS_PLAYBACK, + }, + { + .basename = "Monitor", + .type = SND_EVO_TYPE_MONITOR, + .channels = 1, + .hwchannels = 1, + .val_offs = 0, + .flags = SND_EVO_FLAGS_PLAYBACK, + }, + { + .basename = "Mic 1", + .type = SND_EVO_TYPE_MIXER, + .channels = 2, + .hwchannels = 2, + .val_offs = 0, + .flags = SND_EVO_FLAGS_CAPTURE, + }, + { + .basename = "Mic 2", + .type = SND_EVO_TYPE_MIXER, + .channels = 2, + .hwchannels = 2, + .val_offs = 2, + .flags = SND_EVO_FLAGS_CAPTURE, + }, + { + .basename = "Master Left", + .type = SND_EVO_TYPE_MIXER, + .channels = 2, + .hwchannels = 2, + .val_offs = 4, + .flags = SND_EVO_FLAGS_CAPTURE, + }, + { + .basename = "Master Right", + .type = SND_EVO_TYPE_MIXER, + .channels = 2, + .hwchannels = 2, + .val_offs = 6, + .flags = SND_EVO_FLAGS_CAPTURE, + }, + { + .basename = "Loopback Left", + .type = SND_EVO_TYPE_MIXER, + .channels = 2, + .hwchannels = 2, + .val_offs = 8, + .flags = SND_EVO_FLAGS_CAPTURE, + }, + { + .basename = "Loopback Right", + .type = SND_EVO_TYPE_MIXER, + .channels = 2, + .hwchannels = 2, + .val_offs = 10, + .flags = SND_EVO_FLAGS_CAPTURE, + }, + { + .basename = "Mic 1 Phantom", + .type = SND_EVO_TYPE_PHANTOM, + .channels = 1, + .hwchannels = 1, + .val_offs = 0, + .flags = SND_EVO_FLAGS_CAPTURE, + }, + { + .basename = "Mic 2 Phantom", + .type = SND_EVO_TYPE_PHANTOM, + .channels = 1, + .hwchannels = 1, + .val_offs = 1, + .flags = SND_EVO_FLAGS_CAPTURE, + }, + { 0 }, /* sentinel */ +}; + +static const struct evo_devinfo { + u32 usb_id; + const struct snd_evo_ctrl *controls; +} evo_devinfo[] = { + { + .usb_id = USB_ID(USB_AUDIENT_VID, USB_EVO4_PID), + .controls = evo4_controls, + }, + { + .usb_id = USB_ID(USB_AUDIENT_VID, USB_EVO4_PID), + .controls = NULL, + }, + { 0 } /* sentinel */ +}; + + +static inline unsigned long snd_evo_kctl_priv(enum snd_evo_type type, + u8 valoffs, u8 hwchannels) +{ + unsigned long type_l = type & 0xFF; + unsigned long valoffs_l = valoffs & 0xFF; + unsigned long hwchannels_l = hwchannels & 0xFF; + + return (hwchannels_l << 16) | (valoffs_l << 8) | type_l; +} + +static __always_inline +const struct snd_evo_ctrl_type *snd_evo_kctl_type(struct snd_kcontrol *kctl) +{ + return &snd_evo_ctypes[kctl->private_value & 0xFF]; +} + +static __always_inline u16 snd_evo_kctl_valoffs(struct snd_kcontrol *kctl) +{ + return (kctl->private_value >> 8) & 0xFF; +} + +static __always_inline u16 snd_evo_kctl_hwchannels(struct snd_kcontrol *kctl) +{ + return (kctl->private_value >> 16) & 0xFF; +} + +static inline u16 snd_evo_kctl_channels(struct snd_kcontrol *kctl) +{ + struct usb_mixer_elem_info *info = kctl->private_data; + + return info->channels; +} + + +#define EVO_REQ_CUR (0x01) +#define EVO_REQTYPE_SET (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) +#define EVO_REQTYPE_GET (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) + +static inline int snd_evo_get_cur(struct usb_mixer_interface *mixer, + u16 value, u16 index, + void *buf, size_t len) +{ + struct usb_device *const dev = mixer->chip->dev; + + return snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), + EVO_REQ_CUR, EVO_REQTYPE_GET, + value, index, buf, len); +} + +static inline int snd_evo_set_cur(struct usb_mixer_interface *mixer, + u16 value, u16 index, + void *buf, size_t len) +{ + struct usb_device *const dev = mixer->chip->dev; + + return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + EVO_REQ_CUR, EVO_REQTYPE_SET, + value, index, buf, len); +} + + +static int snd_ctl_evo_boolean_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ctl_val) +{ + struct usb_mixer_elem_list *const list = snd_kcontrol_chip(kctl); + struct usb_mixer_interface *const mixer = list->mixer; + + const unsigned int nchan = snd_evo_kctl_channels(kctl); + const unsigned int hwchan = snd_evo_kctl_hwchannels(kctl); + const struct snd_evo_ctrl_type *const ctype = snd_evo_kctl_type(kctl); + const u16 value = ctype->wValue + snd_evo_kctl_valoffs(kctl); + const u16 index = ctype->wIndex; + + int i; + + for (i = 0; i < hwchan; i++) { + u32 buf; + int ret; + + ret = snd_evo_get_cur(mixer, value + i, index, + &buf, sizeof(buf)); + if (ret < 0) + return ret; + + ctl_val->value.integer.value[i] = le32_to_cpu(buf) ? 1 : 0; + + if (ctype->invert) + ctl_val->value.integer.value[i] ^= 0x1; + } + + for (; i < nchan; i++) + ctl_val->value.integer.value[i] = ctype->invert + ? ctype->max.integer + : ctype->min.integer; + + return 0; +} + +static int snd_ctl_evo_boolean_set(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ctl_val) +{ + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); + struct usb_mixer_interface *mixer = list->mixer; + + const unsigned int hwchan = snd_evo_kctl_hwchannels(kctl); + const struct snd_evo_ctrl_type *const ctype = snd_evo_kctl_type(kctl); + const u16 value = ctype->wValue + snd_evo_kctl_valoffs(kctl); + const u16 index = ctype->wIndex; + + int changed = 0; + int i; + + for (i = 0; i < hwchan; i++) { + u32 rbuf; + u32 buf = cpu_to_le32(ctl_val->value.integer.value[i] ? 1 : 0); + int ret; + + if (ctype->invert) + buf ^= 0x1; + + ret = snd_evo_get_cur(mixer, value + i, index, + &rbuf, sizeof(rbuf)); + if (ret < 0) + return ret; + + if (rbuf != buf) { + changed = 1; + + ret = snd_evo_set_cur(mixer, value + i, index, + &buf, sizeof(buf)); + if (ret < 0) + return ret; + } + } + + return changed; +} + +static int snd_ctl_evo_integer_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ctl_val) +{ + struct usb_mixer_elem_list *const list = snd_kcontrol_chip(kctl); + struct usb_mixer_interface *const mixer = list->mixer; + + const unsigned int nchan = snd_evo_kctl_channels(kctl); + const unsigned int hwchan = snd_evo_kctl_hwchannels(kctl); + const struct snd_evo_ctrl_type *const ctype = snd_evo_kctl_type(kctl); + const u16 value = ctype->wValue + snd_evo_kctl_valoffs(kctl); + const u16 index = ctype->wIndex; + + int i; + + for (i = 0; i < hwchan; i++) { + u16 buf; + s16 val; + int ret; + + ret = snd_evo_get_cur(mixer, value + i, index, + &buf, sizeof(buf)); + if (ret < 0) + return ret; + + val = le16_to_cpu(buf); + ctl_val->value.integer.value[i] = val; + } + + for (; i < nchan; i++) + ctl_val->value.integer.value[i] = ctype->min.integer; + + return 0; +} + +static int snd_ctl_evo_integer_set(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ctl_val) +{ + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); + struct usb_mixer_interface *mixer = list->mixer; + + const unsigned int hwchan = snd_evo_kctl_hwchannels(kctl); + const struct snd_evo_ctrl_type *const ctype = snd_evo_kctl_type(kctl); + const u16 value = ctype->wValue + snd_evo_kctl_valoffs(kctl); + const u16 index = ctype->wIndex; + + int changed = 0; + int i; + + for (i = 0; i < hwchan; i++) { + s16 rbuf; + s16 buf = cpu_to_le16(ctl_val->value.integer.value[i]); + int ret; + + ret = snd_evo_get_cur(mixer, value + i, index, + &rbuf, sizeof(rbuf)); + if (ret < 0) + return ret; + + if (rbuf != buf) { + changed = 1; + + ret = snd_evo_set_cur(mixer, value + i, index, + &buf, sizeof(buf)); + if (ret < 0) + return ret; + } + } + + return changed; +} + +static int snd_ctl_evo_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + const struct snd_evo_ctrl_type *const ctype = snd_evo_kctl_type(kctl); + + uinfo->type = ctype->type; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_READWRITE + | SNDRV_CTL_ELEM_ACCESS_VOLATILE; + uinfo->count = snd_evo_kctl_channels(kctl); + uinfo->value.integer.min = ctype->min.integer; + uinfo->value.integer.max = ctype->max.integer; + return 0; +} + + +static int snd_evo_add_ctrl(struct usb_mixer_interface *mixer, + const struct snd_evo_ctrl *ctrl) +{ + const struct snd_evo_ctrl_type *ctype = &snd_evo_ctypes[ctrl->type]; + char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + struct snd_kcontrol_new knew = { 0 }; + struct snd_kcontrol *kctl; + struct usb_mixer_elem_info *elem; + + knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + knew.name = name; + knew.info = snd_ctl_evo_info; + knew.private_value = snd_evo_kctl_priv(ctrl->type, ctrl->val_offs, + ctrl->hwchannels); + + switch (ctype->type) { + case SNDRV_CTL_ELEM_TYPE_INTEGER: + knew.get = snd_ctl_evo_integer_get; + knew.put = snd_ctl_evo_integer_set; + break; + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + knew.get = snd_ctl_evo_boolean_get; + knew.put = snd_ctl_evo_boolean_set; + break; + default: + return -EINVAL; + } + + snprintf(name, sizeof(name), "%s %s %s", ctrl->basename, + ((ctrl->flags & SND_EVO_FLAGS_DIRECTION) + == SND_EVO_FLAGS_CAPTURE) ? "Capture" : "Playback", + (ctype->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN) + ? "Switch" : "Volume"); + + elem = kzalloc_obj(*elem); + if (!elem) + return -ENOMEM; + + elem->head.mixer = mixer; + elem->channels = ctrl->channels; + + kctl = snd_ctl_new1(&knew, elem); + if (!kctl) { + kfree(elem); + return -ENOMEM; + } + + kctl->private_free = snd_usb_mixer_elem_free; + + return snd_usb_mixer_add_control(&elem->head, kctl); +} + + +/* called from mixer_quirks.c */ +int snd_evo_controls_create(struct usb_mixer_interface *mixer) +{ + const struct evo_devinfo *info; + const struct snd_evo_ctrl *ctrl; + + for (info = evo_devinfo; info->controls; info++) + if (info->usb_id == mixer->chip->usb_id) + break; + + if (!info->controls) + return -ENODEV; + + for (ctrl = info->controls; ctrl->basename; ctrl++) { + const int ret = snd_evo_add_ctrl(mixer, ctrl); + + if (ret < 0) + return ret; + } + + return 0; +} diff --git a/sound/usb/mixer_evo.h b/sound/usb/mixer_evo.h new file mode 100644 index 000000000000..7fe7e197185c --- /dev/null +++ b/sound/usb/mixer_evo.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __USB_MIXER_EVO_H +#define __USB_MIXER_EVO_H + +#include "mixer.h" + +#define USB_AUDIENT_VID (0x2708) +#define USB_EVO4_PID (0x0006) + +int snd_evo_controls_create(struct usb_mixer_interface *mixer); + +#endif /* __USB_MIXER_EVO_H */ diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index fc622eb95dc5..1e266fdbbb8e 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -38,6 +38,7 @@ #include "mixer_scarlett2.h" #include "mixer_us16x08.h" #include "mixer_s1810c.h" +#include "mixer_evo.h" #include "helper.h" #include "fcp.h" @@ -4539,6 +4540,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) err = snd_fcp_init(mixer); break; + case USB_ID(USB_AUDIENT_VID, USB_EVO4_PID): /* Audient EVO 4 */ + err = snd_evo_controls_create(mixer); + break; + case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */ err = snd_soundblaster_e1_switch_create(mixer); break; -- 2.55.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/3] Add Kconfig option for Audient EVO4 mixer quirks 2026-09-19 15:18 [PATCH 0/3] Add Audient EVO4 support Christian Ruppert 2026-09-19 15:18 ` [PATCH 1/3] Fix Audient EVO4 master playback control name Christian Ruppert 2026-09-19 15:18 ` [PATCH 2/3] Add Audient EVO4 mixer quirks Christian Ruppert @ 2026-09-19 15:18 ` Christian Ruppert 2026-09-25 10:18 ` [PATCH 0/3] Add Audient EVO4 support Faaris Ansari 3 siblings, 0 replies; 7+ messages in thread From: Christian Ruppert @ 2026-09-19 15:18 UTC (permalink / raw) To: Jaroslav Kysela, Takashi Iwai, linux-kernel, linux-sound Cc: Christian Ruppert, Will Porter, Peter Drabik, Neil Andrews Add Kconfig option for the Audient EVO4 support. This is split out from the evo4 driver so it can be optionally applied. Other mixer quirks don't seem to have Kconfig options so I leave it to the upstream to decide what to do with this. Signed-off-by: Christian Ruppert <arc@gmx.li> --- sound/usb/Kconfig | 10 ++++++++++ sound/usb/Makefile | 3 ++- sound/usb/mixer_quirks.c | 4 ++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index b4588915efa1..21039dd4ae3a 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -175,6 +175,16 @@ config SND_USB_HIFACE To compile this driver as a module, choose M here: the module will be called snd-usb-hiface. +config SND_USB_EVO + bool "Audient EVO advanced mixer features" + help + Support advanced mixer features for the Audient EVO4 USB audio + interface such as + * the recording mixer + * the monitor crossfader + * phantom power control + * missing channel mute buttons + config SND_BCD2000 tristate "Behringer BCD2000 MIDI driver" select SND_RAWMIDI diff --git a/sound/usb/Makefile b/sound/usb/Makefile index 2e842dcc73de..f3664adeab85 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -11,7 +11,6 @@ snd-usb-audio-y := card.o \ helper.o \ implicit.o \ mixer.o \ - mixer_evo.o \ mixer_quirks.o \ mixer_scarlett.o \ mixer_scarlett2.o \ @@ -27,6 +26,8 @@ snd-usb-audio-y := card.o \ snd-usb-audio-$(CONFIG_SND_USB_AUDIO_MIDI_V2) += midi2.o snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o +snd-usb-audio-$(CONFIG_SND_USB_EVO) += mixer_evo.o + snd-usbmidi-lib-y := midi.o # Toplevel Module Dependency diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 1e266fdbbb8e..c32ccff40122 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -38,7 +38,9 @@ #include "mixer_scarlett2.h" #include "mixer_us16x08.h" #include "mixer_s1810c.h" +#ifdef CONFIG_SND_USB_EVO #include "mixer_evo.h" +#endif #include "helper.h" #include "fcp.h" @@ -4540,9 +4542,11 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) err = snd_fcp_init(mixer); break; +#ifdef CONFIG_SND_USB_EVO case USB_ID(USB_AUDIENT_VID, USB_EVO4_PID): /* Audient EVO 4 */ err = snd_evo_controls_create(mixer); break; +#endif case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */ err = snd_soundblaster_e1_switch_create(mixer); -- 2.55.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/3] Add Audient EVO4 support 2026-09-19 15:18 [PATCH 0/3] Add Audient EVO4 support Christian Ruppert ` (2 preceding siblings ...) 2026-09-19 15:18 ` [PATCH 3/3] Add Kconfig option for " Christian Ruppert @ 2026-09-25 10:18 ` Faaris Ansari 2026-09-27 17:12 ` Christian Ruppert 3 siblings, 1 reply; 7+ messages in thread From: Faaris Ansari @ 2026-09-25 10:18 UTC (permalink / raw) To: arc; +Cc: drabik.p, linux-kernel, linux-sound, mrwillporter, neil, perex, tiwai Thanks for your work on this - there is currently a regression on the latest kernel versions (7.2 onwards, as well as LTS kernels 6.12 and 6.18). Trying to set the volume in software like wpctl, or pwvucontrol causes the software volume to be pulled down with it - I think it's something to do with "sticky mixers", not completely sure. I worked through troubleshooting it here as I originally thought it was a wireplumber issue: https://gitlab.freedesktop.org/pipewire/wireplumber/-/work_items/1022 This patch should hopefully solve that, and avoid the usage of external kernel modules like https://github.com/vanzaho/audient-evo-py (which you've based your work from) I'm not exactly sure how the process with kernel stuff works, but considering a regression on current mainline as well as LTS branches for this device - is there some chance of fast tracking the merge of these patches? Thanks, Faaris ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/3] Add Audient EVO4 support 2026-09-25 10:18 ` [PATCH 0/3] Add Audient EVO4 support Faaris Ansari @ 2026-09-27 17:12 ` Christian Ruppert 2026-09-27 17:38 ` Faaris Ansari 0 siblings, 1 reply; 7+ messages in thread From: Christian Ruppert @ 2026-09-27 17:12 UTC (permalink / raw) To: Faaris Ansari Cc: drabik.p, linux-kernel, linux-sound, mrwillporter, neil, perex, tiwai On Fri, Sep 25, 2026 at 11:18:33AM +0100, Faaris Ansari wrote: > Thanks for your work on this - there is currently a regression on the latest > kernel versions (7.2 onwards, as well as LTS kernels 6.12 and 6.18). Trying > to set the volume in software like wpctl, or pwvucontrol causes the software > volume to be pulled down with it - I think it's something to do with "sticky > mixers", not completely sure. > > I worked through troubleshooting it here as I originally thought it was a > wireplumber issue: > https://gitlab.freedesktop.org/pipewire/wireplumber/-/work_items/1022 > > This patch should hopefully solve that, I'm afraid this is not going to be the case. The patch set doesn't change anything with the pre-existing controls except for renaming the 'EVO4 ' master volume mixer to 'Master'. As a matter of fact, I made a similar observation to yours when testing the patch set on the 'sound' kernel tree and the (very sporadic) issue did not disappear after applying the patches. Unluckily, I didn't have time to investigate and as it seemed independent from this patch set and was never observed on my (vanilla) 6.18.x day-to-day setup, even with very recent kernels, I forgot about it. I suspect this might be a regression in the sound-USB core modules or possibly the the alsa core. > and avoid the usage of external > kernel modules like https://github.com/vanzaho/audient-evo-py (which you've > based your work from) This one should be solved with the patch set. > I'm not exactly sure how the process with kernel stuff works, but > considering a regression on current mainline as well as LTS branches for > this device - is there some chance of fast tracking the merge of these > patches? The best way of supporting this (even if it only solves half of your concerns) is probably to test it and reply with a Tested-by: tag to the patches. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/3] Add Audient EVO4 support 2026-09-27 17:12 ` Christian Ruppert @ 2026-09-27 17:38 ` Faaris Ansari 0 siblings, 0 replies; 7+ messages in thread From: Faaris Ansari @ 2026-09-27 17:38 UTC (permalink / raw) To: Christian Ruppert Cc: drabik.p, linux-kernel, linux-sound, mrwillporter, neil, perex, tiwai > I'm afraid this is not going to be the case. The patch set doesn't change > anything with the pre-existing controls except for renaming the 'EVO4 ' > master volume mixer to 'Master'. As a matter of fact, I made a similar > observation to yours when testing the patch set on the 'sound' kernel tree > and the (very sporadic) issue did not disappear after applying the > patches. > Unluckily, I didn't have time to investigate and as it seemed independent > from this patch set and was never observed on my (vanilla) 6.18.x > day-to-day setup, even with very recent kernels, I forgot about it. I > suspect this might be a regression in the sound-USB core modules or > possibly the the alsa core. I was able to find a work around to this specific issue, adding this below line in modprobe.d made the hardware volume start working correctly again. options snd_usb_audio quirk_flags=2708:0006:ignore_ctl_error I've reported this regression separately here: https://lore.kernel.org/regressions/CANBVYRCL=8QdLxGg4S6qrahrFtwJxhv-aSGpW7-1S=+iOe4ZGA@mail.gmail.com/ I also was able to test your patches alongside this workaround. All of the system controls I was expecting were in fact available within `alsamixer`, including phantom power, mic gain, etc. Both mic inputs still seem to be reported as stereo even though they're mono - I think the other channel is for loopback or something? I'm not entirely sure if this is something the patches are supposed to solve. > The patch set doesn't change > anything with the pre-existing controls except for renaming the 'EVO4 ' On the note of the UCM config, I had to patch it due to the above or else PipeWire wasn't able to directly manage the hardware volume knob. Adding the PlaybackSwitch part also allowed the hardware mute to be used by PipeWire. 46c46,47 < PlaybackVolume "EVO4 " --- > PlaybackVolume "Master Playback Volume" > PlaybackSwitch "Master Playback Switch" One problem I had with this patchset is the settings I have don't seem to save with UCM / PipeWire. When powering off the interface and powering it back on again all settings are reset except for the Master Playback Volume. After a small discussion on the PipeWire matrix server I was told that these settings should live in the UCM config too which I'm assuming they do not currently. Muting the microphone in pwvucontrol also didn't seem to use the hardware mic mute. Probably need to add `CaptureSwitch` for the microphone in UCM too. However, the current state is by far better than how the interface is being handled by default - thanks so much for your work on this! Faaris On Sun, 27 Sept 2026 at 18:12, Christian Ruppert <arc@gmx.li> wrote: > > On Fri, Sep 25, 2026 at 11:18:33AM +0100, Faaris Ansari wrote: > > Thanks for your work on this - there is currently a regression on the latest > > kernel versions (7.2 onwards, as well as LTS kernels 6.12 and 6.18). Trying > > to set the volume in software like wpctl, or pwvucontrol causes the software > > volume to be pulled down with it - I think it's something to do with "sticky > > mixers", not completely sure. > > > > I worked through troubleshooting it here as I originally thought it was a > > wireplumber issue: > > https://gitlab.freedesktop.org/pipewire/wireplumber/-/work_items/1022 > > > > This patch should hopefully solve that, > > I'm afraid this is not going to be the case. The patch set doesn't change > anything with the pre-existing controls except for renaming the 'EVO4 ' > master volume mixer to 'Master'. As a matter of fact, I made a similar > observation to yours when testing the patch set on the 'sound' kernel tree > and the (very sporadic) issue did not disappear after applying the > patches. > > Unluckily, I didn't have time to investigate and as it seemed independent > from this patch set and was never observed on my (vanilla) 6.18.x > day-to-day setup, even with very recent kernels, I forgot about it. I > suspect this might be a regression in the sound-USB core modules or > possibly the the alsa core. > > > and avoid the usage of external > > kernel modules like https://github.com/vanzaho/audient-evo-py (which you've > > based your work from) > > This one should be solved with the patch set. > > > I'm not exactly sure how the process with kernel stuff works, but > > considering a regression on current mainline as well as LTS branches for > > this device - is there some chance of fast tracking the merge of these > > patches? > > The best way of supporting this (even if it only solves half of your > concerns) is probably to test it and reply with a Tested-by: tag to the > patches. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-27 17:39 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-09-19 15:18 [PATCH 0/3] Add Audient EVO4 support Christian Ruppert 2026-09-19 15:18 ` [PATCH 1/3] Fix Audient EVO4 master playback control name Christian Ruppert 2026-09-19 15:18 ` [PATCH 2/3] Add Audient EVO4 mixer quirks Christian Ruppert 2026-09-19 15:18 ` [PATCH 3/3] Add Kconfig option for " Christian Ruppert 2026-09-25 10:18 ` [PATCH 0/3] Add Audient EVO4 support Faaris Ansari 2026-09-27 17:12 ` Christian Ruppert 2026-09-27 17:38 ` Faaris Ansari
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®