浏览代码

[ALSA] hda-codec - Check PINCAP only for PIN widgets

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>
Takashi Iwai 17 年之前
父节点
当前提交
7eba5c9dc3
共有 1 个文件被更改,包括 20 次插入13 次删除
  1. 20 13
      sound/pci/hda/hda_codec.c

+ 20 - 13
sound/pci/hda/hda_codec.c

@@ -1625,19 +1625,26 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
 
 
 	nid = codec->start_nid;
 	nid = codec->start_nid;
 	for (i = 0; i < codec->num_nodes; i++, 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,
 			snd_hda_codec_write(codec, nid, 0,
 					    AC_VERB_SET_POWER_STATE,
 					    AC_VERB_SET_POWER_STATE,