ALSA: hda - Don't apply EAPD power filter as default
authorTakashi Iwai <tiwai@suse.de>
Wed, 13 Mar 2013 13:47:21 +0000 (14:47 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 13 Mar 2013 17:07:05 +0000 (18:07 +0100)
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>
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_sigmatel.c

index ea061b6c14f9e8333395fb2c2d2839c9f689639a..39a510699b86e3acd4db9b3ba28f157d97df13c6 100644 (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++) {
index 83b7486c8eff15c8ab5ec386baf9c534b6c02dc0..e0bf7534fa1f410c28986e5cb0d0be4ee03e1442 100644 (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
  */
index 941bf6c766ecf5f6ff2aa35e28e33563066c58ef..7d941ef54172b81058dd0d722f051459cab6e7d9 100644 (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;
index 83d5335ac348ee2c3b7a3f7e243f7d5ad8096045..d57c81e79edd314fe72ae6ef1d98a0d20a9c3fcc 100644 (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);