ALSA: hda - Don't apply EAPD power filter as default

So far, the driver doesn't power down the widget at going down to D3
when the widget node has an EAPD capability and EAPD is actually set
on all codecs unless codec->power_filter is set explicitly.
This caused a problem on some Conexant codecs, leading to click
noises, and we set it as NULL there.  But it is very unlikely that the
problem hits only these codecs.

Looking back at the development history, this workaround for EAPD was
introduced just for some laptops with STAC9200 codec, then we applied
it blindly for all.  Now, since it's revealed to have an ill effect,
we should disable this workaround per default and apply only for the
known requiring systems.

The EAPD workaround is implemented now as snd_hda_codec_eapd_power_filter(),
and this has to be set explicitly by the codec driver when needed.
As of now, only patch_stac9200() sets this one.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2013-03-13 14:47:21 +01:00
parent bce0d2a80e
commit ba615b86d6
4 changed files with 11 additions and 8 deletions

View file

@ -1296,8 +1296,6 @@ 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
@ -1418,7 +1416,6 @@ 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);
@ -3759,8 +3756,9 @@ static unsigned int hda_sync_power_state(struct hda_codec *codec,
}
/* 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)
unsigned int snd_hda_codec_eapd_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 &&
@ -3772,6 +3770,7 @@ static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid,
}
return power_state;
}
EXPORT_SYMBOL_HDA(snd_hda_codec_eapd_power_filter);
/*
* set power state of the codec, and return the power state
@ -3816,8 +3815,8 @@ static void sync_power_up_states(struct hda_codec *codec)
hda_nid_t nid = codec->start_nid;
int i;
/* don't care if no or standard filter is used */
if (!codec->power_filter || codec->power_filter == default_power_filter)
/* don't care if no filter is used */
if (!codec->power_filter)
return;
for (i = 0; i < codec->num_nodes; i++, nid++) {

View file

@ -670,6 +670,10 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
return (state != target_state);
}
unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
hda_nid_t nid,
unsigned int power_state);
/*
* AMP control callbacks
*/

View file

@ -3350,7 +3350,6 @@ static int patch_conexant_auto(struct hda_codec *codec)
switch (codec->vendor_id) {
case 0x14f15045:
codec->single_adc_amp = 1;
codec->power_filter = NULL; /* Needs speaker amp to D3 to avoid click */
break;
case 0x14f15047:
codec->pin_amp_workaround = 1;

View file

@ -3774,6 +3774,7 @@ static int patch_stac9200(struct hda_codec *codec)
spec->gen.own_eapd_ctl = 1;
codec->patch_ops = stac_patch_ops;
codec->power_filter = snd_hda_codec_eapd_power_filter;
snd_hda_add_verbs(codec, stac9200_eapd_init);