From e14cce2e259af55798fa64d8d64a340b2bbb1ab8 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 11 Dec 2012 13:32:43 +0100 Subject: [PATCH] ALSA: hda - Fix clicking noise on Thinkpad T61/R61i The bug reporter reports that setting the speaker pin to D3 before turning off its pinctl fixes the clicking noise on powersave for Thinkpad T61. Thanks to c4pp4 for doing most of the work with this bug, including reporting and testing, and writing preliminary patches. BugLink: https://bugs.launchpad.net/bugs/886975 Signed-off-by: David Henningsson --- sound/pci/hda/patch_conexant.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index a3a2263..ffb8506 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -144,6 +144,7 @@ struct conexant_spec { unsigned int asus:1; unsigned int pin_eapd_ctrls:1; unsigned int fixup_stereo_dmic:1; + unsigned int d3_before_shutup:1; /* Needs speaker to go to D3 before pinctl */ unsigned int adc_switching:1; @@ -558,13 +559,22 @@ static int conexant_build_controls(struct hda_codec *codec) return 0; } -#ifdef CONFIG_PM static int conexant_suspend(struct hda_codec *codec) { + struct conexant_spec *spec = codec->spec; + + if (spec->d3_before_shutup) + snd_hda_codec_set_power_to_all(codec, codec->afg, AC_PWRST_D3, + false); snd_hda_shutup_pins(codec); return 0; } -#endif + +static void conexant_reboot_notify(struct hda_codec *codec) +{ + conexant_suspend(codec); +} + static const struct hda_codec_ops conexant_patch_ops = { .build_controls = conexant_build_controls, @@ -575,7 +585,7 @@ static const struct hda_codec_ops conexant_patch_ops = { #ifdef CONFIG_PM .suspend = conexant_suspend, #endif - .reboot_notify = snd_hda_shutup_pins, + .reboot_notify = conexant_reboot_notify, }; #ifdef CONFIG_SND_HDA_INPUT_BEEP @@ -4421,6 +4431,7 @@ enum { CXT_PINCFG_LEMOTE_A1205, CXT_FIXUP_STEREO_DMIC, CXT_FIXUP_INC_MIC_BOOST, + CXT_FIXUP_D3_BEFORE_SHUTUP, }; static void cxt_fixup_stereo_dmic(struct hda_codec *codec, @@ -4430,6 +4441,13 @@ static void cxt_fixup_stereo_dmic(struct hda_codec *codec, spec->fixup_stereo_dmic = 1; } +static void cxt_fixup_d3_before_shutup(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct conexant_spec *spec = codec->spec; + spec->d3_before_shutup = 1; +} + static void cxt5066_increase_mic_boost(struct hda_codec *codec, const struct hda_fixup *fix, int action) { @@ -4499,6 +4517,15 @@ static const struct hda_fixup cxt_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = cxt5066_increase_mic_boost, }, + [CXT_FIXUP_D3_BEFORE_SHUTUP] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_d3_before_shutup, + }, +}; + +static const struct snd_pci_quirk cxt5045_fixups[] = { + SND_PCI_QUIRK(0x17aa, 0x20ac, "Lenovo T61/R61i", CXT_FIXUP_D3_BEFORE_SHUTUP), + {} }; static const struct snd_pci_quirk cxt5051_fixups[] = { @@ -4553,6 +4580,7 @@ static int patch_conexant_auto(struct hda_codec *codec) switch (codec->vendor_id) { case 0x14f15045: codec->single_adc_amp = 1; + snd_hda_pick_fixup(codec, NULL, cxt5045_fixups, cxt_fixups); break; case 0x14f15051: add_cx5051_fake_mutes(codec); -- 1.7.9.5