Linux Sound subsystem development
 help / color / mirror / Atom feed
* [PATCH 0/1] ALSA: hda/realtek: fix LG Gram Style 14 speakers
@ 2026-01-21 13:12 Damien
  2026-01-23 16:35 ` Takashi Iwai
  0 siblings, 1 reply; 4+ messages in thread
From: Damien @ 2026-01-21 13:12 UTC (permalink / raw)
  To: tiwai, perex; +Cc: linux-sound, alsa-devel


[-- Attachment #1.1: Type: text/plain, Size: 585 bytes --]

  Hi,

  The LG Gram Style 14 (14Z90RS-G.AD77F, SSID 1854:0490) with Realtek ALC298
  shows normal routing and volume changes, but internal speakers remain
silent
  unless a userland HDA-verb workaround is applied.

  This patch adds a dedicated quirk for the LG Gram Style 14 that programs
  the codec coefficient sequence used by the known workaround and enables
  the speaker amps only during playback.

  Tested-by: Dams <damien.dagorn29@gmail.com>
  Tested: speaker-test -D hw:0 -c 2 -t wav -l 1 (front left/right OK)

  Please find the patch series attached.

  Thanks,
  Damien

[-- Attachment #1.2: Type: text/html, Size: 720 bytes --]

[-- Attachment #2: 0000-cover-letter.patch --]
[-- Type: text/x-patch, Size: 899 bytes --]

From 113b13ace8671a18c8f3820b007d5757df43dd36 Mon Sep 17 00:00:00 2001
From: Dams <damien.dagorn29@gmail.com>
Date: Wed, 21 Jan 2026 14:06:38 +0100
Subject: [PATCH 0/1] ALSA: hda/realtek: fix LG Gram Style 14 speakers

The LG Gram Style 14 (14Z90RS-G.AD77F, SSID 1854:0490) with Realtek ALC298
shows normal routing and volume changes, but internal speakers stay silent
unless a userland HDA-verb workaround is applied.

This patch adds a dedicated quirk for the LG Gram Style 14 that programs
the codec coefficient sequence used by the known workaround and enables
the speaker amps only during playback.

Tested-by: Dams <damien.dagorn29@gmail.com>
Tested: speaker-test -D hw:0 -c 2 -t wav -l 1 (front left/right OK)

Dams (1):
  ALSA: hda/realtek: add LG Gram Style 14 amp init

 sound/hda/codecs/realtek/alc269.c | 168 ++++++++++++++++++++++++++++++
 1 file changed, 168 insertions(+)

-- 
2.51.0

[-- Attachment #3: 0001-ALSA-hda-realtek-add-LG-Gram-Style-14-amp-init.patch --]
[-- Type: text/x-patch, Size: 8448 bytes --]

From 113b13ace8671a18c8f3820b007d5757df43dd36 Mon Sep 17 00:00:00 2001
From: Dams <damien.dagorn29@gmail.com>
Date: Wed, 21 Jan 2026 14:06:30 +0100
Subject: [PATCH 1/1] ALSA: hda/realtek: add LG Gram Style 14 amp init

---
 sound/hda/codecs/realtek/alc269.c | 168 ++++++++++++++++++++++++++++++
 1 file changed, 168 insertions(+)

diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index f267437..acbe818 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -1814,6 +1814,161 @@ static void alc298_samsung_v2_init_amps(struct hda_codec *codec,
 	spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook;
 }
 
+struct alc298_lg_gram_style_seq {
+	unsigned short verb;
+	unsigned short idx;
+	unsigned short val;
+};
+
+static void alc298_lg_gram_style_coef_write(struct hda_codec *codec,
+					    unsigned int verb,
+					    unsigned int idx,
+					    unsigned int val)
+{
+	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x23);
+	snd_hda_codec_write(codec, 0x20, 0, verb, idx);
+	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0x00);
+	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, val);
+	snd_hda_codec_write(codec, 0x20, 0, 0x4b0, 0x11);
+}
+
+static void alc298_lg_gram_style_run_seq(struct hda_codec *codec,
+					 const struct alc298_lg_gram_style_seq *seq,
+					 int seq_size)
+{
+	int i;
+
+	for (i = 0; i < seq_size; i++)
+		alc298_lg_gram_style_coef_write(codec, seq[i].verb,
+						seq[i].idx, seq[i].val);
+}
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_preinit_seq[] = {
+	{ 0x420, 0x00, 0x01 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_disable_seq[] = {
+	{ 0x423, 0xff, 0x00 },
+	{ 0x420, 0x3a, 0x80 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_enable_seq[] = {
+	{ 0x420, 0x3a, 0x81 },
+	{ 0x423, 0xff, 0x01 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_38[] = {
+	{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
+	{ 0x420, 0x1b, 0x01 }, { 0x420, 0x1d, 0x01 }, { 0x420, 0x1f, 0xfe },
+	{ 0x420, 0x21, 0x00 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
+	{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
+	{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0x99, 0x03 },
+	{ 0x423, 0xa4, 0xb5 }, { 0x423, 0xa5, 0x01 }, { 0x423, 0xba, 0x94 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_39[] = {
+	{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
+	{ 0x420, 0x1b, 0x02 }, { 0x420, 0x1d, 0x02 }, { 0x420, 0x1f, 0xfd },
+	{ 0x420, 0x21, 0x01 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
+	{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
+	{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0x99, 0x03 },
+	{ 0x423, 0xa4, 0xb5 }, { 0x423, 0xa5, 0x01 }, { 0x423, 0xba, 0x94 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_3c[] = {
+	{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
+	{ 0x420, 0x1b, 0x01 }, { 0x420, 0x1d, 0x01 }, { 0x420, 0x1f, 0xfe },
+	{ 0x420, 0x21, 0x00 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
+	{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
+	{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0xba, 0x8d },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_3d[] = {
+	{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
+	{ 0x420, 0x1b, 0x02 }, { 0x420, 0x1d, 0x02 }, { 0x420, 0x1f, 0xfd },
+	{ 0x420, 0x21, 0x01 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
+	{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
+	{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0xba, 0x8d },
+};
+
+struct alc298_lg_gram_style_amp_desc {
+	unsigned char nid;
+	const struct alc298_lg_gram_style_seq *init_seq;
+	int init_seq_size;
+};
+
+static const struct alc298_lg_gram_style_amp_desc alc298_lg_gram_style_amps[] = {
+	{ 0x38, alc298_lg_gram_style_init_seq_38,
+		ARRAY_SIZE(alc298_lg_gram_style_init_seq_38) },
+	{ 0x39, alc298_lg_gram_style_init_seq_39,
+		ARRAY_SIZE(alc298_lg_gram_style_init_seq_39) },
+	{ 0x3c, alc298_lg_gram_style_init_seq_3c,
+		ARRAY_SIZE(alc298_lg_gram_style_init_seq_3c) },
+	{ 0x3d, alc298_lg_gram_style_init_seq_3d,
+		ARRAY_SIZE(alc298_lg_gram_style_init_seq_3d) },
+};
+
+static void alc298_lg_gram_style_enable_amps(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < spec->num_speaker_amps; i++) {
+		alc_write_coef_idx(codec, 0x22, alc298_lg_gram_style_amps[i].nid);
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_enable_seq,
+					     ARRAY_SIZE(alc298_lg_gram_style_enable_seq));
+	}
+}
+
+static void alc298_lg_gram_style_disable_amps(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < spec->num_speaker_amps; i++) {
+		alc_write_coef_idx(codec, 0x22, alc298_lg_gram_style_amps[i].nid);
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_disable_seq,
+					     ARRAY_SIZE(alc298_lg_gram_style_disable_seq));
+	}
+}
+
+static void alc298_lg_gram_style_playback_hook(struct hda_pcm_stream *hinfo,
+					       struct hda_codec *codec,
+					       struct snd_pcm_substream *substream,
+					       int action)
+{
+	if (action == HDA_GEN_PCM_ACT_OPEN)
+		alc298_lg_gram_style_enable_amps(codec);
+	if (action == HDA_GEN_PCM_ACT_CLOSE)
+		alc298_lg_gram_style_disable_amps(codec);
+}
+
+static void alc298_lg_gram_style_init_amps(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	spec->num_speaker_amps = ARRAY_SIZE(alc298_lg_gram_style_amps);
+
+	for (i = 0; i < spec->num_speaker_amps; i++) {
+		alc_write_coef_idx(codec, 0x22, alc298_lg_gram_style_amps[i].nid);
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_preinit_seq,
+					     ARRAY_SIZE(alc298_lg_gram_style_preinit_seq));
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_disable_seq,
+					     ARRAY_SIZE(alc298_lg_gram_style_disable_seq));
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_amps[i].init_seq,
+					     alc298_lg_gram_style_amps[i].init_seq_size);
+		alc_write_coef_idx(codec, 0x89, 0x0);
+	}
+
+	spec->gen.pcm_playback_hook = alc298_lg_gram_style_playback_hook;
+}
+
 static void alc298_fixup_samsung_amp_v2_2_amps(struct hda_codec *codec,
 				const struct hda_fixup *fix, int action)
 {
@@ -1828,6 +1983,13 @@ static void alc298_fixup_samsung_amp_v2_4_amps(struct hda_codec *codec,
 		alc298_samsung_v2_init_amps(codec, 4);
 }
 
+static void alc298_fixup_lg_gram_style_14(struct hda_codec *codec,
+					  const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PROBE)
+		alc298_lg_gram_style_init_amps(codec);
+}
+
 static void gpio2_mic_hotkey_event(struct hda_codec *codec,
 				   struct hda_jack_callback *event)
 {
@@ -3630,6 +3792,7 @@ enum {
 	ALC298_FIXUP_SAMSUNG_AMP,
 	ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS,
 	ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS,
+	ALC298_FIXUP_LG_GRAM_STYLE_14,
 	ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
 	ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
 	ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
@@ -5294,6 +5457,10 @@ static const struct hda_fixup alc269_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc298_fixup_samsung_amp_v2_4_amps
 	},
+	[ALC298_FIXUP_LG_GRAM_STYLE_14] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc298_fixup_lg_gram_style_14
+	},
 	[ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
 		.type = HDA_FIXUP_VERBS,
 		.v.verbs = (const struct hda_verb[]) {
@@ -7135,6 +7302,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1854, 0x0488, "LG gram 16 (16Z90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
 	SND_PCI_QUIRK(0x1854, 0x0489, "LG gram 16 (16Z90R-A)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
 	SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
+	SND_PCI_QUIRK(0x1854, 0x0490, "LG Gram Style 14 (14Z90RS)", ALC298_FIXUP_LG_GRAM_STYLE_14),
 	SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
 	SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x19e5, 0x3212, "Huawei KLV-WX9 ", ALC256_FIXUP_ACER_HEADSET_MIC),
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/1] ALSA: hda/realtek: fix LG Gram Style 14 speakers
  2026-01-21 13:12 [PATCH 0/1] ALSA: hda/realtek: fix LG Gram Style 14 speakers Damien
@ 2026-01-23 16:35 ` Takashi Iwai
  2026-01-23 17:20   ` Damien
  0 siblings, 1 reply; 4+ messages in thread
From: Takashi Iwai @ 2026-01-23 16:35 UTC (permalink / raw)
  To: Damien; +Cc: perex, linux-sound, alsa-devel

On Wed, 21 Jan 2026 14:12:09 +0100,
Damien wrote:
> 
> 
>   Hi,
> 
>   The LG Gram Style 14 (14Z90RS-G.AD77F, SSID 1854:0490) with Realtek ALC298
>   shows normal routing and volume changes, but internal speakers remain silent
>   unless a userland HDA-verb workaround is applied.
> 
>   This patch adds a dedicated quirk for the LG Gram Style 14 that programs
>   the codec coefficient sequence used by the known workaround and enables
>   the speaker amps only during playback.
> 
>   Tested-by: Dams <damien.dagorn29@gmail.com>
>   Tested: speaker-test -D hw:0 -c 2 -t wav -l 1 (front left/right OK)
> 
>   Please find the patch series attached.
> 
>   Thanks,
>   Damien

Thanks for the patch.  Unfortunately, the patch looks created somehow
in a not ideal way.  First of all, the useful information like:
> 
> From 113b13ace8671a18c8f3820b007d5757df43dd36 Mon Sep 17 00:00:00 2001
> From: Dams <damien.dagorn29@gmail.com>
> Date: Wed, 21 Jan 2026 14:06:38 +0100
> Subject: [PATCH 0/1] ALSA: hda/realtek: fix LG Gram Style 14 speakers
> 
> The LG Gram Style 14 (14Z90RS-G.AD77F, SSID 1854:0490) with Realtek ALC298
> shows normal routing and volume changes, but internal speakers stay silent
> unless a userland HDA-verb workaround is applied.
> 
> This patch adds a dedicated quirk for the LG Gram Style 14 that programs
> the codec coefficient sequence used by the known workaround and enables
> the speaker amps only during playback.
> 
> Tested-by: Dams <damien.dagorn29@gmail.com>
> Tested: speaker-test -D hw:0 -c 2 -t wav -l 1 (front left/right OK)

... those should be put rather in the description of the patch itself.
You've put it in 0/1, that is a cover letter, which won't be included
in the git commit.
(And in general, there is no need for splitting to a cover letter if
it's only a single patch; describe it right in the patch itself or
not.)

Secondly, a valid Signed-off-by tag is mandatory for upstreaming.
It's a legal requirement.  And for the Signed-off-by tag (also the
From line as the author), you should provide a full real name.

Now about the code changes:

> --- a/sound/hda/codecs/realtek/alc269.c
> +++ b/sound/hda/codecs/realtek/alc269.c
> @@ -1814,6 +1814,161 @@ static void alc298_samsung_v2_init_amps(struct hda_codec *codec,
>  	spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook;
>  }
>  

Maybe it'd be better to have some comments about the quirk.
It's no trivial code, hence it's worth for explanation.

> +struct alc298_lg_gram_style_seq {
> +	unsigned short verb;
> +	unsigned short idx;
> +	unsigned short val;
> +};
> +
> +static void alc298_lg_gram_style_coef_write(struct hda_codec *codec,
> +					    unsigned int verb,
> +					    unsigned int idx,
> +					    unsigned int val)
> +{
> +	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x23);
> +	snd_hda_codec_write(codec, 0x20, 0, verb, idx);
> +	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0x00);
> +	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, val);
> +	snd_hda_codec_write(codec, 0x20, 0, 0x4b0, 0x11);

Use AC_VERB_SET_PROC_COEF for 0x400.  It's equivalent with
	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0xb011);

Could you try to resubmit with the corrections above?


thanks,

Takashi

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/1] ALSA: hda/realtek: fix LG Gram Style 14 speakers
  2026-01-23 16:35 ` Takashi Iwai
@ 2026-01-23 17:20   ` Damien
  2026-01-24 10:21     ` Takashi Iwai
  0 siblings, 1 reply; 4+ messages in thread
From: Damien @ 2026-01-23 17:20 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: perex, linux-sound, alsa-devel


[-- Attachment #1.1: Type: text/plain, Size: 4170 bytes --]

 Hi Takashi,

 Thanks for the feedback. I’ve reworked the patch as requested:
 - single patch (no cover letter), with the full description in the commit
message
 - proper Signed-off-by with my full name
 - added comments for the quirk
 - use AC_VERB_SET_PROC_COEF for 0x400 and 0xb011 instead of 0x4b0

I hope this rework matches your request

 Please find the updated patch attached.

  Thanks,
  Damien

Le ven. 23 janv. 2026 à 17:35, Takashi Iwai <tiwai@suse.de> a écrit :

> On Wed, 21 Jan 2026 14:12:09 +0100,
> Damien wrote:
> >
> >
> >   Hi,
> >
> >   The LG Gram Style 14 (14Z90RS-G.AD77F, SSID 1854:0490) with Realtek
> ALC298
> >   shows normal routing and volume changes, but internal speakers remain
> silent
> >   unless a userland HDA-verb workaround is applied.
> >
> >   This patch adds a dedicated quirk for the LG Gram Style 14 that
> programs
> >   the codec coefficient sequence used by the known workaround and enables
> >   the speaker amps only during playback.
> >
> >   Tested-by: Dams <damien.dagorn29@gmail.com>
> >   Tested: speaker-test -D hw:0 -c 2 -t wav -l 1 (front left/right OK)
> >
> >   Please find the patch series attached.
> >
> >   Thanks,
> >   Damien
>
> Thanks for the patch.  Unfortunately, the patch looks created somehow
> in a not ideal way.  First of all, the useful information like:
> >
> > From 113b13ace8671a18c8f3820b007d5757df43dd36 Mon Sep 17 00:00:00 2001
> > From: Dams <damien.dagorn29@gmail.com>
> > Date: Wed, 21 Jan 2026 14:06:38 +0100
> > Subject: [PATCH 0/1] ALSA: hda/realtek: fix LG Gram Style 14 speakers
> >
> > The LG Gram Style 14 (14Z90RS-G.AD77F, SSID 1854:0490) with Realtek
> ALC298
> > shows normal routing and volume changes, but internal speakers stay
> silent
> > unless a userland HDA-verb workaround is applied.
> >
> > This patch adds a dedicated quirk for the LG Gram Style 14 that programs
> > the codec coefficient sequence used by the known workaround and enables
> > the speaker amps only during playback.
> >
> > Tested-by: Dams <damien.dagorn29@gmail.com>
> > Tested: speaker-test -D hw:0 -c 2 -t wav -l 1 (front left/right OK)
>
> ... those should be put rather in the description of the patch itself.
> You've put it in 0/1, that is a cover letter, which won't be included
> in the git commit.
> (And in general, there is no need for splitting to a cover letter if
> it's only a single patch; describe it right in the patch itself or
> not.)
>
> Secondly, a valid Signed-off-by tag is mandatory for upstreaming.
> It's a legal requirement.  And for the Signed-off-by tag (also the
> From line as the author), you should provide a full real name.
>
> Now about the code changes:
>
> > --- a/sound/hda/codecs/realtek/alc269.c
> > +++ b/sound/hda/codecs/realtek/alc269.c
> > @@ -1814,6 +1814,161 @@ static void alc298_samsung_v2_init_amps(struct
> hda_codec *codec,
> >       spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook;
> >  }
> >
>
> Maybe it'd be better to have some comments about the quirk.
> It's no trivial code, hence it's worth for explanation.
>
> > +struct alc298_lg_gram_style_seq {
> > +     unsigned short verb;
> > +     unsigned short idx;
> > +     unsigned short val;
> > +};
> > +
> > +static void alc298_lg_gram_style_coef_write(struct hda_codec *codec,
> > +                                         unsigned int verb,
> > +                                         unsigned int idx,
> > +                                         unsigned int val)
> > +{
> > +     snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x23);
> > +     snd_hda_codec_write(codec, 0x20, 0, verb, idx);
> > +     snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0x00);
> > +     snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, val);
> > +     snd_hda_codec_write(codec, 0x20, 0, 0x4b0, 0x11);
>
> Use AC_VERB_SET_PROC_COEF for 0x400.  It's equivalent with
>         snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0xb011);
>
> Could you try to resubmit with the corrections above?
>
>
> thanks,
>
> Takashi
>

[-- Attachment #1.2: Type: text/html, Size: 5208 bytes --]

[-- Attachment #2: 0001-ALSA-hda-realtek-fix-LG-Gram-Style-14-speakers.patch --]
[-- Type: text/x-patch, Size: 9112 bytes --]

From 82a7855e66194e1882c18409345bf41324ba6874 Mon Sep 17 00:00:00 2001
From: Damien Dagorn <damien.dagorn29@gmail.com>
Date: Fri, 23 Jan 2026 18:14:52 +0100
Subject: [PATCH] ALSA: hda/realtek: fix LG Gram Style 14 speakers

The LG Gram Style 14 (14Z90RS-G.AD77F, SSID 1854:0490) with Realtek ALC298
shows normal routing and volume changes, but internal speakers stay silent
unless a userland HDA-verb workaround is applied.

Add a dedicated quirk for the LG Gram Style 14 that programs the codec
coefficient sequence used by the known workaround and enables the speaker
amps only during playback.

Tested-by: Damien Dagorn <damien.dagorn29@gmail.com>
Signed-off-by: Damien Dagorn <damien.dagorn29@gmail.com>
---
 sound/hda/codecs/realtek/alc269.c | 170 ++++++++++++++++++++++++++++++
 1 file changed, 170 insertions(+)

diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index f267437..c2bba85 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -1814,6 +1814,163 @@ static void alc298_samsung_v2_init_amps(struct hda_codec *codec,
 	spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook;
 }
 
+/* LG Gram Style 14: program vendor coef sequence used by HDA-verb workaround */
+struct alc298_lg_gram_style_seq {
+	unsigned short verb;
+	unsigned short idx;
+	unsigned short val;
+};
+
+static void alc298_lg_gram_style_coef_write(struct hda_codec *codec,
+					    unsigned int verb,
+					    unsigned int idx,
+					    unsigned int val)
+{
+	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x23);
+	snd_hda_codec_write(codec, 0x20, 0, verb, idx);
+	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0x00);
+	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, val);
+	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0xb011);
+}
+
+static void alc298_lg_gram_style_run_seq(struct hda_codec *codec,
+					 const struct alc298_lg_gram_style_seq *seq,
+					 int seq_size)
+{
+	int i;
+
+	for (i = 0; i < seq_size; i++)
+		alc298_lg_gram_style_coef_write(codec, seq[i].verb,
+						seq[i].idx, seq[i].val);
+}
+
+/* Coef sequences derived from the HDA-verb workaround for this model. */
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_preinit_seq[] = {
+	{ 0x420, 0x00, 0x01 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_disable_seq[] = {
+	{ 0x423, 0xff, 0x00 },
+	{ 0x420, 0x3a, 0x80 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_enable_seq[] = {
+	{ 0x420, 0x3a, 0x81 },
+	{ 0x423, 0xff, 0x01 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_38[] = {
+	{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
+	{ 0x420, 0x1b, 0x01 }, { 0x420, 0x1d, 0x01 }, { 0x420, 0x1f, 0xfe },
+	{ 0x420, 0x21, 0x00 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
+	{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
+	{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0x99, 0x03 },
+	{ 0x423, 0xa4, 0xb5 }, { 0x423, 0xa5, 0x01 }, { 0x423, 0xba, 0x94 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_39[] = {
+	{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
+	{ 0x420, 0x1b, 0x02 }, { 0x420, 0x1d, 0x02 }, { 0x420, 0x1f, 0xfd },
+	{ 0x420, 0x21, 0x01 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
+	{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
+	{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0x99, 0x03 },
+	{ 0x423, 0xa4, 0xb5 }, { 0x423, 0xa5, 0x01 }, { 0x423, 0xba, 0x94 },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_3c[] = {
+	{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
+	{ 0x420, 0x1b, 0x01 }, { 0x420, 0x1d, 0x01 }, { 0x420, 0x1f, 0xfe },
+	{ 0x420, 0x21, 0x00 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
+	{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
+	{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0xba, 0x8d },
+};
+
+static const struct alc298_lg_gram_style_seq alc298_lg_gram_style_init_seq_3d[] = {
+	{ 0x423, 0xe1, 0x00 }, { 0x420, 0x12, 0x6f }, { 0x420, 0x14, 0x00 },
+	{ 0x420, 0x1b, 0x02 }, { 0x420, 0x1d, 0x02 }, { 0x420, 0x1f, 0xfd },
+	{ 0x420, 0x21, 0x01 }, { 0x420, 0x22, 0x10 }, { 0x420, 0x3d, 0x05 },
+	{ 0x420, 0x3f, 0x03 }, { 0x420, 0x50, 0x2c }, { 0x420, 0x76, 0x0e },
+	{ 0x420, 0x7c, 0x4a }, { 0x420, 0x81, 0x03 }, { 0x423, 0xba, 0x8d },
+};
+
+struct alc298_lg_gram_style_amp_desc {
+	unsigned char nid;
+	const struct alc298_lg_gram_style_seq *init_seq;
+	int init_seq_size;
+};
+
+static const struct alc298_lg_gram_style_amp_desc alc298_lg_gram_style_amps[] = {
+	{ 0x38, alc298_lg_gram_style_init_seq_38,
+		ARRAY_SIZE(alc298_lg_gram_style_init_seq_38) },
+	{ 0x39, alc298_lg_gram_style_init_seq_39,
+		ARRAY_SIZE(alc298_lg_gram_style_init_seq_39) },
+	{ 0x3c, alc298_lg_gram_style_init_seq_3c,
+		ARRAY_SIZE(alc298_lg_gram_style_init_seq_3c) },
+	{ 0x3d, alc298_lg_gram_style_init_seq_3d,
+		ARRAY_SIZE(alc298_lg_gram_style_init_seq_3d) },
+};
+
+static void alc298_lg_gram_style_enable_amps(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < spec->num_speaker_amps; i++) {
+		alc_write_coef_idx(codec, 0x22, alc298_lg_gram_style_amps[i].nid);
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_enable_seq,
+					     ARRAY_SIZE(alc298_lg_gram_style_enable_seq));
+	}
+}
+
+static void alc298_lg_gram_style_disable_amps(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < spec->num_speaker_amps; i++) {
+		alc_write_coef_idx(codec, 0x22, alc298_lg_gram_style_amps[i].nid);
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_disable_seq,
+					     ARRAY_SIZE(alc298_lg_gram_style_disable_seq));
+	}
+}
+
+static void alc298_lg_gram_style_playback_hook(struct hda_pcm_stream *hinfo,
+					       struct hda_codec *codec,
+					       struct snd_pcm_substream *substream,
+					       int action)
+{
+	if (action == HDA_GEN_PCM_ACT_OPEN)
+		alc298_lg_gram_style_enable_amps(codec);
+	if (action == HDA_GEN_PCM_ACT_CLOSE)
+		alc298_lg_gram_style_disable_amps(codec);
+}
+
+static void alc298_lg_gram_style_init_amps(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	spec->num_speaker_amps = ARRAY_SIZE(alc298_lg_gram_style_amps);
+
+	for (i = 0; i < spec->num_speaker_amps; i++) {
+		alc_write_coef_idx(codec, 0x22, alc298_lg_gram_style_amps[i].nid);
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_preinit_seq,
+					     ARRAY_SIZE(alc298_lg_gram_style_preinit_seq));
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_disable_seq,
+					     ARRAY_SIZE(alc298_lg_gram_style_disable_seq));
+		alc298_lg_gram_style_run_seq(codec,
+					     alc298_lg_gram_style_amps[i].init_seq,
+					     alc298_lg_gram_style_amps[i].init_seq_size);
+		alc_write_coef_idx(codec, 0x89, 0x0);
+	}
+
+	spec->gen.pcm_playback_hook = alc298_lg_gram_style_playback_hook;
+}
+
 static void alc298_fixup_samsung_amp_v2_2_amps(struct hda_codec *codec,
 				const struct hda_fixup *fix, int action)
 {
@@ -1828,6 +1985,13 @@ static void alc298_fixup_samsung_amp_v2_4_amps(struct hda_codec *codec,
 		alc298_samsung_v2_init_amps(codec, 4);
 }
 
+static void alc298_fixup_lg_gram_style_14(struct hda_codec *codec,
+					  const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PROBE)
+		alc298_lg_gram_style_init_amps(codec);
+}
+
 static void gpio2_mic_hotkey_event(struct hda_codec *codec,
 				   struct hda_jack_callback *event)
 {
@@ -3630,6 +3794,7 @@ enum {
 	ALC298_FIXUP_SAMSUNG_AMP,
 	ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS,
 	ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS,
+	ALC298_FIXUP_LG_GRAM_STYLE_14,
 	ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
 	ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
 	ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
@@ -5294,6 +5459,10 @@ static const struct hda_fixup alc269_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc298_fixup_samsung_amp_v2_4_amps
 	},
+	[ALC298_FIXUP_LG_GRAM_STYLE_14] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc298_fixup_lg_gram_style_14
+	},
 	[ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
 		.type = HDA_FIXUP_VERBS,
 		.v.verbs = (const struct hda_verb[]) {
@@ -7135,6 +7304,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1854, 0x0488, "LG gram 16 (16Z90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
 	SND_PCI_QUIRK(0x1854, 0x0489, "LG gram 16 (16Z90R-A)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
 	SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
+	SND_PCI_QUIRK(0x1854, 0x0490, "LG Gram Style 14 (14Z90RS)", ALC298_FIXUP_LG_GRAM_STYLE_14),
 	SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
 	SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x19e5, 0x3212, "Huawei KLV-WX9 ", ALC256_FIXUP_ACER_HEADSET_MIC),
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/1] ALSA: hda/realtek: fix LG Gram Style 14 speakers
  2026-01-23 17:20   ` Damien
@ 2026-01-24 10:21     ` Takashi Iwai
  0 siblings, 0 replies; 4+ messages in thread
From: Takashi Iwai @ 2026-01-24 10:21 UTC (permalink / raw)
  To: Damien; +Cc: perex, linux-sound, alsa-devel

On Fri, 23 Jan 2026 18:20:44 +0100,
Damien wrote:
> 
> 
>  Hi Takashi,
> 
>  Thanks for the feedback. I’ve reworked the patch as requested:
>  - single patch (no cover letter), with the full description in the commit
> message
>  - proper Signed-off-by with my full name
>  - added comments for the quirk
>  - use AC_VERB_SET_PROC_COEF for 0x400 and 0xb011 instead of 0x4b0
> 
> I hope this rework matches your request
> 
>  Please find the updated patch attached.
> 
>   Thanks,
>   Damien

Thanks, I applied now to for-next branch.

At the next time, please try to submit via git-fixes directly without
attachments.  An attachment is rather a last-resort when no direct
submission is possible by some reasons.


Takashi

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-01-24 10:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-21 13:12 [PATCH 0/1] ALSA: hda/realtek: fix LG Gram Style 14 speakers Damien
2026-01-23 16:35 ` Takashi Iwai
2026-01-23 17:20   ` Damien
2026-01-24 10:21     ` Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox