Headphone jack non-functional on Huawei MateBook D15 (sof-essx8336 / ES8336) — jack detection dead, amp-enable GPIO not driven by mixer controls
Summary
On this Huawei MateBook D15 (Comet Lake, sof-essx8336 driver), the 3.5mm headphone jack does not produce audio under any configuration. Investigation shows two distinct, compounding driver-level bugs:
- Jack detection is completely non-functional — the
SW_HEADPHONE_INSERT switch never fires regardless of quirk value tested, despite the ACPI DSDT declaring a valid GpioInt jack-detect line.
- The
Headphone Switch / Speaker Switch ALSA mixer controls are disconnected from the actual amp-enable GPIO lines — toggling these controls in software has no effect on the physical GPIO state that gates the headphone/speaker amplifiers.
Headphones are confirmed fully functional under Windows on the same hardware, and USB-C audio output works correctly under Linux, isolating the fault entirely to this driver's handling of the onboard ES8336 codec's 3.5mm analog path.
Hardware
- Model: Huawei MateBook D15 (10th Gen Intel, Comet Lake)
- Board:
HUAWEI-BOHB_WAX9-M1240-BOHB_WAX9_PCB_B2 (per alsa.long_card_name)
- Codec: ES8336 (
sof-essx8336)
- Kernel driver:
snd_soc_sof_es8336
- Platform GPIO controller:
INT34BB:00 (Intel Comet Lake PCH GPIO community), exposed as gpiochip0, 312 lines
- Distro: CachyOS (Arch-based)
Board has multiple hardware sub-variants
The DSDT's _SUB (Subsystem ID) method under the ESSX device returns one of four IDs depending on an EC register read, meaning this single BIOS/board name actually covers multiple hardware revisions:
Method (_SUB, 0, NotSerialized)
{
If ((^^^LPCB.EC0.MRBD == 0x38))
{
If (((RDCM (0xB6) & 0xF0) == 0x10))
{
Return ("152D125E")
}
Else
{
Return ("152D125F")
}
}
ElseIf (((RDCM (0xB6) & 0xF0) == 0x10))
{
Return ("152D1261")
}
Else
{
Return ("152D1262")
}
}
Any quirk table entry keyed only on a generic board/DMI string may not account for this variance.
ACPI GPIO resource declaration (DSDT, Device (ESSX))
Device (ESSX)
{
Name (_HID, "ESSX8336")
Name (SBUF, ResourceTemplate ()
{
I2cSerialBusV2 (0x0010, ...)
I2cSerialBusV2 (0x0011, ...)
GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly,
"\\_SB.PCI0.GPI0", ...) { Pin: 0x0000 } // resolved via PIN1
GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly,
"\\_SB.PCI0.GPI0", ...) { Pin: 0x0000 } // resolved via PIN2
GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullDefault, 0x0000,
"\\_SB.PCI0.GPI0", ...) { Pin: 0x0000 } // resolved via INT1
})
CreateWordField (SBUF, 0x59, PIN1)
CreateWordField (SBUF, 0x81, PIN2)
CreateWordField (SBUF, 0xA9, INT1)
Method (_INI, 0, NotSerialized)
{
PIN1 = GNUM (0x04010010)
PIN2 = GNUM (0x0401000F)
INT1 = GNUM (0x04020016)
}
}
Decoding via the board's own GNUM/GGRP helper methods (group = (Arg0 & 0x00FF0000) >> 16, pin = Arg0 & 0xFF):
| Signal |
Raw value |
Group |
Pin |
Declared type |
| PIN1 (GPIO output) |
0x04010010 |
1 |
16 |
Output |
| PIN2 (GPIO output) |
0x0401000F |
1 |
15 |
Output |
| INT1 (jack-detect IRQ) |
0x04020016 |
2 |
22 |
GpioInt, Edge, ActiveHigh |
Runtime GPIO state (/sys/kernel/debug/gpio)
The kernel has already correctly bound and named two of these lines:
gpiochip0: 312 GPIOs, parent: platform/INT34BB:00, INT34BB:00:
gpio-35 ( |TPDE GpioInt(0) ) in hi IRQ ACTIVE LOW
gpio-47 ( |headphone-enable ) out hi ACTIVE LOW
gpio-48 ( |speakers-enable ) out lo ACTIVE LOW
gpio-278 ( |ESSX GpioInt(0) ) in hi IRQ
Both headphone-enable and speakers-enable are ACTIVE LOW (asserted/enabled = logic lo).
Observed state on the HiFi (..., Headphones, Headset, Mic) PipeWire/ALSA profile:
headphone-enable: hi → disabled
speakers-enable: lo → enabled
i.e. even while the "Headphones" ALSA/PipeWire profile is active and the corresponding sink is selected, the physical amp-enable GPIO for the headphone path is never asserted. The speaker amp remains enabled regardless of profile selection.
Mixer controls do not affect the GPIO state
Two raw mixer controls exist that appear intended to drive these lines:
numid=30,iface=MIXER,name='Headphone Switch'
numid=29,iface=MIXER,name='Speaker Switch'
Observed prior to any change:
numid=30 'Headphone Switch': values=on
numid=29 'Speaker Switch': values=off
Despite Headphone Switch already reading on and Speaker Switch already reading off, the GPIO debug output still shows headphone-enable = hi (disabled) and speakers-enable = lo (enabled) — the opposite of what the mixer control names claim. Explicitly re-setting both controls to their already-reported values via amixer -c 0 cset numid=30 on / cset numid=29 off produced no change in the GPIO state.
This indicates the Headphone Switch / Speaker Switch ALSA controls are not correctly wired to the headphone-enable (gpio-47) / speakers-enable (gpio-48) lines in the current driver, or are shadowed by another control/quirk path that overrides them.
Jack detection is dead regardless of quirk value
Confirmed via evtest against /dev/input/eventN (sof-essx8336 Headset device), monitoring SW_HEADPHONE_INSERT directly:
- Default DMI-detected quirk (
0x1a0 — SSP0 + DMIC + headphone GPIO + headset mic1): jack always reads on, never toggles on physical plug/unplug.
0x1a0 | SOF_ES8336_JD_INVERTED (0x40) = 0x1e0: jack always reads off, never toggles.
0x1a0 | SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK (0x10) = 0x1b0: no change, never toggles.
0x1a0 | 0x40 | 0x10 = 0x1f0 (both bits combined): switch initializes at state 0 but still never toggles on physical insert/removal.
sudo dmesg | grep -i quirk confirms each value is actually loaded by the module (cat /sys/module/snd_soc_sof_es8336/parameters/quirk matches the decimal equivalent of each hex value tested).
Confirmation the hardware itself is functional
- Windows on the same physical machine: headphone jack works correctly, including automatic switching between speaker and headphone output.
- USB-C headphones on this Linux install: work correctly (bypasses the ES8336 codec entirely, confirming the fault is isolated to this codec's driver path, not a general audio subsystem issue).
Reproduction steps
- Boot CachyOS on the affected D15 board.
- Confirm active quirk:
cat /sys/module/snd_soc_sof_es8336/parameters/quirk
- Monitor jack-detect:
sudo evtest /dev/input/eventN (device named sof-essx8336 Headset), then physically plug/unplug 3.5mm headphones. No SW_HEADPHONE_INSERT event fires at any tested quirk value.
- Manually switch to the Headphones profile:
pactl set-card-profile alsa_card.pci-0000_00_1f.3-platform-sof-essx8336 "HiFi (HDMI1, HDMI2, HDMI3, Headphones, Headset, Mic)"
- Check GPIO state:
sudo cat /sys/kernel/debug/gpio | grep -i -A2 -B2 "headphone\|speaker" — headphone-enable remains hi (disabled).
- No audio is audible through the 3.5mm jack under any tested mixer/quirk/profile combination.
Requested from maintainers
- Confirmation of the correct quirk value (or driver fix) for this board's
_SUB variant(s) (152D125E / 152D125F / 152D1261 / 152D1262).
- Investigation into why
Headphone Switch (numid 30) / Speaker Switch (numid 29) do not affect the headphone-enable (gpio-47) / speakers-enable (gpio-48) GPIO lines despite apparently being intended to.
- Investigation into why the jack-detect interrupt (ACPI
GpioInt, Group 2 Pin 22 — likely corresponding to gpio-278 "ESSX GpioInt(0)" in the runtime GPIO dump) never fires a SW_HEADPHONE_INSERT event under any tested quirk combination.
Environment
- Kernel/module:
snd_soc_sof_es8336
- Audio server: PipeWire 1.6.8 + WirePlumber
- Distro: CachyOS
Headphone jack non-functional on Huawei MateBook D15 (sof-essx8336 / ES8336) — jack detection dead, amp-enable GPIO not driven by mixer controls
Summary
On this Huawei MateBook D15 (Comet Lake,
sof-essx8336driver), the 3.5mm headphone jack does not produce audio under any configuration. Investigation shows two distinct, compounding driver-level bugs:SW_HEADPHONE_INSERTswitch never fires regardless of quirk value tested, despite the ACPI DSDT declaring a validGpioIntjack-detect line.Headphone Switch/Speaker SwitchALSA mixer controls are disconnected from the actual amp-enable GPIO lines — toggling these controls in software has no effect on the physical GPIO state that gates the headphone/speaker amplifiers.Headphones are confirmed fully functional under Windows on the same hardware, and USB-C audio output works correctly under Linux, isolating the fault entirely to this driver's handling of the onboard ES8336 codec's 3.5mm analog path.
Hardware
HUAWEI-BOHB_WAX9-M1240-BOHB_WAX9_PCB_B2(peralsa.long_card_name)sof-essx8336)snd_soc_sof_es8336INT34BB:00(Intel Comet Lake PCH GPIO community), exposed asgpiochip0, 312 linesBoard has multiple hardware sub-variants
The DSDT's
_SUB(Subsystem ID) method under theESSXdevice returns one of four IDs depending on an EC register read, meaning this single BIOS/board name actually covers multiple hardware revisions:Any quirk table entry keyed only on a generic board/DMI string may not account for this variance.
ACPI GPIO resource declaration (DSDT,
Device (ESSX))Decoding via the board's own
GNUM/GGRPhelper methods (group = (Arg0 & 0x00FF0000) >> 16,pin = Arg0 & 0xFF):Runtime GPIO state (
/sys/kernel/debug/gpio)The kernel has already correctly bound and named two of these lines:
Both
headphone-enableandspeakers-enableareACTIVE LOW(asserted/enabled = logiclo).Observed state on the
HiFi (..., Headphones, Headset, Mic)PipeWire/ALSA profile:headphone-enable:hi→ disabledspeakers-enable:lo→ enabledi.e. even while the "Headphones" ALSA/PipeWire profile is active and the corresponding sink is selected, the physical amp-enable GPIO for the headphone path is never asserted. The speaker amp remains enabled regardless of profile selection.
Mixer controls do not affect the GPIO state
Two raw mixer controls exist that appear intended to drive these lines:
Observed prior to any change:
Despite
Headphone Switchalready readingonandSpeaker Switchalready readingoff, the GPIO debug output still showsheadphone-enable = hi(disabled) andspeakers-enable = lo(enabled) — the opposite of what the mixer control names claim. Explicitly re-setting both controls to their already-reported values viaamixer -c 0 cset numid=30 on/cset numid=29 offproduced no change in the GPIO state.This indicates the
Headphone Switch/Speaker SwitchALSA controls are not correctly wired to theheadphone-enable(gpio-47) /speakers-enable(gpio-48) lines in the current driver, or are shadowed by another control/quirk path that overrides them.Jack detection is dead regardless of quirk value
Confirmed via
evtestagainst/dev/input/eventN(sof-essx8336 Headsetdevice), monitoringSW_HEADPHONE_INSERTdirectly:0x1a0— SSP0 + DMIC + headphone GPIO + headset mic1): jack always readson, never toggles on physical plug/unplug.0x1a0 | SOF_ES8336_JD_INVERTED (0x40) = 0x1e0: jack always readsoff, never toggles.0x1a0 | SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK (0x10) = 0x1b0: no change, never toggles.0x1a0 | 0x40 | 0x10 = 0x1f0(both bits combined): switch initializes atstate 0but still never toggles on physical insert/removal.sudo dmesg | grep -i quirkconfirms each value is actually loaded by the module (cat /sys/module/snd_soc_sof_es8336/parameters/quirkmatches the decimal equivalent of each hex value tested).Confirmation the hardware itself is functional
Reproduction steps
cat /sys/module/snd_soc_sof_es8336/parameters/quirksudo evtest /dev/input/eventN(device namedsof-essx8336 Headset), then physically plug/unplug 3.5mm headphones. NoSW_HEADPHONE_INSERTevent fires at any tested quirk value.pactl set-card-profile alsa_card.pci-0000_00_1f.3-platform-sof-essx8336 "HiFi (HDMI1, HDMI2, HDMI3, Headphones, Headset, Mic)"sudo cat /sys/kernel/debug/gpio | grep -i -A2 -B2 "headphone\|speaker"—headphone-enableremainshi(disabled).Requested from maintainers
_SUBvariant(s) (152D125E/152D125F/152D1261/152D1262).Headphone Switch(numid 30) /Speaker Switch(numid 29) do not affect theheadphone-enable(gpio-47) /speakers-enable(gpio-48) GPIO lines despite apparently being intended to.GpioInt, Group 2 Pin 22 — likely corresponding togpio-278 "ESSX GpioInt(0)"in the runtime GPIO dump) never fires aSW_HEADPHONE_INSERTevent under any tested quirk combination.Environment
snd_soc_sof_es8336