[ALSA] hda-codec - Check PINCAP only for PIN widgets
authorTakashi Iwai <tiwai@suse.de>
Wed, 14 Nov 2007 13:53:42 +0000 (14:53 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 19 Nov 2007 17:38:32 +0000 (18:38 +0100)
The recent addition of checking PINCAP for EAPD seems to break some
systems due to unexpected response from the codec chip.  We shouldn't
issue GET_PINCAP verb to non-PIN widgets.  Now checks the widget type
before checking EAPD bit.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
sound/pci/hda/hda_codec.c

index b52f56ffedf48a519fe8433eeb9346190b3be2d7..8cbe3bf1e3170afb798fad92beb5579378877459 100644 (file)
@@ -1625,19 +1625,26 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
 
        nid = codec->start_nid;
        for (i = 0; i < codec->num_nodes; i++, nid++) {
-               if (get_wcaps(codec, nid) & AC_WCAP_POWER) {
-                       unsigned int pincap;
-                       /*
-                        * don't power down the widget if it controls eapd
-                        * and EAPD_BTLENABLE is set.
-                        */
-                       pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-                       if (pincap & AC_PINCAP_EAPD) {
-                               int eapd = snd_hda_codec_read(codec, nid,
-                                       0, AC_VERB_GET_EAPD_BTLENABLE, 0);
-                               eapd &= 0x02;
-                               if (power_state == AC_PWRST_D3 && eapd)
-                                       continue;
+               unsigned int wcaps = get_wcaps(codec, nid);
+               if (wcaps & AC_WCAP_POWER) {
+                       unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
+                               AC_WCAP_TYPE_SHIFT;
+                       if (wid_type == AC_WID_PIN) {
+                               unsigned int pincap;
+                               /*
+                                * don't power down the widget if it controls
+                                * eapd and EAPD_BTLENABLE is set.
+                                */
+                               pincap = snd_hda_param_read(codec, nid,
+                                                           AC_PAR_PIN_CAP);
+                               if (pincap & AC_PINCAP_EAPD) {
+                                       int eapd = snd_hda_codec_read(codec,
+                                               nid, 0,
+                                               AC_VERB_GET_EAPD_BTLENABLE, 0);
+                                       eapd &= 0x02;
+                                       if (power_state == AC_PWRST_D3 && eapd)
+                                               continue;
+                               }
                        }
                        snd_hda_codec_write(codec, nid, 0,
                                            AC_VERB_SET_POWER_STATE,