Skip to content

Commit 7030469

Browse files
joshuagrishamgregkh
authored andcommitted
ALSA: hda/realtek: Refactor and simplify Samsung Galaxy Book init
[ Upstream commit 7e4d4b3 ] I have done a lot of analysis for these type of devices and collaborated quite a bit with Nick Weihs (author of the first patch submitted for this including adding samsung_helper.c). More information can be found in the issue on Github [1] including additional rationale and testing. The existing implementation includes a large number of equalizer coef values that are not necessary to actually init and enable the speaker amps, as well as create a somewhat worse sound profile. Users have reported "muffled" or "muddy" sound; more information about this including my analysis of the differences can be found in the linked Github issue. This patch refactors the "v2" version of ALC298_FIXUP_SAMSUNG_AMP to a much simpler implementation which removes the new samsung_helper.c, reuses more of the existing patch_realtek.c, and sends significantly fewer unnecessary coef values (including removing all of these EQ-specific coef values). A pcm_playback_hook is used to dynamically enable and disable the speaker amps only when there will be audio playback; this is to match the behavior of how the driver for these devices is working in Windows, and is suspected but not yet tested or confirmed to help with power consumption. Support for models with 2 speaker amps vs 4 speaker amps is controlled by a specific quirk name for both types. A new int num_speaker_amps has been added to alc_spec so that the hooks can know how many speaker amps to enable or disable. This design was chosen to limit the number of places that subsystem ids will need to be maintained: like this, they can be maintained only once in the quirk table and there will not be another separate list of subsystem ids to maintain elsewhere in the code. Also updated the quirk name from ALC298_FIXUP_SAMSUNG_AMP2 to ALC298_FIXUP_SAMSUNG_AMP_V2_.. as this is not a quirk for "Amp #2" on ALC298 but is instead a different version of how to handle it. More devices have been added (see Github issue for testing confirmation), as well as a small cleanup to existing names. [1]: thesofproject#4055 (comment) Signed-off-by: Joshua Grisham <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Takashi Iwai <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 50f63f1 commit 7030469

File tree

2 files changed

+144
-317
lines changed

2 files changed

+144
-317
lines changed

sound/pci/hda/patch_realtek.c

Lines changed: 144 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct alc_spec {
125125
unsigned int has_hs_key:1;
126126
unsigned int no_internal_mic_pin:1;
127127
unsigned int en_3kpull_low:1;
128+
int num_speaker_amps;
128129

129130
/* for PLL fix */
130131
hda_nid_t pll_nid;
@@ -4803,7 +4804,133 @@ static void alc298_fixup_samsung_amp(struct hda_codec *codec,
48034804
}
48044805
}
48054806

4806-
#include "samsung_helper.c"
4807+
struct alc298_samsung_v2_amp_desc {
4808+
unsigned short nid;
4809+
int init_seq_size;
4810+
unsigned short init_seq[18][2];
4811+
};
4812+
4813+
static const struct alc298_samsung_v2_amp_desc
4814+
alc298_samsung_v2_amp_desc_tbl[] = {
4815+
{ 0x38, 18, {
4816+
{ 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
4817+
{ 0x201b, 0x0001 }, { 0x201d, 0x0001 }, { 0x201f, 0x00fe },
4818+
{ 0x2021, 0x0000 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
4819+
{ 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
4820+
{ 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x2399, 0x0003 },
4821+
{ 0x23a4, 0x00b5 }, { 0x23a5, 0x0001 }, { 0x23ba, 0x0094 }
4822+
}},
4823+
{ 0x39, 18, {
4824+
{ 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
4825+
{ 0x201b, 0x0002 }, { 0x201d, 0x0002 }, { 0x201f, 0x00fd },
4826+
{ 0x2021, 0x0001 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
4827+
{ 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
4828+
{ 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x2399, 0x0003 },
4829+
{ 0x23a4, 0x00b5 }, { 0x23a5, 0x0001 }, { 0x23ba, 0x0094 }
4830+
}},
4831+
{ 0x3c, 15, {
4832+
{ 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
4833+
{ 0x201b, 0x0001 }, { 0x201d, 0x0001 }, { 0x201f, 0x00fe },
4834+
{ 0x2021, 0x0000 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
4835+
{ 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
4836+
{ 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x23ba, 0x008d }
4837+
}},
4838+
{ 0x3d, 15, {
4839+
{ 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
4840+
{ 0x201b, 0x0002 }, { 0x201d, 0x0002 }, { 0x201f, 0x00fd },
4841+
{ 0x2021, 0x0001 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
4842+
{ 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
4843+
{ 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x23ba, 0x008d }
4844+
}}
4845+
};
4846+
4847+
static void alc298_samsung_v2_enable_amps(struct hda_codec *codec)
4848+
{
4849+
struct alc_spec *spec = codec->spec;
4850+
static const unsigned short enable_seq[][2] = {
4851+
{ 0x203a, 0x0081 }, { 0x23ff, 0x0001 },
4852+
};
4853+
int i, j;
4854+
4855+
for (i = 0; i < spec->num_speaker_amps; i++) {
4856+
alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
4857+
for (j = 0; j < ARRAY_SIZE(enable_seq); j++)
4858+
alc298_samsung_write_coef_pack(codec, enable_seq[j]);
4859+
codec_dbg(codec, "alc298_samsung_v2: Enabled speaker amp 0x%02x\n",
4860+
alc298_samsung_v2_amp_desc_tbl[i].nid);
4861+
}
4862+
}
4863+
4864+
static void alc298_samsung_v2_disable_amps(struct hda_codec *codec)
4865+
{
4866+
struct alc_spec *spec = codec->spec;
4867+
static const unsigned short disable_seq[][2] = {
4868+
{ 0x23ff, 0x0000 }, { 0x203a, 0x0080 },
4869+
};
4870+
int i, j;
4871+
4872+
for (i = 0; i < spec->num_speaker_amps; i++) {
4873+
alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
4874+
for (j = 0; j < ARRAY_SIZE(disable_seq); j++)
4875+
alc298_samsung_write_coef_pack(codec, disable_seq[j]);
4876+
codec_dbg(codec, "alc298_samsung_v2: Disabled speaker amp 0x%02x\n",
4877+
alc298_samsung_v2_amp_desc_tbl[i].nid);
4878+
}
4879+
}
4880+
4881+
static void alc298_samsung_v2_playback_hook(struct hda_pcm_stream *hinfo,
4882+
struct hda_codec *codec,
4883+
struct snd_pcm_substream *substream,
4884+
int action)
4885+
{
4886+
/* Dynamically enable/disable speaker amps before and after playback */
4887+
if (action == HDA_GEN_PCM_ACT_OPEN)
4888+
alc298_samsung_v2_enable_amps(codec);
4889+
if (action == HDA_GEN_PCM_ACT_CLOSE)
4890+
alc298_samsung_v2_disable_amps(codec);
4891+
}
4892+
4893+
static void alc298_samsung_v2_init_amps(struct hda_codec *codec,
4894+
int num_speaker_amps)
4895+
{
4896+
struct alc_spec *spec = codec->spec;
4897+
int i, j;
4898+
4899+
/* Set spec's num_speaker_amps before doing anything else */
4900+
spec->num_speaker_amps = num_speaker_amps;
4901+
4902+
/* Disable speaker amps before init to prevent any physical damage */
4903+
alc298_samsung_v2_disable_amps(codec);
4904+
4905+
/* Initialize the speaker amps */
4906+
for (i = 0; i < spec->num_speaker_amps; i++) {
4907+
alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
4908+
for (j = 0; j < alc298_samsung_v2_amp_desc_tbl[i].init_seq_size; j++) {
4909+
alc298_samsung_write_coef_pack(codec,
4910+
alc298_samsung_v2_amp_desc_tbl[i].init_seq[j]);
4911+
}
4912+
alc_write_coef_idx(codec, 0x89, 0x0);
4913+
codec_dbg(codec, "alc298_samsung_v2: Initialized speaker amp 0x%02x\n",
4914+
alc298_samsung_v2_amp_desc_tbl[i].nid);
4915+
}
4916+
4917+
/* register hook to enable speaker amps only when they are needed */
4918+
spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook;
4919+
}
4920+
4921+
static void alc298_fixup_samsung_amp_v2_2_amps(struct hda_codec *codec,
4922+
const struct hda_fixup *fix, int action)
4923+
{
4924+
if (action == HDA_FIXUP_ACT_PROBE)
4925+
alc298_samsung_v2_init_amps(codec, 2);
4926+
}
4927+
4928+
static void alc298_fixup_samsung_amp_v2_4_amps(struct hda_codec *codec,
4929+
const struct hda_fixup *fix, int action)
4930+
{
4931+
if (action == HDA_FIXUP_ACT_PROBE)
4932+
alc298_samsung_v2_init_amps(codec, 4);
4933+
}
48074934

48084935
#if IS_REACHABLE(CONFIG_INPUT)
48094936
static void gpio2_mic_hotkey_event(struct hda_codec *codec,
@@ -7541,7 +7668,8 @@ enum {
75417668
ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
75427669
ALC236_FIXUP_LENOVO_INV_DMIC,
75437670
ALC298_FIXUP_SAMSUNG_AMP,
7544-
ALC298_FIXUP_SAMSUNG_AMP2,
7671+
ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS,
7672+
ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS,
75457673
ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
75467674
ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
75477675
ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
@@ -9176,9 +9304,13 @@ static const struct hda_fixup alc269_fixups[] = {
91769304
.chained = true,
91779305
.chain_id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET
91789306
},
9179-
[ALC298_FIXUP_SAMSUNG_AMP2] = {
9307+
[ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS] = {
9308+
.type = HDA_FIXUP_FUNC,
9309+
.v.func = alc298_fixup_samsung_amp_v2_2_amps
9310+
},
9311+
[ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS] = {
91809312
.type = HDA_FIXUP_FUNC,
9181-
.v.func = alc298_fixup_samsung_amp2
9313+
.v.func = alc298_fixup_samsung_amp_v2_4_amps
91829314
},
91839315
[ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
91849316
.type = HDA_FIXUP_VERBS,
@@ -10558,8 +10690,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
1055810690
SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
1055910691
SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP),
1056010692
SND_PCI_QUIRK(0x144d, 0xc868, "Samsung Galaxy Book2 Pro (NP930XED)", ALC298_FIXUP_SAMSUNG_AMP),
10561-
SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG-KB1US)", ALC298_FIXUP_SAMSUNG_AMP2),
10562-
SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH-XD92G))", ALC298_FIXUP_SAMSUNG_AMP2),
10693+
SND_PCI_QUIRK(0x144d, 0xc870, "Samsung Galaxy Book2 Pro (NP950XED)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
10694+
SND_PCI_QUIRK(0x144d, 0xc886, "Samsung Galaxy Book3 Pro (NP964XFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
10695+
SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
10696+
SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
1056310697
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
1056410698
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
1056510699
SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
@@ -10790,6 +10924,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
1079010924
SND_PCI_QUIRK(0x1849, 0xa233, "Positivo Master C6300", ALC269_FIXUP_HEADSET_MIC),
1079110925
SND_PCI_QUIRK(0x1854, 0x0440, "LG CQ6", ALC256_FIXUP_HEADPHONE_AMP_VOL),
1079210926
SND_PCI_QUIRK(0x1854, 0x0441, "LG CQ6 AIO", ALC256_FIXUP_HEADPHONE_AMP_VOL),
10927+
SND_PCI_QUIRK(0x1854, 0x0488, "LG gram 16 (16Z90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
10928+
SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
1079310929
SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
1079410930
SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
1079510931
SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
@@ -11000,7 +11136,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
1100011136
{.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
1100111137
{.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
1100211138
{.id = ALC298_FIXUP_SAMSUNG_AMP, .name = "alc298-samsung-amp"},
11003-
{.id = ALC298_FIXUP_SAMSUNG_AMP2, .name = "alc298-samsung-amp2"},
11139+
{.id = ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS, .name = "alc298-samsung-amp-v2-2-amps"},
11140+
{.id = ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS, .name = "alc298-samsung-amp-v2-4-amps"},
1100411141
{.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
1100511142
{.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
1100611143
{.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},

0 commit comments

Comments
 (0)