| From 70a0976b0c0d90f4246d7e63359d796ec82b87d6 Mon Sep 17 00:00:00 2001 |
| From: Takashi Iwai <tiwai@suse.de> |
| Date: Tue, 15 Dec 2015 14:59:58 +0100 |
| Subject: ALSA: hda - Set codec to D3 at reboot/shutdown on Thinkpads |
| |
| From: Takashi Iwai <tiwai@suse.de> |
| |
| commit 70a0976b0c0d90f4246d7e63359d796ec82b87d6 upstream. |
| |
| Lenovo Thinkpads with Realtek codecs may still have some loud |
| crackling noises at reboot/shutdown even though a few previous fixes |
| have been applied. It's because the previous fix (disabling the |
| default shutup callback) takes effect only at transition of the codec |
| power state. Meanwhile, at reboot or shutdown, we don't take down the |
| codec power as default, thus it triggers the same problem unless the |
| codec is powered down casually by runtime PM. |
| |
| This patch tries to address the issue. It gives two things: |
| - implement the separate reboot_notify hook to struct alc_spec, and |
| call it optionally if defined. |
| - turn off the codec to D3 for Thinkpad models via this new callback |
| |
| Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=958439 |
| Reported-and-tested-by: Benjamin Poirier <bpoirier@suse.com> |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| sound/pci/hda/patch_realtek.c | 23 ++++++++++++++++++++++- |
| 1 file changed, 22 insertions(+), 1 deletion(-) |
| |
| --- a/sound/pci/hda/patch_realtek.c |
| +++ b/sound/pci/hda/patch_realtek.c |
| @@ -111,6 +111,7 @@ struct alc_spec { |
| void (*power_hook)(struct hda_codec *codec); |
| #endif |
| void (*shutup)(struct hda_codec *codec); |
| + void (*reboot_notify)(struct hda_codec *codec); |
| |
| int init_amp; |
| int codec_variant; /* flag for other variants */ |
| @@ -773,6 +774,25 @@ static inline void alc_shutup(struct hda |
| snd_hda_shutup_pins(codec); |
| } |
| |
| +static void alc_reboot_notify(struct hda_codec *codec) |
| +{ |
| + struct alc_spec *spec = codec->spec; |
| + |
| + if (spec && spec->reboot_notify) |
| + spec->reboot_notify(codec); |
| + else |
| + alc_shutup(codec); |
| +} |
| + |
| +/* power down codec to D3 at reboot/shutdown; set as reboot_notify ops */ |
| +static void alc_d3_at_reboot(struct hda_codec *codec) |
| +{ |
| + snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3); |
| + snd_hda_codec_write(codec, codec->core.afg, 0, |
| + AC_VERB_SET_POWER_STATE, AC_PWRST_D3); |
| + msleep(10); |
| +} |
| + |
| #define alc_free snd_hda_gen_free |
| |
| #ifdef CONFIG_PM |
| @@ -818,7 +838,7 @@ static const struct hda_codec_ops alc_pa |
| .suspend = alc_suspend, |
| .check_power_status = snd_hda_gen_check_power_status, |
| #endif |
| - .reboot_notify = alc_shutup, |
| + .reboot_notify = alc_reboot_notify, |
| }; |
| |
| |
| @@ -4209,6 +4229,7 @@ static void alc_fixup_tpt440_dock(struct |
| |
| if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
| spec->shutup = alc_no_shutup; /* reduce click noise */ |
| + spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */ |
| spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; |
| codec->power_save_node = 0; /* avoid click noises */ |
| snd_hda_apply_pincfgs(codec, pincfgs); |