* [PATCH 0/2] Subject: [PATCH 0/2] ALSA: usb-audio: Mixer quirks for ASRock X870E Taichi
@ 2026-11-08 18:58 Brian Harring via B4 Relay
2026-11-08 18:58 ` [PATCH 1/2] ALSA: usb-audio: Use ALC4080 mixer map " Brian Harring via B4 Relay
2026-11-08 18:58 ` [PATCH 2/2] ALSA: usb-audio: Add ES9219 speaker volume " Brian Harring via B4 Relay
0 siblings, 2 replies; 4+ messages in thread
From: Brian Harring via B4 Relay @ 2026-11-08 18:58 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai; +Cc: linux-sound, Brian Harring
The ASRock X870E Taichi / Taichi Lite onboard audio (26ce:0a0b, Realtek
ALC4082) has its headphone volume control misassigned to the rear
output, resulting in the rear output being full volume and only
mutable, and the headphones falling back to software control.
Patch 1 uses the existing ALC4080 map to correct the assignment. This is
a fix: the headphones get their actual hardware control, and the rear
output falls back to software.
Patch 2 adds a hardware volume control for the rear output through the
ESS ES9219 DAC behind it.
Validation was against alsa-ucm-conf 1.2.16 and a 7.3.3 kernel. The
resultant changes to the PipeWire sinks are below:
7.3.3:
SPDIF HARDWARE HW_MUTE_CTRL DECIBEL_VOLUME LATENCY
Speaker HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY
Headphones HARDWARE DECIBEL_VOLUME LATENCY
with remap:
SPDIF HARDWARE HW_MUTE_CTRL DECIBEL_VOLUME LATENCY
Speaker HARDWARE HW_MUTE_CTRL DECIBEL_VOLUME LATENCY
Headphones HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY
with remap + ES9219:
SPDIF HARDWARE HW_MUTE_CTRL DECIBEL_VOLUME LATENCY
Speaker HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY
Headphones HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY
Signed-off-by: Brian Harring <ferringb@gmail.com>
---
Brian Harring (2):
ALSA: usb-audio: Use ALC4080 mixer map for ASRock X870E Taichi
ALSA: usb-audio: Add ES9219 speaker volume for ASRock X870E Taichi
sound/usb/mixer_maps.c | 14 +++--
sound/usb/mixer_quirks.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 166 insertions(+), 5 deletions(-)
---
base-commit: 94dd534d2eb96ceea4e36f3d3f0651a1abaa9b99
change-id: 20261108-alc4082-taichi-af4789f5763e
Best regards,
--
Brian Harring <ferringb@gmail.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] ALSA: usb-audio: Use ALC4080 mixer map for ASRock X870E Taichi
2026-11-08 18:58 [PATCH 0/2] Subject: [PATCH 0/2] ALSA: usb-audio: Mixer quirks for ASRock X870E Taichi Brian Harring via B4 Relay
@ 2026-11-08 18:58 ` Brian Harring via B4 Relay
2026-11-08 18:58 ` [PATCH 2/2] ALSA: usb-audio: Add ES9219 speaker volume " Brian Harring via B4 Relay
1 sibling, 0 replies; 4+ messages in thread
From: Brian Harring via B4 Relay @ 2026-11-08 18:58 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai; +Cc: linux-sound, Brian Harring
From: Brian Harring <ferringb@gmail.com>
The ASRock X870E Taichi / Taichi Lite onboard audio (26ce:0a0b, Realtek
ALC4082) has the same problem as the MSI ALC4080 boards already using
this map: all its playback feature units are named "PCM", so the UCM
profile pairs the headphone volume with the rear output's mute. Its
unit IDs match, so use the same map, renamed to alc408x_map now that
it's no longer MSI-only.
Signed-off-by: Brian Harring <ferringb@gmail.com>
---
sound/usb/mixer_maps.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index 9218ca6314ad..15065ee3f363 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -486,8 +486,8 @@ static const struct usbmix_name_map aorus_master_alc1220vb_map[] = {
{}
};
-/* MSI MPG X570S Carbon Max Wifi with ALC4080 */
-static const struct usbmix_name_map msi_mpg_x570s_carbon_max_wifi_alc4080_map[] = {
+/* ALC4080/ALC4082 boards with this playback feature unit layout */
+static const struct usbmix_name_map alc408x_map[] = {
{ 29, "Speaker Playback" },
{ 30, "Front Headphone Playback" },
{ 32, "IEC958 Playback" },
@@ -770,15 +770,19 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
},
{ /* MSI MPG X570S Carbon Max Wifi */
.id = USB_ID(0x0db0, 0x419c),
- .map = msi_mpg_x570s_carbon_max_wifi_alc4080_map,
+ .map = alc408x_map,
},
{ /* MSI MAG X570S Torpedo Max */
.id = USB_ID(0x0db0, 0xa073),
- .map = msi_mpg_x570s_carbon_max_wifi_alc4080_map,
+ .map = alc408x_map,
},
{ /* MSI MAG B850M MORTAR WIFI */
.id = USB_ID(0x0db0, 0xcc78),
- .map = msi_mpg_x570s_carbon_max_wifi_alc4080_map,
+ .map = alc408x_map,
+ },
+ { /* ASRock X870E Taichi / Taichi Lite (ALC4082) */
+ .id = USB_ID(0x26ce, 0x0a0b),
+ .map = alc408x_map,
},
{ /* MSI TRX40 */
.id = USB_ID(0x0db0, 0x543d),
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] ALSA: usb-audio: Add ES9219 speaker volume for ASRock X870E Taichi
2026-11-08 18:58 [PATCH 0/2] Subject: [PATCH 0/2] ALSA: usb-audio: Mixer quirks for ASRock X870E Taichi Brian Harring via B4 Relay
2026-11-08 18:58 ` [PATCH 1/2] ALSA: usb-audio: Use ALC4080 mixer map " Brian Harring via B4 Relay
@ 2026-11-08 18:58 ` Brian Harring via B4 Relay
2026-11-08 19:12 ` sashiko-bot
1 sibling, 1 reply; 4+ messages in thread
From: Brian Harring via B4 Relay @ 2026-11-08 18:58 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai; +Cc: linux-sound, Brian Harring
From: Brian Harring <ferringb@gmail.com>
The rear output of the ASRock X870E Taichi / Taichi Lite onboard audio
(26ce:0a0b, Realtek ALC4082) has a feature unit with only a mute, but an
ESS ES9219 DAC sits behind it which can be used for volume control.
The DAC is reachable through the codec's I2C bridge, using the vendor
requests found in Realtek's Windows 10 driver (version 6.4.0.2449). That
driver doesn't enable this for any ASRock device; at a guess, ASRock
simply overlooked it.
Assisted-by: Claude Opus 5.5
Signed-off-by: Brian Harring <ferringb@gmail.com>
---
sound/usb/mixer_quirks.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 157 insertions(+)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 4c7d68311f20..075fb5847030 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -4656,6 +4656,159 @@ static int snd_xiisound_init_fu_pins(struct usb_mixer_interface *mixer)
return 0;
}
+/*
+ * ASRock X870E Taichi (ALC4082): the rear line exposes only mute (feature
+ * unit 19), but there is an ESS ES9219 DAC behind it that is usable for
+ * volume control.
+ */
+#define TAICHI_I2C_READ 0x3d
+#define TAICHI_I2C_WRITE 0x3e
+#define TAICHI_I2C_INDEX 0x0100
+#define TAICHI_ES9219_I2C_ADDR 0x48
+#define TAICHI_ES9219_REG_VOL1 0x0f
+#define TAICHI_ES9219_REG_VOL2 0x10
+#define TAICHI_ES9219_VOL_MAX 0xff
+
+static int taichi_es9219_read(struct snd_usb_audio *chip, u8 reg, u8 *val)
+{
+ struct usb_device *dev = chip->dev;
+ u8 buf[2] = { reg, 0 };
+ int err;
+
+ err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), TAICHI_I2C_READ,
+ USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_OUT,
+ TAICHI_ES9219_I2C_ADDR, TAICHI_I2C_INDEX,
+ buf, sizeof(buf));
+ if (err < 0)
+ return err;
+ err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), TAICHI_I2C_READ,
+ USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_IN,
+ TAICHI_ES9219_I2C_ADDR, TAICHI_I2C_INDEX,
+ buf, sizeof(buf));
+ if (err < 0)
+ return err;
+ if (err < 1)
+ return -EIO;
+ *val = buf[0];
+ return 0;
+}
+
+static int taichi_es9219_write(struct snd_usb_audio *chip, u8 reg, u8 val)
+{
+ struct usb_device *dev = chip->dev;
+ u8 buf[2] = { reg, val };
+ int err;
+
+ err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), TAICHI_I2C_WRITE,
+ USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_OUT,
+ TAICHI_ES9219_I2C_ADDR, TAICHI_I2C_INDEX,
+ buf, sizeof(buf));
+ return err < 0 ? err : 0;
+}
+
+static int taichi_es9219_vol_update(struct usb_mixer_interface *mixer,
+ unsigned long pv)
+{
+ struct snd_usb_audio *chip = mixer->chip;
+ int err;
+
+ CLASS(snd_usb_lock, pm)(chip);
+ if (pm.err < 0)
+ return pm.err;
+
+ err = taichi_es9219_write(chip, TAICHI_ES9219_REG_VOL1,
+ TAICHI_ES9219_VOL_MAX - (pv & 0xff));
+ if (err < 0)
+ return err;
+ return taichi_es9219_write(chip, TAICHI_ES9219_REG_VOL2,
+ TAICHI_ES9219_VOL_MAX - ((pv >> 8) & 0xff));
+}
+
+static int taichi_es9219_vol_info(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = TAICHI_ES9219_VOL_MAX;
+ return 0;
+}
+
+static int taichi_es9219_vol_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = kctl->private_value & 0xff;
+ ucontrol->value.integer.value[1] = (kctl->private_value >> 8) & 0xff;
+ return 0;
+}
+
+static int taichi_es9219_vol_put(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+ long l = ucontrol->value.integer.value[0];
+ long r = ucontrol->value.integer.value[1];
+ unsigned long pv;
+ int err;
+
+ if (l < 0 || l > TAICHI_ES9219_VOL_MAX ||
+ r < 0 || r > TAICHI_ES9219_VOL_MAX)
+ return -EINVAL;
+
+ pv = l | (r << 8);
+ if (pv == kctl->private_value)
+ return 0;
+
+ kctl->private_value = pv;
+ err = taichi_es9219_vol_update(list->mixer, pv);
+ return err < 0 ? err : 1;
+}
+
+static int taichi_es9219_vol_resume(struct usb_mixer_elem_list *list)
+{
+ return taichi_es9219_vol_update(list->mixer, list->kctl->private_value);
+}
+
+static const DECLARE_TLV_DB_SCALE(taichi_es9219_db_scale, -12750, 50, 0);
+
+static const struct snd_kcontrol_new taichi_es9219_vol = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Speaker Playback Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = taichi_es9219_vol_info,
+ .get = taichi_es9219_vol_get,
+ .put = taichi_es9219_vol_put,
+ .tlv = { .p = taichi_es9219_db_scale },
+};
+
+static int taichi_es9219_controls_create(struct usb_mixer_interface *mixer)
+{
+ struct snd_usb_audio *chip = mixer->chip;
+ struct usb_mixer_elem_list *list;
+ u8 v1, v2;
+ int err;
+
+ err = taichi_es9219_read(chip, TAICHI_ES9219_REG_VOL1, &v1);
+ if (err < 0) {
+ usb_audio_dbg(chip, "ES9219 VOL1 read failed: %d\n", err);
+ return 0;
+ }
+ err = taichi_es9219_read(chip, TAICHI_ES9219_REG_VOL2, &v2);
+ if (err < 0) {
+ usb_audio_dbg(chip, "ES9219 VOL2 read failed: %d\n", err);
+ return 0;
+ }
+
+ err = add_single_ctl_with_resume(mixer, 0, taichi_es9219_vol_resume,
+ &taichi_es9219_vol, &list);
+ if (err < 0)
+ return err;
+ list->kctl->private_value = (TAICHI_ES9219_VOL_MAX - v1) |
+ ((TAICHI_ES9219_VOL_MAX - v2) << 8);
+ return 0;
+}
+
int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
{
int err = 0;
@@ -4797,6 +4950,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
err = dell_dock_mixer_create(mixer);
break;
+ case USB_ID(0x26ce, 0x0a0b): /* ASRock X870E Taichi (Lite) */
+ err = taichi_es9219_controls_create(mixer);
+ break;
+
case USB_ID(0x2a39, 0x3fd2): /* RME ADI-2 Pro */
case USB_ID(0x2a39, 0x3fd3): /* RME ADI-2 DAC */
case USB_ID(0x2a39, 0x3fd4): /* RME */
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] ALSA: usb-audio: Add ES9219 speaker volume for ASRock X870E Taichi
2026-11-08 18:58 ` [PATCH 2/2] ALSA: usb-audio: Add ES9219 speaker volume " Brian Harring via B4 Relay
@ 2026-11-08 19:12 ` sashiko-bot
0 siblings, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-11-08 19:12 UTC (permalink / raw)
To: Brian Harring; +Cc: linux-sound
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] ALSA: usb-audio: premature private_value update in
taichi_es9219_vol_put()
- [Low] ALSA: usb-audio: wrong feature unit ID in taichi_es9219 comment
--
commit 67dc6589a98098f31e87c384d4ca4f8074ecf8d0
Author: Brian Harring <ferringb@gmail.com>
ALSA: usb-audio: Add ES9219 speaker volume for ASRock X870E Taichi
This commit adds a Speaker Playback Volume mixer control for the ASRock
X870E Taichi and Taichi Lite onboard audio by accessing the ESS ES9219
DAC over the ALC4082 codec's I2C bridge.
> diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
> index 4c7d68311f204..075fb5847030f 100644
> --- a/sound/usb/mixer_quirks.c
> +++ b/sound/usb/mixer_quirks.c
> @@ -4656,6 +4656,159 @@ static int snd_xiisound_init_fu_pins(struct usb_mixer_interface *mixer)
> return 0;
> }
>
> +/*
> + * ASRock X870E Taichi (ALC4082): the rear line exposes only mute (feature
> + * unit 19), but there is an ESS ES9219 DAC behind it that is usable for
> + * volume control.
> + */
[Severity: Low]
This isn't a bug, but should this comment say feature unit 29 rather than
19? In sound/usb/mixer_maps.c, alc408x_map maps unit 29 to "Speaker
Playback" for USB_ID(0x26ce, 0x0a0b).
[ ... ]
> +static int taichi_es9219_vol_put(struct snd_kcontrol *kctl,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
> + long l = ucontrol->value.integer.value[0];
> + long r = ucontrol->value.integer.value[1];
> + unsigned long pv;
> + int err;
> +
> + if (l < 0 || l > TAICHI_ES9219_VOL_MAX ||
> + r < 0 || r > TAICHI_ES9219_VOL_MAX)
> + return -EINVAL;
> +
> + pv = l | (r << 8);
> + if (pv == kctl->private_value)
> + return 0;
> +
> + kctl->private_value = pv;
> + err = taichi_es9219_vol_update(list->mixer, pv);
> + return err < 0 ? err : 1;
> +}
[Severity: Medium]
Should kctl->private_value be updated only after taichi_es9219_vol_update()
succeeds?
If taichi_es9219_vol_update() fails, kctl->private_value retains the
unwritten volume. taichi_es9219_vol_get() then reports the wrong value to
userspace, and retrying the same volume in taichi_es9219_vol_put() hits the
pv == kctl->private_value check and returns 0 without writing to the DAC.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261108-alc4082-taichi-v1-0-942558088157@gmail.com?part=2
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-08 19:12 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-08 18:58 [PATCH 0/2] Subject: [PATCH 0/2] ALSA: usb-audio: Mixer quirks for ASRock X870E Taichi Brian Harring via B4 Relay
2026-11-08 18:58 ` [PATCH 1/2] ALSA: usb-audio: Use ALC4080 mixer map " Brian Harring via B4 Relay
2026-11-08 18:58 ` [PATCH 2/2] ALSA: usb-audio: Add ES9219 speaker volume " Brian Harring via B4 Relay
2026-11-08 19:12 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox