TL;DR: The kernel incorrectly maps PCI SSID
17aa:3847to a Legion laptop fixup instead of the correct Yoga fixup. This causes volume control to be completely non-functional. The fix requires rebuilding a single kernel module with a one-line patch.
- Model: Lenovo Yoga Pro 7 14IMH9
- DMI product name:
83E2 - CPU: Intel Core Ultra 7 155H (Meteor Lake)
- Audio codec: Realtek ALC287
- PCI SSID:
17aa:3847 - Tested on: Linux Mint 22 / Ubuntu 24.04 Noble, kernel 6.14.0-29-generic (HWE)
May also affect other distributions using the same kernel series.
Volume controll does not work - audio is either completely silent (0%) or at maximum volume regardless of the slider position from 1% to 100%. Above 100% (PipeWire software boost) the volume changes slightly, but this is not real hardware volume control
In the Linux kernel quirk table (sound/pci/hda/patch_realtek.c), SSID 17aa:3847 is incorrectly assigned to the Legion 7 16ACHG6:
SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6),The same SSID is used by the Yoga Pro 7 14IMH9, which requires a different fixup:
ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PINTechnically, pin 0x17 (bass speakers) gets connected to DAC 0x06*, which has no volume control. The correct Yoga fixup redirects the connection to DAC 0x02, which has a full volume control path.
The Legion fixup instead tries to initialize an external I2C amplifier CLSA0100, which is not present on the Yoga Pro 7.
| Approach | Result |
|---|---|
options snd_hda_codec_realtek model=... |
Ignored by the SOF stack |
options snd_sof_intel_hda_common hda_model=... |
Does not override SSID-based fixup |
options snd_hda_codec_realtek patch=... |
Ignored by SOF |
options snd_hda_codec_realtek quirk_id=... |
Parameter not supported by the module |
hdajackretask |
Blocked by SOF (/sys/class/sound/hwC0D0/reconfig: Device or resource busy) |
| I2C script (as used for Yoga Pro 9i 16IMH9) | Not applicable - the 14IMH9 has no external I2C amplifier |
Only the snd_hda_codec_realtek module is rebuilt - the kernel itself is not touched.
sudo apt install build-essential libelf-dev linux-headers-$(uname -r) zstdmkdir ~/audio-fix && cd ~/audio-fix
# Download the main source file
curl -o patch_realtek.c "https://raw.githubusercontent.com/torvalds/linux/v6.14/sound/pci/hda/patch_realtek.c"
# Download all required headers and helper files
curl -s "https://api.github.com/repos/torvalds/linux/contents/sound/pci/hda?ref=v6.14" | \
grep '"name"' | grep -E '\.(c|h)"' | sed 's/.*"name": "//;s/".*//' | \
while read f; do
curl -s -o "$f" "https://raw.githubusercontent.com/torvalds/linux/v6.14/sound/pci/hda/$f"
echo "Downloaded: $f"
donesed -i 's/SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6)/SND_PCI_QUIRK(0x17aa, 0x3847, "Yoga Pro 7 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN)/' patch_realtek.c
# Verify
grep "0x3847" patch_realtek.c
# Expected: SND_PCI_QUIRK(0x17aa, 0x3847, "Yoga Pro 7 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN),cat > Makefile << 'EOF'
obj-m := snd_hda_codec_realtek.o
snd_hda_codec_realtek-objs := patch_realtek.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
EOFmake# Backup the original module
sudo cp /lib/modules/$(uname -r)/kernel/sound/pci/hda/snd-hda-codec-realtek.ko.zst \
/lib/modules/$(uname -r)/kernel/sound/pci/hda/snd-hda-codec-realtek.ko.zst.bak
# Compress and install the patched module
zstd snd_hda_codec_realtek.ko -o snd_hda_codec_realtek.ko.zst -f
sudo cp snd_hda_codec_realtek.ko.zst \
/lib/modules/$(uname -r)/kernel/sound/pci/hda/snd-hda-codec-realtek.ko.zst
sudo depmod -a
sudo rebootIf something goes wrong, restore the original module:
sudo cp /lib/modules/$(uname -r)/kernel/sound/pci/hda/snd-hda-codec-realtek.ko.zst.bak \
/lib/modules/$(uname -r)/kernel/sound/pci/hda/snd-hda-codec-realtek.ko.zst
sudo depmod -a
sudo rebootWhen the kernel is updated, the module will be replaced with the original. Rebuild the patched version:
cd ~/audio-fix
make clean && make
zstd snd_hda_codec_realtek.ko -o snd_hda_codec_realtek.ko.zst -f
sudo cp snd_hda_codec_realtek.ko.zst \
/lib/modules/$(uname -r)/kernel/sound/pci/hda/snd-hda-codec-realtek.ko.zst
sudo depmod -a
sudo rebootNote: If the kernel version changes (e.g. from 6.14 to 6.15), update the source URL - replace
v6.14with the correct version tag.
# Pin 0x17 should now use DAC 0x02, not 0x06
cat /proc/asound/card0/codec#0 | grep -A15 "Node 0x17"
# Look for: Connection: ... 0x02* (asterisk on 0x02, not 0x06)This is a kernel bug - the SSID 17aa:3847 is shared between the Legion 7 16ACHG6 and the Yoga Pro 7 14IMH9, but only the Legion entry exists in patch_realtek.c. The proper fix would be to submit a patch to the upstream Linux kernel adding the correct quirk entry for the Yoga Pro 7 14IMH9
- Yoga Pro 9i Gen 9 Linux guide - similar hardware, different model
- kernel bugzilla #217449 - related SOF audio issues on Lenovo Yoga