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
#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);
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);
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
*/
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))
spinlock_t power_lock;
#endif
+ /* filter the requested power state per nid */
+ unsigned int (*power_filter)(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int power_state);
+
/* codec-specific additional proc output */
void (*proc_widget_hook)(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid);
void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
void snd_hda_bus_reboot_notify(struct hda_bus *bus);
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);
int snd_hda_lock_devices(struct hda_bus *bus);
void snd_hda_unlock_devices(struct hda_bus *bus);