Commit 70a0976b authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Set codec to D3 at reboot/shutdown on Thinkpads

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=958439Reported-and-tested-by: default avatarBenjamin Poirier <bpoirier@suse.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 157f0b7f
...@@ -111,6 +111,7 @@ struct alc_spec { ...@@ -111,6 +111,7 @@ struct alc_spec {
void (*power_hook)(struct hda_codec *codec); void (*power_hook)(struct hda_codec *codec);
#endif #endif
void (*shutup)(struct hda_codec *codec); void (*shutup)(struct hda_codec *codec);
void (*reboot_notify)(struct hda_codec *codec);
int init_amp; int init_amp;
int codec_variant; /* flag for other variants */ int codec_variant; /* flag for other variants */
...@@ -773,6 +774,25 @@ static inline void alc_shutup(struct hda_codec *codec) ...@@ -773,6 +774,25 @@ static inline void alc_shutup(struct hda_codec *codec)
snd_hda_shutup_pins(codec); 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 #define alc_free snd_hda_gen_free
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -818,7 +838,7 @@ static const struct hda_codec_ops alc_patch_ops = { ...@@ -818,7 +838,7 @@ static const struct hda_codec_ops alc_patch_ops = {
.suspend = alc_suspend, .suspend = alc_suspend,
.check_power_status = snd_hda_gen_check_power_status, .check_power_status = snd_hda_gen_check_power_status,
#endif #endif
.reboot_notify = alc_shutup, .reboot_notify = alc_reboot_notify,
}; };
...@@ -4199,6 +4219,7 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec, ...@@ -4199,6 +4219,7 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) { if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->shutup = alc_no_shutup; /* reduce click noise */ 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; spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
codec->power_save_node = 0; /* avoid click noises */ codec->power_save_node = 0; /* avoid click noises */
snd_hda_apply_pincfgs(codec, pincfgs); snd_hda_apply_pincfgs(codec, pincfgs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment