Skip to content

Commit 7e4d4b3

Browse files
joshuagrishamtiwai
authored andcommitted
ALSA: hda/realtek: Refactor and simplify Samsung Galaxy Book init
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]>
1 parent fc09ea5 commit 7e4d4b3

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;
@@ -4813,7 +4814,133 @@ static void alc298_fixup_samsung_amp(struct hda_codec *codec,
48134814
}
48144815
}
48154816

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

48184945
#if IS_REACHABLE(CONFIG_INPUT)
48194946
static void gpio2_mic_hotkey_event(struct hda_codec *codec,
@@ -7514,7 +7641,8 @@ enum {
75147641
ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
75157642
ALC236_FIXUP_LENOVO_INV_DMIC,
75167643
ALC298_FIXUP_SAMSUNG_AMP,
7517-
ALC298_FIXUP_SAMSUNG_AMP2,
7644+
ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS,
7645+
ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS,
75187646
ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
75197647
ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
75207648
ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
@@ -9151,9 +9279,13 @@ static const struct hda_fixup alc269_fixups[] = {
91519279
.chained = true,
91529280
.chain_id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET
91539281
},
9154-
[ALC298_FIXUP_SAMSUNG_AMP2] = {
9282+
[ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS] = {
9283+
.type = HDA_FIXUP_FUNC,
9284+
.v.func = alc298_fixup_samsung_amp_v2_2_amps
9285+
},
9286+
[ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS] = {
91559287
.type = HDA_FIXUP_FUNC,
9156-
.v.func = alc298_fixup_samsung_amp2
9288+
.v.func = alc298_fixup_samsung_amp_v2_4_amps
91579289
},
91589290
[ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
91599291
.type = HDA_FIXUP_VERBS,
@@ -10506,8 +10638,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
1050610638
SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
1050710639
SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP),
1050810640
SND_PCI_QUIRK(0x144d, 0xc868, "Samsung Galaxy Book2 Pro (NP930XED)", ALC298_FIXUP_SAMSUNG_AMP),
10509-
SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG-KB1US)", ALC298_FIXUP_SAMSUNG_AMP2),
10510-
SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH-XD92G))", ALC298_FIXUP_SAMSUNG_AMP2),
10641+
SND_PCI_QUIRK(0x144d, 0xc870, "Samsung Galaxy Book2 Pro (NP950XED)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
10642+
SND_PCI_QUIRK(0x144d, 0xc886, "Samsung Galaxy Book3 Pro (NP964XFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
10643+
SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
10644+
SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
1051110645
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
1051210646
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
1051310647
SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
@@ -10739,6 +10873,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
1073910873
SND_PCI_QUIRK(0x1849, 0xa233, "Positivo Master C6300", ALC269_FIXUP_HEADSET_MIC),
1074010874
SND_PCI_QUIRK(0x1854, 0x0440, "LG CQ6", ALC256_FIXUP_HEADPHONE_AMP_VOL),
1074110875
SND_PCI_QUIRK(0x1854, 0x0441, "LG CQ6 AIO", ALC256_FIXUP_HEADPHONE_AMP_VOL),
10876+
SND_PCI_QUIRK(0x1854, 0x0488, "LG gram 16 (16Z90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
10877+
SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
1074210878
SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
1074310879
SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
1074410880
SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
@@ -10949,7 +11085,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
1094911085
{.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
1095011086
{.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
1095111087
{.id = ALC298_FIXUP_SAMSUNG_AMP, .name = "alc298-samsung-amp"},
10952-
{.id = ALC298_FIXUP_SAMSUNG_AMP2, .name = "alc298-samsung-amp2"},
11088+
{.id = ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS, .name = "alc298-samsung-amp-v2-2-amps"},
11089+
{.id = ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS, .name = "alc298-samsung-amp-v2-4-amps"},
1095311090
{.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
1095411091
{.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
1095511092
{.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},

0 commit comments

Comments
 (0)