* [PATCH 1/2] ALSA: hda/realtek: Add speaker depop sequence to alc225_shutup
@ 2026-10-29 5:59 Zhang Heng
2026-10-29 5:59 ` [PATCH 2/2] ALSA: hda/realtek: Convert HP AIO SPK fixup to INIT-stage depop Zhang Heng
2026-10-29 6:18 ` [PATCH 1/2] ALSA: hda/realtek: Add speaker depop sequence to alc225_shutup sashiko-bot
0 siblings, 2 replies; 4+ messages in thread
From: Zhang Heng @ 2026-10-29 5:59 UTC (permalink / raw)
To: tiwai; +Cc: perex, kailang, linux-sound, linux-kernel, Zhang Heng, John Doe
Mute speaker pins and disable their pin widgets, with a 75 ms delay
after each step, before cutting EAPD in alc225_shutup(). This
prevents the pop noise that occurs on suspend when the amplifier
loses its input signal while still powered.
Reported-by: John Doe <coolcrew45@disroot.org>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221616
Tested-by: John Doe <coolcrew45@disroot.org>
Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
---
sound/hda/codecs/realtek/alc269.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index 23329d5887a5..67ce5b130f81 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -665,6 +665,7 @@ static void alc225_shutup(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
hda_nid_t hp_pin = alc_get_hp_pin(spec);
bool hp1_pin_sense, hp2_pin_sense;
+ int i;
if (!hp_pin)
hp_pin = 0x21;
@@ -698,6 +699,16 @@ static void alc225_shutup(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
alc_enable_headset_jack_key(codec);
}
+
+ for (i = 0; i < spec->gen.autocfg.speaker_outs; i++)
+ snd_hda_codec_write(codec, spec->gen.autocfg.speaker_pins[i], 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+ msleep(75);
+ for (i = 0; i < spec->gen.autocfg.speaker_outs; i++)
+ snd_hda_codec_write(codec, spec->gen.autocfg.speaker_pins[i], 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ msleep(75);
+
alc_auto_setup_eapd(codec, false);
alc_shutup_pins(codec);
if (spec->ultra_low_power) {
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] ALSA: hda/realtek: Convert HP AIO SPK fixup to INIT-stage depop
2026-10-29 5:59 [PATCH 1/2] ALSA: hda/realtek: Add speaker depop sequence to alc225_shutup Zhang Heng
@ 2026-10-29 5:59 ` Zhang Heng
2026-10-29 6:13 ` sashiko-bot
2026-10-29 6:18 ` [PATCH 1/2] ALSA: hda/realtek: Add speaker depop sequence to alc225_shutup sashiko-bot
1 sibling, 1 reply; 4+ messages in thread
From: Zhang Heng @ 2026-10-29 5:59 UTC (permalink / raw)
To: tiwai; +Cc: perex, kailang, linux-sound, linux-kernel, Zhang Heng, John Doe
Replace the static coef-0x10 verb table with a function that mutes
pin 0x1b, writes coef 0x10, waits 75 ms, then unmutes — eliminating
the pop when the internal amplifier enables at init time. Add
SSID 103c:84ee to the quirk table.
Reported-by: John Doe <coolcrew45@disroot.org>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221616
Tested-by: John Doe <coolcrew45@disroot.org>
Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
---
sound/hda/codecs/realtek/alc269.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index 67ce5b130f81..3a1b664fca0e 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -2902,6 +2902,20 @@ static void alc225_fixup_s3_pop_noise(struct hda_codec *codec,
codec->power_save_node = 1;
}
+static void alc225_fixup_hp_aio_spk(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (action != HDA_FIXUP_ACT_INIT)
+ return;
+
+ snd_hda_codec_write(codec, 0x1b, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+ alc_write_coef_idx(codec, 0x10, 0x0220);
+ msleep(75);
+ snd_hda_codec_write(codec, 0x1b, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+}
+
/* Forcibly assign NID 0x03 to HP/LO while NID 0x02 to SPK for EQ */
static void alc274_fixup_bind_dacs(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
@@ -5987,12 +6001,8 @@ static const struct hda_fixup alc269_fixups[] = {
.chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
},
[ALC225_FIXUP_HP_AIO_SPK] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x10 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0220 },
- { }
- },
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc225_fixup_hp_aio_spk,
},
[ALC286_FIXUP_ACER_AIO_HEADSET_MIC] = {
.type = HDA_FIXUP_VERBS,
@@ -7737,6 +7747,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x854d, "HP EliteBook 840 G6", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x856a, "HP Pavilion 15-cs1xxx", ALC295_FIXUP_HP_PAVILION_MUTE_LED_1B),
+ HDA_CODEC_QUIRK(0x103c, 0x84ee, "HP Pavilion AiO 24", ALC225_FIXUP_HP_AIO_SPK),
HDA_CODEC_QUIRK(0x103c, 0x85ba, "HP Pavilion AiO 24", ALC225_FIXUP_HP_AIO_SPK),
SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11),
SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360),
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] ALSA: hda/realtek: Convert HP AIO SPK fixup to INIT-stage depop
2026-10-29 5:59 ` [PATCH 2/2] ALSA: hda/realtek: Convert HP AIO SPK fixup to INIT-stage depop Zhang Heng
@ 2026-10-29 6:13 ` sashiko-bot
0 siblings, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-10-29 6:13 UTC (permalink / raw)
To: Zhang Heng; +Cc: linux-sound
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] ALSA: hda/realtek: unconditional unmute in alc225_fixup_hp_aio_spk()
- [Low] ALSA: hda/realtek: duplicate 103c:84ee quirk entry in alc269_fixup_tbl
--
commit 2bd7f803bf3acde738482eabfd02d74f96a4d957
Author: Zhang Heng <zhangheng@kylinos.cn>
ALSA: hda/realtek: Convert HP AIO SPK fixup to INIT-stage depop
This commit replaces the static coef 0x10 verb table for
ALC225_FIXUP_HP_AIO_SPK with an init-stage fixup function that mutes pin 0x1b,
writes coef 0x10, sleeps 75 ms, and unmutes pin 0x1b. It also adds a quirk
entry for SSID 103c:84ee in alc269_fixup_tbl.
> diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
> index 67ce5b130f81f..3a1b664fca0ef 100644
> --- a/sound/hda/codecs/realtek/alc269.c
> +++ b/sound/hda/codecs/realtek/alc269.c
> @@ -2902,6 +2902,20 @@ static void alc225_fixup_s3_pop_noise(struct hda_codec *codec,
> codec->power_save_node = 1;
> }
>
> +static void alc225_fixup_hp_aio_spk(struct hda_codec *codec,
> + const struct hda_fixup *fix, int action)
> +{
> + if (action != HDA_FIXUP_ACT_INIT)
> + return;
> +
> + snd_hda_codec_write(codec, 0x1b, 0,
> + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
> + alc_write_coef_idx(codec, 0x10, 0x0220);
> + msleep(75);
> + snd_hda_codec_write(codec, 0x1b, 0,
> + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
> +}
[Severity: Medium]
Does unconditionally writing AMP_OUT_UNMUTE via snd_hda_codec_write() here
override the mixer or headphone auto-mute state and desynchronize
codec->core.regmap on init and resume?
During codec initialization in sound/hda/codecs/realtek/realtek.c:alc_init(),
snd_hda_gen_init() runs before HDA_FIXUP_ACT_INIT fixups are applied:
sound/hda/codecs/realtek/realtek.c:alc_init() {
...
snd_hda_gen_init(codec);
alc_fix_pll(codec);
alc_auto_init_amp(codec, spec->init_amp);
snd_hda_apply_verbs(codec); /* apply verbs here after own init */
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
...
}
Inside sound/hda/codecs/generic.c:snd_hda_gen_init(), the output paths and
auto-mute state are initialized in codec->core.regmap and flushed to hardware:
sound/hda/codecs/generic.c:snd_hda_gen_init() {
...
/* call init functions of standard auto-mute helpers */
update_automute_all(codec);
snd_hda_regmap_sync(codec);
}
When alc225_fixup_hp_aio_spk() then runs at HDA_FIXUP_ACT_INIT, calling
snd_hda_codec_write() sends raw verbs via snd_hdac_codec_write(), bypassing
codec->core.regmap. If the Speaker or Master Playback Switch was muted (or
auto-muted by headphones), hardware pin 0x1b is left unmuted while regmap
still caches HDA_AMP_MUTE. Because snd_hda_gen_init() already cleared the
regmap dirty state, the trailing snd_hda_regmap_sync() in alc269_resume() is
a no-op, and subsequent userspace attempts to mute via
snd_hda_mixer_amp_switch_put() -> snd_hda_codec_amp_update() see no change
against the cached value and suppress the hardware write.
Should alc225_fixup_hp_aio_spk() restore pin 0x1b to its cached regmap amp
state instead of unconditionally writing AMP_OUT_UNMUTE?
[ ... ]
> @@ -7737,6 +7747,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
> SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED),
> SND_PCI_QUIRK(0x103c, 0x854d, "HP EliteBook 840 G6", ALC285_FIXUP_HP_GPIO_LED),
> SND_PCI_QUIRK(0x103c, 0x856a, "HP Pavilion 15-cs1xxx", ALC295_FIXUP_HP_PAVILION_MUTE_LED_1B),
> + HDA_CODEC_QUIRK(0x103c, 0x84ee, "HP Pavilion AiO 24", ALC225_FIXUP_HP_AIO_SPK),
[Severity: Low]
Doesn't this add a duplicate quirk entry to alc269_fixup_tbl[]?
Commit fd47de58575a ("ALSA: hda/realtek: Add quirk for HP Pavilion AiO 24
(ALC225)") already added an identical entry further down in
alc269_fixup_tbl[]:
SND_PCI_QUIRK(0x103c, 0x8e43, "HP Laptop 15-fd2xxx", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
HDA_CODEC_QUIRK(0x103c, 0x84ee, "HP Pavilion AiO 24", ALC225_FIXUP_HP_AIO_SPK),
SND_PCI_QUIRK(0x103c, 0x8e60, "HP OmniBook 7 Laptop 16-bh0xxx", ALC245_FIXUP_CS35L41_I2C_2_MUTE_LED),
In addition, placing 0x84ee after 0x856a leaves it out of ascending subdevice
ID order (right after 0x84e7). Should the pre-existing misplaced entry be
removed when moving it to its sorted position?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261029055945.188723-1-zhangheng@kylinos.cn?part=2
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] ALSA: hda/realtek: Add speaker depop sequence to alc225_shutup
2026-10-29 5:59 [PATCH 1/2] ALSA: hda/realtek: Add speaker depop sequence to alc225_shutup Zhang Heng
2026-10-29 5:59 ` [PATCH 2/2] ALSA: hda/realtek: Convert HP AIO SPK fixup to INIT-stage depop Zhang Heng
@ 2026-10-29 6:18 ` sashiko-bot
1 sibling, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-10-29 6:18 UTC (permalink / raw)
To: Zhang Heng; +Cc: linux-sound
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] ALSA: hda/realtek: alc225_shutup() ignores spec->no_shutup_pins on speakers
- [Medium] ALSA: hda/realtek: alc225_shutup() misses auto_cfg_speaker_pins() and sleeps
--
commit bcfd970890c43a9ca0666614579d8a6c2d5603c7
Author: Zhang Heng <zhangheng@kylinos.cn>
ALSA: hda/realtek: Add speaker depop sequence to alc225_shutup
This commit mutes speaker pins and disables their pin widgets with 75 ms
delays before cutting EAPD in alc225_shutup() to prevent pop noise on
suspend.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221616
> diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
> index 23329d5887a56..67ce5b130f81f 100644
> --- a/sound/hda/codecs/realtek/alc269.c
> +++ b/sound/hda/codecs/realtek/alc269.c
> @@ -665,6 +665,7 @@ static void alc225_shutup(struct hda_codec *codec)
> struct alc_spec *spec = codec->spec;
> hda_nid_t hp_pin = alc_get_hp_pin(spec);
> bool hp1_pin_sense, hp2_pin_sense;
> + int i;
>
> if (!hp_pin)
> hp_pin = 0x21;
> @@ -698,6 +699,16 @@ static void alc225_shutup(struct hda_codec *codec)
> alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
> alc_enable_headset_jack_key(codec);
> }
> +
> + for (i = 0; i < spec->gen.autocfg.speaker_outs; i++)
> + snd_hda_codec_write(codec, spec->gen.autocfg.speaker_pins[i], 0,
> + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
> + msleep(75);
> + for (i = 0; i < spec->gen.autocfg.speaker_outs; i++)
> + snd_hda_codec_write(codec, spec->gen.autocfg.speaker_pins[i], 0,
> + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
[Severity: Medium]
Should this loop check !spec->no_shutup_pins before clearing
AC_VERB_SET_PIN_WIDGET_CONTROL on spec->gen.autocfg.speaker_pins[i]?
Previously, alc225_shutup() only cleared speaker pin widget controls via
alc_shutup_pins() in sound/hda/codecs/realtek/realtek.c:
void alc_shutup_pins(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
if (spec->no_shutup_pins)
return;
Other shutup callbacks in sound/hda/codecs/realtek/alc269.c, such as
alc256_shutup(), alc282_shutup(), alc283_shutup(), and alc_default_shutup(),
also guard AC_VERB_SET_PIN_WIDGET_CONTROL = 0x0 writes with
if (!spec->no_shutup_pins).
Several quirks for codecs using alc225_shutup() (such as ALC285, ALC287, and
ALC295) set spec->no_shutup_pins via alc_fixup_no_shutup(), including
alc_fixup_thinkpad_acpi() and alc295_fixup_dell_inspiron_top_speakers().
When hda_call_codec_suspend() -> alc269_suspend() -> alc_suspend() ->
alc_shutup() -> alc225_shutup() runs on those machines, clearing the speaker
pin widget controls unconditionally bypasses the no_shutup_pins quirk while
alc_shutup_pins() still returns early without setting codec->pins_shutup, so
restore_shutup_pins() will also skip restoring the pins on early resume.
> + msleep(75);
[Severity: Medium]
What happens in alc225_shutup() when spec->gen.autocfg.speaker_outs is 0, or
when the speaker pins were moved to line_out_pins by
snd_hda_parse_pin_defcfg()?
In sound/hda/common/auto_parser.c, snd_hda_parse_pin_defcfg() moves
speaker_pins into line_out_pins when no line-out pins are present:
if (cfg->speaker_outs) {
cfg->line_outs = cfg->speaker_outs;
memcpy(cfg->line_out_pins, cfg->speaker_pins,
sizeof(cfg->speaker_pins));
cfg->speaker_outs = 0;
memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
}
And in sound/hda/codecs/generic.c, check_auto_mute_availability() only copies
them back to speaker_pins if at least two different output types are present
and suppress_auto_mute is not set. Otherwise, speaker_outs remains 0 while the
speaker pins reside in line_out_pins.
Furthermore, because both msleep(75) calls run outside any speaker count
check, systems with no speakers (or with speaker_outs == 0) will still incur
150 ms of unconditional sleep on every runtime PM and system suspend.
Would it make sense to use auto_cfg_speaker_outs() and
auto_cfg_speaker_pins() from sound/hda/common/hda_auto_parser.h (similar to
snd_hda_gen_shutup_speakers()), and only run the msleep(75) delays when there
are speaker pins to shut up?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261029055945.188723-1-zhangheng@kylinos.cn?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-29 6:18 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 5:59 [PATCH 1/2] ALSA: hda/realtek: Add speaker depop sequence to alc225_shutup Zhang Heng
2026-10-29 5:59 ` [PATCH 2/2] ALSA: hda/realtek: Convert HP AIO SPK fixup to INIT-stage depop Zhang Heng
2026-10-29 6:13 ` sashiko-bot
2026-10-29 6:18 ` [PATCH 1/2] ALSA: hda/realtek: Add speaker depop sequence to alc225_shutup sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.