Skip to content

Commit d3dca02

Browse files
Lucas Tanuretiwai
authored andcommitted
ALSA: hda/realtek: Add support for Legion 7 16ACHg6 laptop
Add Support for CS35L41 using the component binding method [ corrected the quirk entry position by tiwai ] Signed-off-by: Lucas Tanure <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 7b2f3eb commit d3dca02

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

sound/pci/hda/patch_realtek.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "hda_auto_parser.h"
2626
#include "hda_jack.h"
2727
#include "hda_generic.h"
28+
#include "hda_component.h"
2829

2930
/* keep halting ALC5505 DSP, for power saving */
3031
#define HALT_REALTEK_ALC5505
@@ -126,6 +127,10 @@ struct alc_spec {
126127
unsigned int coef0;
127128
struct input_dev *kb_dev;
128129
u8 alc_mute_keycode_map[1];
130+
131+
/* component binding */
132+
struct component_match *match;
133+
struct hda_component comps[HDA_MAX_COMPONENTS];
129134
};
130135

131136
/*
@@ -6525,6 +6530,102 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
65256530
}
65266531
}
65276532

6533+
static int comp_match_dev_name(struct device *dev, void *data)
6534+
{
6535+
return strcmp(dev_name(dev), data) == 0;
6536+
}
6537+
6538+
static int find_comp_by_dev_name(struct alc_spec *spec, const char *name)
6539+
{
6540+
int i;
6541+
6542+
for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
6543+
if (strcmp(spec->comps[i].name, name) == 0)
6544+
return i;
6545+
}
6546+
6547+
return -ENODEV;
6548+
}
6549+
6550+
static int comp_bind(struct device *dev)
6551+
{
6552+
struct hda_codec *cdc = dev_to_hda_codec(dev);
6553+
struct alc_spec *spec = cdc->spec;
6554+
6555+
return component_bind_all(dev, spec->comps);
6556+
}
6557+
6558+
static void comp_unbind(struct device *dev)
6559+
{
6560+
struct hda_codec *cdc = dev_to_hda_codec(dev);
6561+
struct alc_spec *spec = cdc->spec;
6562+
6563+
component_unbind_all(dev, spec->comps);
6564+
}
6565+
6566+
static const struct component_master_ops comp_master_ops = {
6567+
.bind = comp_bind,
6568+
.unbind = comp_unbind,
6569+
};
6570+
6571+
static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
6572+
struct snd_pcm_substream *sub, int action)
6573+
{
6574+
struct alc_spec *spec = cdc->spec;
6575+
int i;
6576+
6577+
for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
6578+
if (spec->comps[i].dev)
6579+
spec->comps[i].playback_hook(spec->comps[i].dev, action);
6580+
}
6581+
}
6582+
6583+
static void alc287_legion_16achg6_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
6584+
struct snd_pcm_substream *sub, int action)
6585+
{
6586+
struct alc_spec *spec = cdc->spec;
6587+
unsigned int rx_slot;
6588+
int i;
6589+
6590+
switch (action) {
6591+
case HDA_GEN_PCM_ACT_PREPARE:
6592+
rx_slot = 0;
6593+
i = find_comp_by_dev_name(spec, "i2c-CLSA0100:00-cs35l41-hda.0");
6594+
if (i >= 0)
6595+
spec->comps[i].set_channel_map(spec->comps[i].dev, 0, NULL, 1, &rx_slot);
6596+
6597+
rx_slot = 1;
6598+
i = find_comp_by_dev_name(spec, "i2c-CLSA0100:00-cs35l41-hda.1");
6599+
if (i >= 0)
6600+
spec->comps[i].set_channel_map(spec->comps[i].dev, 0, NULL, 1, &rx_slot);
6601+
break;
6602+
}
6603+
6604+
comp_generic_playback_hook(hinfo, cdc, sub, action);
6605+
}
6606+
6607+
static void alc287_fixup_legion_16achg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix,
6608+
int action)
6609+
{
6610+
struct device *dev = hda_codec_dev(cdc);
6611+
struct alc_spec *spec = cdc->spec;
6612+
int ret;
6613+
6614+
switch (action) {
6615+
case HDA_FIXUP_ACT_PRE_PROBE:
6616+
component_match_add(dev, &spec->match, comp_match_dev_name,
6617+
"i2c-CLSA0100:00-cs35l41-hda.0");
6618+
component_match_add(dev, &spec->match, comp_match_dev_name,
6619+
"i2c-CLSA0100:00-cs35l41-hda.1");
6620+
ret = component_master_add_with_match(dev, &comp_master_ops, spec->match);
6621+
if (ret)
6622+
codec_err(cdc, "Fail to register component aggregator %d\n", ret);
6623+
else
6624+
spec->gen.pcm_playback_hook = alc287_legion_16achg6_playback_hook;
6625+
break;
6626+
}
6627+
}
6628+
65286629
/* for alc295_fixup_hp_top_speakers */
65296630
#include "hp_x360_helper.c"
65306631

@@ -6814,6 +6915,7 @@ enum {
68146915
ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME,
68156916
ALC285_FIXUP_LEGION_Y9000X_SPEAKERS,
68166917
ALC285_FIXUP_LEGION_Y9000X_AUTOMUTE,
6918+
ALC287_FIXUP_LEGION_16ACHG6,
68176919
};
68186920

68196921
static const struct hda_fixup alc269_fixups[] = {
@@ -8556,6 +8658,10 @@ static const struct hda_fixup alc269_fixups[] = {
85568658
.chained = true,
85578659
.chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
85588660
},
8661+
[ALC287_FIXUP_LEGION_16ACHG6] = {
8662+
.type = HDA_FIXUP_FUNC,
8663+
.v.func = alc287_fixup_legion_16achg6_speakers,
8664+
},
85598665
};
85608666

85618667
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -8970,6 +9076,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
89709076
SND_PCI_QUIRK(0x17aa, 0x3824, "Legion Y9000X 2020", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS),
89719077
SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
89729078
SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP),
9079+
SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6),
89739080
SND_PCI_QUIRK(0x17aa, 0x384a, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
89749081
SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
89759082
SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),

0 commit comments

Comments
 (0)