diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-02-08 17:10:04 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-02-08 06:23:48 -0500 |
commit | c88d4e84e639df9a9640ecff71de2501a84d1f48 (patch) | |
tree | 612e79c48144f0e985312f0fec170bd35f12f74d /sound | |
parent | 1611a9c931e95fab871a33beba49cc9ea39bbba8 (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.c | 56 |
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 { | |||
84 | struct hdmi_spec { | 84 | struct 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 | ||
1201 | static void intel_haswell_fixup_connect_list(struct hda_codec *codec, | ||
1202 | hda_nid_t nid); | ||
1203 | |||
1200 | static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | 1204 | static 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 | ||
1694 | static 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); | 1702 | static 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 | ||
1747 | static 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 */ |
1747 | enum { | 1765 | enum { |
@@ -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; |