aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-02-08 17:10:04 -0500
committerTakashi Iwai <tiwai@suse.de>2013-02-08 06:23:48 -0500
commitc88d4e84e639df9a9640ecff71de2501a84d1f48 (patch)
tree612e79c48144f0e985312f0fec170bd35f12f74d /sound
parent1611a9c931e95fab871a33beba49cc9ea39bbba8 (diff)
ALSA: hda - Yet another fix for broken HSW HDMI pin connections
A Haswell test machine showed that the invalid connection list, but this time it has only a single pin on the codec, thus the former fixup code doesn't work as it assumes the three pins blindly. This patch splits the former fixup code to two parts: - Enable eDP 1.2 for Haswell codec - Fix the connection list of pins on Haswell codec; the converter list is recorded dynamically in hdmi_add_cvt(), and applied in hdmi_add_pin() Signed-off-by: Mengdong Lin <mengdong.lin@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_hdmi.c56
1 files changed, 37 insertions, 19 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 54243c4a4e9d..b9af281b2ba4 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -84,6 +84,7 @@ struct hdmi_spec_per_pin {
84struct hdmi_spec { 84struct hdmi_spec {
85 int num_cvts; 85 int num_cvts;
86 struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS]; 86 struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS];
87 hda_nid_t cvt_nids[MAX_HDMI_CVTS];
87 88
88 int num_pins; 89 int num_pins;
89 struct hdmi_spec_per_pin pins[MAX_HDMI_PINS]; 90 struct hdmi_spec_per_pin pins[MAX_HDMI_PINS];
@@ -1197,6 +1198,9 @@ static void hdmi_repoll_eld(struct work_struct *work)
1197 hdmi_present_sense(per_pin, per_pin->repoll_count); 1198 hdmi_present_sense(per_pin, per_pin->repoll_count);
1198} 1199}
1199 1200
1201static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
1202 hda_nid_t nid);
1203
1200static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) 1204static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
1201{ 1205{
1202 struct hdmi_spec *spec = codec->spec; 1206 struct hdmi_spec *spec = codec->spec;
@@ -1216,6 +1220,9 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
1216 if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS)) 1220 if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS))
1217 return -E2BIG; 1221 return -E2BIG;
1218 1222
1223 if (codec->vendor_id == 0x80862807)
1224 intel_haswell_fixup_connect_list(codec, pin_nid);
1225
1219 pin_idx = spec->num_pins; 1226 pin_idx = spec->num_pins;
1220 per_pin = &spec->pins[pin_idx]; 1227 per_pin = &spec->pins[pin_idx];
1221 1228
@@ -1263,7 +1270,7 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
1263 if (err < 0) 1270 if (err < 0)
1264 return err; 1271 return err;
1265 1272
1266 spec->num_cvts++; 1273 spec->cvt_nids[spec->num_cvts++] = cvt_nid;
1267 1274
1268 return 0; 1275 return 0;
1269} 1276}
@@ -1691,27 +1698,22 @@ static const struct hda_codec_ops generic_hdmi_patch_ops = {
1691 .unsol_event = hdmi_unsol_event, 1698 .unsol_event = hdmi_unsol_event,
1692}; 1699};
1693 1700
1694static void intel_haswell_fixup_connect_list(struct hda_codec *codec)
1695{
1696 unsigned int vendor_param;
1697 hda_nid_t list[3] = {0x2, 0x3, 0x4};
1698 1701
1699 vendor_param = snd_hda_codec_read(codec, 0x08, 0, 0xf81, 0); 1702static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
1700 if (vendor_param == -1 || vendor_param & 0x02) 1703 hda_nid_t nid)
1701 return; 1704{
1702 1705 struct hdmi_spec *spec = codec->spec;
1703 /* enable DP1.2 mode */ 1706 hda_nid_t conns[4];
1704 vendor_param |= 0x02; 1707 int nconns;
1705 snd_hda_codec_read(codec, 0x08, 0, 0x781, vendor_param);
1706 1708
1707 vendor_param = snd_hda_codec_read(codec, 0x08, 0, 0xf81, 0); 1709 nconns = snd_hda_get_connections(codec, nid, conns, ARRAY_SIZE(conns));
1708 if (vendor_param == -1 || !(vendor_param & 0x02)) 1710 if (nconns == spec->num_cvts &&
1711 !memcmp(conns, spec->cvt_nids, spec->num_cvts * sizeof(hda_nid_t)))
1709 return; 1712 return;
1710 1713
1711 /* override 3 pins connection list */ 1714 /* override pins connection list */
1712 snd_hda_override_conn_list(codec, 0x05, 3, list); 1715 snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid);
1713 snd_hda_override_conn_list(codec, 0x06, 3, list); 1716 snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids);
1714 snd_hda_override_conn_list(codec, 0x07, 3, list);
1715} 1717}
1716 1718
1717#define INTEL_VENDOR_NID 0x08 1719#define INTEL_VENDOR_NID 0x08
@@ -1742,6 +1744,22 @@ static void intel_haswell_enable_all_pins(struct hda_codec *codec,
1742 return; 1744 return;
1743} 1745}
1744 1746
1747static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec)
1748{
1749 unsigned int vendor_param;
1750
1751 vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0,
1752 INTEL_GET_VENDOR_VERB, 0);
1753 if (vendor_param == -1 || vendor_param & INTEL_EN_DP12)
1754 return;
1755
1756 /* enable DP1.2 mode */
1757 vendor_param |= INTEL_EN_DP12;
1758 snd_hda_codec_write_cache(codec, INTEL_VENDOR_NID, 0,
1759 INTEL_SET_VENDOR_VERB, vendor_param);
1760}
1761
1762
1745 1763
1746/* available models for fixup */ 1764/* available models for fixup */
1747enum { 1765enum {
@@ -1780,7 +1798,7 @@ static int patch_generic_hdmi(struct hda_codec *codec)
1780 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 1798 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1781 1799
1782 if (codec->vendor_id == 0x80862807) 1800 if (codec->vendor_id == 0x80862807)
1783 intel_haswell_fixup_connect_list(codec); 1801 intel_haswell_fixup_enable_dp12(codec);
1784 1802
1785 if (hdmi_parse_codec(codec) < 0) { 1803 if (hdmi_parse_codec(codec) < 0) {
1786 codec->spec = NULL; 1804 codec->spec = NULL;