diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e4e0501ab84a..19ff923b2431 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1276,6 +1276,8 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, static unsigned int hda_set_power_state(struct hda_codec *codec, unsigned int power_state); +static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid, + unsigned int power_state); /** * snd_hda_codec_new - create a HDA codec @@ -1396,6 +1398,7 @@ int snd_hda_codec_new(struct hda_bus *bus, #endif codec->epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); + codec->power_filter = default_power_filter; /* power-up all before initialization */ hda_set_power_state(codec, AC_PWRST_D0); @@ -3649,29 +3652,23 @@ void snd_hda_codec_flush_cache(struct hda_codec *codec) EXPORT_SYMBOL_HDA(snd_hda_codec_flush_cache); void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, - unsigned int power_state, - bool eapd_workaround) + unsigned int power_state) { hda_nid_t nid = codec->start_nid; int i; for (i = 0; i < codec->num_nodes; i++, nid++) { unsigned int wcaps = get_wcaps(codec, nid); + unsigned int state = power_state; if (!(wcaps & AC_WCAP_POWER)) continue; - /* don't power down the widget if it controls eapd and - * EAPD_BTLENABLE is set. - */ - if (eapd_workaround && power_state == AC_PWRST_D3 && - get_wcaps_type(wcaps) == AC_WID_PIN && - (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) { - int eapd = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_EAPD_BTLENABLE, 0); - if (eapd & 0x02) + if (codec->power_filter) { + state = codec->power_filter(codec, nid, power_state); + if (state != power_state && power_state == AC_PWRST_D3) continue; } snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, - power_state); + state); } } EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); @@ -3718,6 +3715,21 @@ static unsigned int hda_sync_power_state(struct hda_codec *codec, return state; } +/* don't power down the widget if it controls eapd and EAPD_BTLENABLE is set */ +static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid, + unsigned int power_state) +{ + if (power_state == AC_PWRST_D3 && + get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN && + (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) { + int eapd = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_EAPD_BTLENABLE, 0); + if (eapd & 0x02) + return AC_PWRST_D0; + } + return power_state; +} + /* * set power state of the codec, and return the power state */ @@ -3743,8 +3755,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec, snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state); - snd_hda_codec_set_power_to_all(codec, fg, power_state, - true); + snd_hda_codec_set_power_to_all(codec, fg, power_state); } state = hda_sync_power_state(codec, fg, power_state); if (!(state & AC_PWRST_ERROR)) |