diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 39 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 7 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 2 |
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 | ||
1277 | static unsigned int hda_set_power_state(struct hda_codec *codec, | 1277 | static unsigned int hda_set_power_state(struct hda_codec *codec, |
1278 | unsigned int power_state); | 1278 | unsigned int power_state); |
1279 | static 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) | |||
3649 | EXPORT_SYMBOL_HDA(snd_hda_codec_flush_cache); | 3652 | EXPORT_SYMBOL_HDA(snd_hda_codec_flush_cache); |
3650 | 3653 | ||
3651 | void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, | 3654 | void 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 | } |
3677 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); | 3674 | 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, | |||
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 */ | ||
3719 | static 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[]; | |||
1047 | void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); | 1051 | void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); |
1048 | void snd_hda_bus_reboot_notify(struct hda_bus *bus); | 1052 | void snd_hda_bus_reboot_notify(struct hda_bus *bus); |
1049 | void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, | 1053 | void 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 | ||
1053 | int snd_hda_lock_devices(struct hda_bus *bus); | 1056 | int snd_hda_lock_devices(struct hda_bus *bus); |
1054 | void snd_hda_unlock_devices(struct hda_bus *bus); | 1057 | void 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 | ||
441 | static int conexant_init(struct hda_codec *codec) | 441 | static 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 |