aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_codec.c39
-rw-r--r--sound/pci/hda/hda_codec.h7
-rw-r--r--sound/pci/hda/patch_conexant.c2
-rw-r--r--sound/pci/hda/patch_sigmatel.c2
4 files changed, 32 insertions, 18 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,
1276 1276
1277static unsigned int hda_set_power_state(struct hda_codec *codec, 1277static unsigned int hda_set_power_state(struct hda_codec *codec,
1278 unsigned int power_state); 1278 unsigned int power_state);
1279static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
1280 unsigned int power_state);
1279 1281
1280/** 1282/**
1281 * snd_hda_codec_new - create a HDA codec 1283 * snd_hda_codec_new - create a HDA codec
@@ -1396,6 +1398,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
1396#endif 1398#endif
1397 codec->epss = snd_hda_codec_get_supported_ps(codec, fg, 1399 codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
1398 AC_PWRST_EPSS); 1400 AC_PWRST_EPSS);
1401 codec->power_filter = default_power_filter;
1399 1402
1400 /* power-up all before initialization */ 1403 /* power-up all before initialization */
1401 hda_set_power_state(codec, AC_PWRST_D0); 1404 hda_set_power_state(codec, AC_PWRST_D0);
@@ -3649,29 +3652,23 @@ void snd_hda_codec_flush_cache(struct hda_codec *codec)
3649EXPORT_SYMBOL_HDA(snd_hda_codec_flush_cache); 3652EXPORT_SYMBOL_HDA(snd_hda_codec_flush_cache);
3650 3653
3651void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, 3654void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
3652 unsigned int power_state, 3655 unsigned int power_state)
3653 bool eapd_workaround)
3654{ 3656{
3655 hda_nid_t nid = codec->start_nid; 3657 hda_nid_t nid = codec->start_nid;
3656 int i; 3658 int i;
3657 3659
3658 for (i = 0; i < codec->num_nodes; i++, nid++) { 3660 for (i = 0; i < codec->num_nodes; i++, nid++) {
3659 unsigned int wcaps = get_wcaps(codec, nid); 3661 unsigned int wcaps = get_wcaps(codec, nid);
3662 unsigned int state = power_state;
3660 if (!(wcaps & AC_WCAP_POWER)) 3663 if (!(wcaps & AC_WCAP_POWER))
3661 continue; 3664 continue;
3662 /* don't power down the widget if it controls eapd and 3665 if (codec->power_filter) {
3663 * EAPD_BTLENABLE is set. 3666 state = codec->power_filter(codec, nid, power_state);
3664 */ 3667 if (state != power_state && power_state == AC_PWRST_D3)
3665 if (eapd_workaround && power_state == AC_PWRST_D3 &&
3666 get_wcaps_type(wcaps) == AC_WID_PIN &&
3667 (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
3668 int eapd = snd_hda_codec_read(codec, nid, 0,
3669 AC_VERB_GET_EAPD_BTLENABLE, 0);
3670 if (eapd & 0x02)
3671 continue; 3668 continue;
3672 } 3669 }
3673 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, 3670 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
3674 power_state); 3671 state);
3675 } 3672 }
3676} 3673}
3677EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); 3674EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all);
@@ -3718,6 +3715,21 @@ static unsigned int hda_sync_power_state(struct hda_codec *codec,
3718 return state; 3715 return state;
3719} 3716}
3720 3717
3718/* don't power down the widget if it controls eapd and EAPD_BTLENABLE is set */
3719static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
3720 unsigned int power_state)
3721{
3722 if (power_state == AC_PWRST_D3 &&
3723 get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
3724 (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
3725 int eapd = snd_hda_codec_read(codec, nid, 0,
3726 AC_VERB_GET_EAPD_BTLENABLE, 0);
3727 if (eapd & 0x02)
3728 return AC_PWRST_D0;
3729 }
3730 return power_state;
3731}
3732
3721/* 3733/*
3722 * set power state of the codec, and return the power state 3734 * set power state of the codec, and return the power state
3723 */ 3735 */
@@ -3743,8 +3755,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
3743 snd_hda_codec_read(codec, fg, 0, 3755 snd_hda_codec_read(codec, fg, 0,
3744 AC_VERB_SET_POWER_STATE, 3756 AC_VERB_SET_POWER_STATE,
3745 power_state); 3757 power_state);
3746 snd_hda_codec_set_power_to_all(codec, fg, power_state, 3758 snd_hda_codec_set_power_to_all(codec, fg, power_state);
3747 true);
3748 } 3759 }
3749 state = hda_sync_power_state(codec, fg, power_state); 3760 state = hda_sync_power_state(codec, fg, power_state);
3750 if (!(state & AC_PWRST_ERROR)) 3761 if (!(state & AC_PWRST_ERROR))
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index cc73287341de..fbedcf3c9d0b 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -886,6 +886,10 @@ struct hda_codec {
886 spinlock_t power_lock; 886 spinlock_t power_lock;
887#endif 887#endif
888 888
889 /* filter the requested power state per nid */
890 unsigned int (*power_filter)(struct hda_codec *codec, hda_nid_t nid,
891 unsigned int power_state);
892
889 /* codec-specific additional proc output */ 893 /* codec-specific additional proc output */
890 void (*proc_widget_hook)(struct snd_info_buffer *buffer, 894 void (*proc_widget_hook)(struct snd_info_buffer *buffer,
891 struct hda_codec *codec, hda_nid_t nid); 895 struct hda_codec *codec, hda_nid_t nid);
@@ -1047,8 +1051,7 @@ extern const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[];
1047void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); 1051void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
1048void snd_hda_bus_reboot_notify(struct hda_bus *bus); 1052void snd_hda_bus_reboot_notify(struct hda_bus *bus);
1049void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, 1053void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
1050 unsigned int power_state, 1054 unsigned int power_state);
1051 bool eapd_workaround);
1052 1055
1053int snd_hda_lock_devices(struct hda_bus *bus); 1056int snd_hda_lock_devices(struct hda_bus *bus);
1054void snd_hda_unlock_devices(struct hda_bus *bus); 1057void snd_hda_unlock_devices(struct hda_bus *bus);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index d98d470b0f26..7d941ef54172 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -435,7 +435,7 @@ static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg,
435 /* partial workaround for "azx_get_response timeout" */ 435 /* partial workaround for "azx_get_response timeout" */
436 if (power_state == AC_PWRST_D0) 436 if (power_state == AC_PWRST_D0)
437 msleep(10); 437 msleep(10);
438 snd_hda_codec_set_power_to_all(codec, fg, power_state, true); 438 snd_hda_codec_set_power_to_all(codec, fg, power_state);
439} 439}
440 440
441static int conexant_init(struct hda_codec *codec) 441static int conexant_init(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 0aa0ceba0806..5895d8f9a546 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -3724,7 +3724,7 @@ static void stac_set_power_state(struct hda_codec *codec, hda_nid_t fg,
3724 } 3724 }
3725 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, 3725 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
3726 afg_power_state); 3726 afg_power_state);
3727 snd_hda_codec_set_power_to_all(codec, fg, power_state, true); 3727 snd_hda_codec_set_power_to_all(codec, fg, power_state);
3728} 3728}
3729#else 3729#else
3730#define stac_suspend NULL 3730#define stac_suspend NULL