Skip to content

Commit

Permalink
ALSA: hda/realtek: Apply fixup for Lenovo Yoga Duet 7 properly
Browse files Browse the repository at this point in the history
commit 56ec3e7 upstream.

It turned out that Lenovo shipped two completely different products
with the very same PCI SSID, where both require different quirks;
namely, Lenovo C940 has already the fixup for its speaker
(ALC298_FIXUP_LENOVO_SPK_VOLUME) with the PCI SSID 17aa:3818, while
Yoga Duet 7 has also the very same PCI SSID but requires a different
quirk, ALC287_FIXUP_YOGA7_14TIL_SPEAKERS.

Fortunately, both are with different codecs (C940 with ALC298 and Duet
7 with ALC287), hence we can apply different fixes by checking the
codec ID.  This patch implements that special fixup function.

For easier handling, the internal function for applying a specific
fixup entry is exported as __snd_hda_apply_fixup(), so that it can be
called from the codec driver.  The rest is simply calling it with a
different fixup ID depending on the codec ID.

Reported-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: nikitashvets@flyium.com
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/5ca147d1-3a2d-60c6-c491-8aa844183222@redhat.com
Link: https://lore.kernel.org/r/20220614054831.14648-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
tiwai authored and gregkh committed Jun 29, 2022
1 parent 7fcbc89 commit 8030745
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
7 changes: 4 additions & 3 deletions sound/pci/hda/hda_auto_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ static void set_pin_targets(struct hda_codec *codec,
snd_hda_set_pin_ctl_cache(codec, cfg->nid, cfg->val);
}

static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth)
{
const char *modelname = codec->fixup_name;

Expand All @@ -833,7 +833,7 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
if (++depth > 10)
break;
if (fix->chained_before)
apply_fixup(codec, fix->chain_id, action, depth + 1);
__snd_hda_apply_fixup(codec, fix->chain_id, action, depth + 1);

switch (fix->type) {
case HDA_FIXUP_PINS:
Expand Down Expand Up @@ -874,6 +874,7 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
id = fix->chain_id;
}
}
EXPORT_SYMBOL_GPL(__snd_hda_apply_fixup);

/**
* snd_hda_apply_fixup - Apply the fixup chain with the given action
Expand All @@ -883,7 +884,7 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
void snd_hda_apply_fixup(struct hda_codec *codec, int action)
{
if (codec->fixup_list)
apply_fixup(codec, codec->fixup_id, action, 0);
__snd_hda_apply_fixup(codec, codec->fixup_id, action, 0);
}
EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);

Expand Down
1 change: 1 addition & 0 deletions sound/pci/hda/hda_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ void snd_hda_apply_verbs(struct hda_codec *codec);
void snd_hda_apply_pincfgs(struct hda_codec *codec,
const struct hda_pintbl *cfg);
void snd_hda_apply_fixup(struct hda_codec *codec, int action);
void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth);
void snd_hda_pick_fixup(struct hda_codec *codec,
const struct hda_model_fixup *models,
const struct snd_pci_quirk *quirk,
Expand Down
24 changes: 23 additions & 1 deletion sound/pci/hda/patch_realtek.c
Original file line number Diff line number Diff line change
Expand Up @@ -6827,6 +6827,7 @@ enum {
ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS,
ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE,
ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
ALC298_FIXUP_LENOVO_C940_DUET7,
ALC287_FIXUP_13S_GEN2_SPEAKERS,
ALC256_FIXUP_SET_COEF_DEFAULTS,
ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
Expand All @@ -6836,6 +6837,23 @@ enum {
ALC285_FIXUP_LEGION_Y9000X_AUTOMUTE,
};

/* A special fixup for Lenovo C940 and Yoga Duet 7;
* both have the very same PCI SSID, and we need to apply different fixups
* depending on the codec ID
*/
static void alc298_fixup_lenovo_c940_duet7(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
int id;

if (codec->core.vendor_id == 0x10ec0298)
id = ALC298_FIXUP_LENOVO_SPK_VOLUME; /* C940 */
else
id = ALC287_FIXUP_YOGA7_14ITL_SPEAKERS; /* Duet 7 */
__snd_hda_apply_fixup(codec, id, action, 0);
}

static const struct hda_fixup alc269_fixups[] = {
[ALC269_FIXUP_GPIO2] = {
.type = HDA_FIXUP_FUNC,
Expand Down Expand Up @@ -8529,6 +8547,10 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE,
},
[ALC298_FIXUP_LENOVO_C940_DUET7] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc298_fixup_lenovo_c940_duet7,
},
[ALC287_FIXUP_13S_GEN2_SPEAKERS] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
Expand Down Expand Up @@ -8993,7 +9015,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x31af, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340),
SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo Yoga DuetITL 2021", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME),
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940 / Yoga Duet 7", ALC298_FIXUP_LENOVO_C940_DUET7),
SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3820, "Yoga Duet 7 13ITL6", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3824, "Legion Y9000X 2020", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS),
Expand Down

0 comments on commit 8030745

Please sign in to comment.