From 1e24881d8b2a7c198a67fe9e5179e9efb2140df7 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Wed, 27 Jul 2022 10:59:22 +0100 Subject: [PATCH] ALSA: hda: cs35l41: Support CLSA0101 Add support for Intel version of Legion 7 laptop. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20220727095924.80884-3-tanureal@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda.c | 66 +++++++++++++++++++++++++---------------- sound/pci/hda/cs35l41_hda_i2c.c | 3 ++ sound/pci/hda/patch_realtek.c | 12 ++++++++ 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 9af5e2e..129bffb 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -1133,6 +1133,45 @@ static int cs35l41_get_speaker_id(struct device *dev, int amp_index, return speaker_id; } +/* + * Device CLSA010(0/1) doesn't have _DSD so a gpiod_get by the label reset won't work. + * And devices created by serial-multi-instantiate don't have their device struct + * pointing to the correct fwnode, so acpi_dev must be used here. + * And devm functions expect that the device requesting the resource has the correct + * fwnode. + */ +static int cs35l41_no_acpi_dsd(struct cs35l41_hda *cs35l41, struct device *physdev, int id, + const char *hid) +{ + struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; + + /* check I2C address to assign the index */ + cs35l41->index = id == 0x40 ? 0 : 1; + cs35l41->channel_index = 0; + cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); + cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2); + hw_cfg->spk_pos = cs35l41->index; + hw_cfg->gpio2.func = CS35L41_INTERRUPT; + hw_cfg->gpio2.valid = true; + hw_cfg->valid = true; + put_device(physdev); + + if (strncmp(hid, "CLSA0100", 8) == 0) { + hw_cfg->bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH; + } else if (strncmp(hid, "CLSA0101", 8) == 0) { + hw_cfg->bst_type = CS35L41_EXT_BOOST; + hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH; + hw_cfg->gpio1.valid = true; + } else { + hw_cfg->valid = false; + hw_cfg->gpio1.valid = false; + hw_cfg->gpio2.valid = false; + return -EINVAL; + } + + return 0; +} + static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id) { struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; @@ -1161,7 +1200,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i property = "cirrus,dev-index"; ret = device_property_count_u32(physdev, property); if (ret <= 0) - goto no_acpi_dsd; + return cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid); if (ret > ARRAY_SIZE(values)) { ret = -EINVAL; @@ -1255,31 +1294,6 @@ err: dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret); return ret; - -no_acpi_dsd: - /* - * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work. - * And devices created by serial-multi-instantiate don't have their device struct - * pointing to the correct fwnode, so acpi_dev must be used here. - * And devm functions expect that the device requesting the resource has the correct - * fwnode. - */ - if (strncmp(hid, "CLSA0100", 8) != 0) - return -EINVAL; - - /* check I2C address to assign the index */ - cs35l41->index = id == 0x40 ? 0 : 1; - cs35l41->hw_cfg.spk_pos = cs35l41->index; - cs35l41->channel_index = 0; - cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); - cs35l41->hw_cfg.bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH; - cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2); - hw_cfg->gpio2.func = CS35L41_INTERRUPT; - hw_cfg->gpio2.valid = true; - cs35l41->hw_cfg.valid = true; - put_device(physdev); - - return 0; } int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq, diff --git a/sound/pci/hda/cs35l41_hda_i2c.c b/sound/pci/hda/cs35l41_hda_i2c.c index 9c08fa0..5baacfd 100644 --- a/sound/pci/hda/cs35l41_hda_i2c.c +++ b/sound/pci/hda/cs35l41_hda_i2c.c @@ -22,6 +22,8 @@ static int cs35l41_hda_i2c_probe(struct i2c_client *clt, const struct i2c_device */ if (strstr(dev_name(&clt->dev), "CLSA0100")) device_name = "CLSA0100"; + else if (strstr(dev_name(&clt->dev), "CLSA0101")) + device_name = "CLSA0101"; else if (strstr(dev_name(&clt->dev), "CSC3551")) device_name = "CSC3551"; else @@ -45,6 +47,7 @@ static const struct i2c_device_id cs35l41_hda_i2c_id[] = { static const struct acpi_device_id cs35l41_acpi_hda_match[] = { {"CLSA0100", 0 }, + {"CLSA0101", 0 }, {"CSC3551", 0 }, {} }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 06bb553..e1fbda2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6710,6 +6710,12 @@ static void alc287_fixup_legion_16achg6_speakers(struct hda_codec *cdc, const st cs35l41_generic_fixup(cdc, action, "i2c", "CLSA0100", 2); } +static void alc287_fixup_legion_16ithg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix, + int action) +{ + cs35l41_generic_fixup(cdc, action, "i2c", "CLSA0101", 2); +} + /* for alc295_fixup_hp_top_speakers */ #include "hp_x360_helper.c" @@ -7047,6 +7053,7 @@ enum { ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED, ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED, ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE, + ALC287_FIXUP_LEGION_16ITHG6, }; /* A special fixup for Lenovo C940 and Yoga Duet 7; @@ -8889,6 +8896,10 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC }, + [ALC287_FIXUP_LEGION_16ITHG6] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc287_fixup_legion_16ithg6_speakers, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -9355,6 +9366,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x384a, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), + SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), -- 2.7.4