* [PATCH] ALSA: hda/realtek: Fix silent speakers on Lenovo Legion S7 15IMH05
@ 2026-10-07 20:37 Matej Sochan
0 siblings, 0 replies; only message in thread
From: Matej Sochan @ 2026-10-07 20:37 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai, Eric Naim
Cc: linux-sound, linux-kernel, stable, Matej Sochan
The speakers on the Legion S7 15IMH05 (PCI SSID 17aa:3811, ALC287) stay
silent after a cold boot with the current quirk, which applies
ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS. They only start working after a
suspend/resume cycle.
The amplifier setup is sent through COEF 0x24/0x26 on NID 0x20. On this
machine the first pass of that sequence appears to only wake the
amplifiers. Sending the identical sequence a second time makes both
speakers work, provided the second write comes a few milliseconds after
the first: back-to-back writes leave the speakers silent, a 7 ms gap
makes only the right speaker work, and 8 ms or more is reliable. A dump
of all COEF registers of NID 0x20 taken before and after the second
write shows no difference.
Add a dedicated fixup that writes the sequence, waits 20 ms to keep a
margin over the measured minimum, and writes it again on every codec
init. It chains to the same AUTOMUTE fixup as before. To share the
sequence, move the verbs of ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS into a
named array; this has no functional change for the other users of that
fixup.
Fixes: 67f4c61a73e9 ("ALSA: hda/realtek: Add quirk for Legion S7 15IMH")
Cc: stable@vger.kernel.org
Link: https://github.com/CachyOS/linux-cachyos/issues/792
Signed-off-by: Matej Sochan <matej.sochan@gmail.com>
---
Tested on a Lenovo Legion S7 15IMH05 (82BC) with v7.2.8 (linux-hardened):
speakers work after repeated cold boots with the 20 ms delay.
The same change applies on top of the sound tree; I have only built and
booted the 7.2.8 module.
---
sound/hda/codecs/realtek/alc269.c | 92 ++++++++++++++++++++++++---------------
1 file changed, 56 insertions(+), 36 deletions(-)
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index 447c0ba358d8..a68b6a9b71aa 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -4377,6 +4377,7 @@ enum {
ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST,
ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS,
ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE,
+ ALC287_FIXUP_LEGION_S7_15IMH05_AMP,
ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
ALC298_FIXUP_LENOVO_C940_DUET7,
ALC287_FIXUP_LENOVO_YOGA_BOOK_9I,
@@ -4529,6 +4530,53 @@ static void alc700_fixup_intel_hades_canyon(struct hda_codec *codec,
alc_update_coef_idx(codec, 0x1b, 0x0400, 0x0400);
}
+static const struct hda_verb legion_amp_verbs[] = {
+ /* left speaker */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x41 },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x1a },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
+
+ /* right speaker */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x42 },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x2a },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
+ {}
+};
+
+static void alc287_fixup_legion_s7_amp(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (action != HDA_FIXUP_ACT_INIT)
+ return;
+
+ snd_hda_sequence_write(codec, legion_amp_verbs);
+ /*
+ * The amplifiers accept the setup only a few ms after the first
+ * write (8 ms is the measured minimum on the test machine), so
+ * keep a margin.
+ */
+ msleep(20);
+ snd_hda_sequence_write(codec, legion_amp_verbs);
+}
+
static const struct hda_fixup alc269_fixups[] = {
[ALC298_FIXUP_RAZER_BLADE16_2025_PINS] = {
.type = HDA_FIXUP_PINS,
@@ -6593,41 +6641,13 @@ static const struct hda_fixup alc269_fixups[] = {
},
[ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS] = {
.type = HDA_FIXUP_VERBS,
- //.v.verbs = legion_15imhg05_coefs,
- .v.verbs = (const struct hda_verb[]) {
- // set left speaker Legion 7i.
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x41 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x1a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- // set right speaker Legion 7i.
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x42 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
- {}
- },
+ .v.verbs = legion_amp_verbs,
+ .chained = true,
+ .chain_id = ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE,
+ },
+ [ALC287_FIXUP_LEGION_S7_15IMH05_AMP] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc287_fixup_legion_s7_amp,
.chained = true,
.chain_id = ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE,
},
@@ -8348,7 +8368,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
HDA_CODEC_QUIRK(0x17aa, 0x38d5, "Lenovo Yoga Pro 9 16IMH9", ALC287_FIXUP_TAS2781_I2C),
HDA_CODEC_QUIRK(0x17aa, 0x38d6, "Lenovo Yoga Pro 9 16IMH9", ALC287_FIXUP_TAS2781_I2C),
HDA_CODEC_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
- SND_PCI_QUIRK(0x17aa, 0x3811, "Legion S7 15IMH05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
+ SND_PCI_QUIRK(0x17aa, 0x3811, "Legion S7 15IMH05", ALC287_FIXUP_LEGION_S7_15IMH05_AMP),
SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940 / Yoga Duet 7", ALC298_FIXUP_LENOVO_C940_DUET7),
SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
---
base-commit: c3e35f355fadf6be660e1fd356bb22140dda8e46
change-id: 20261007-legion-s7-9467a6bd47ef
Best regards,
--
Matej Sochan <matej.sochan@gmail.com>
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-07 20:38 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-07 20:37 [PATCH] ALSA: hda/realtek: Fix silent speakers on Lenovo Legion S7 15IMH05 Matej Sochan
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®