Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Assume non-DP++ port if dvo_port is HDMI and there's no AUX ch specified in the VBT

My heuristic for detecting type 1 DVI DP++ adaptors based on the VBT
port information apparently didn't survive the reality of buggy VBTs.
In this particular case we have a machine with a natice HDMI port, but
the VBT tells us it's a DP++ port based on its capabilities.

The dvo_port information in VBT does claim that we're dealing with a
HDMI port though, but we have other machines which do the same even
when they actually have DP++ ports. So that piece of information alone
isn't sufficient to tell the two apart.

After staring at a bunch of VBTs from various machines, I have to
conclude that the only other semi-reliable clue we can use is the
presence of the AUX channel in the VBT. On this particular machine
AUX channel is specified as zero, whereas on some of the other machines
which listed the DP++ port as HDMI have a non-zero AUX channel.

I've also seen VBTs which have dvo_port a DP but have a zero AUX
channel. I believe those we need to treat as DP ports, so we'll limit
the AUX channel check to just the cases where dvo_port is HDMI.

If we encounter any more serious failures with this heuristic I think
we'll have to have to throw it out entirely. But that could mean that
there is a risk of type 1 DVI dongle users getting greeted by a
black screen, so I'd rather not go there unless absolutely necessary.

v2: Remove the duplicate PORT_A check (Daniel)
Fix some typos in the commit message

Cc: Daniel Otero <daniel.otero@outlook.com>
Cc: stable@vger.kernel.org
Tested-by: Daniel Otero <daniel.otero@outlook.com>
Fixes: d61992565bd3 ("drm/i915: Determine DP++ type 1 DVI adaptor presence based on VBT")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97994
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1478884464-14251-1-git-send-email-ville.syrjala@linux.intel.com
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
(cherry picked from commit 7a17995a3dc8613f778a9e2fd20e870f17789544)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>

authored by

Ville Syrjälä and committed by
Jani Nikula
bc9db5ad fc22b787

+24 -9
+22 -8
drivers/gpu/drm/i915/intel_bios.c
··· 1143 1143 if (!child) 1144 1144 return; 1145 1145 1146 - aux_channel = child->raw[25]; 1146 + aux_channel = child->common.aux_channel; 1147 1147 ddc_pin = child->common.ddc_pin; 1148 1148 1149 1149 is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; ··· 1673 1673 return false; 1674 1674 } 1675 1675 1676 - bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port) 1676 + static bool child_dev_is_dp_dual_mode(const union child_device_config *p_child, 1677 + enum port port) 1677 1678 { 1678 1679 static const struct { 1679 1680 u16 dp, hdmi; ··· 1688 1687 [PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, }, 1689 1688 [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, 1690 1689 }; 1691 - int i; 1692 1690 1693 1691 if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) 1694 1692 return false; 1695 1693 1696 - if (!dev_priv->vbt.child_dev_num) 1694 + if ((p_child->common.device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) != 1695 + (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS)) 1697 1696 return false; 1697 + 1698 + if (p_child->common.dvo_port == port_mapping[port].dp) 1699 + return true; 1700 + 1701 + /* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */ 1702 + if (p_child->common.dvo_port == port_mapping[port].hdmi && 1703 + p_child->common.aux_channel != 0) 1704 + return true; 1705 + 1706 + return false; 1707 + } 1708 + 1709 + bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, 1710 + enum port port) 1711 + { 1712 + int i; 1698 1713 1699 1714 for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { 1700 1715 const union child_device_config *p_child = 1701 1716 &dev_priv->vbt.child_dev[i]; 1702 1717 1703 - if ((p_child->common.dvo_port == port_mapping[port].dp || 1704 - p_child->common.dvo_port == port_mapping[port].hdmi) && 1705 - (p_child->common.device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) == 1706 - (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS)) 1718 + if (child_dev_is_dp_dual_mode(p_child, port)) 1707 1719 return true; 1708 1720 } 1709 1721
+2 -1
drivers/gpu/drm/i915/intel_vbt_defs.h
··· 280 280 u8 dp_support:1; 281 281 u8 tmds_support:1; 282 282 u8 support_reserved:5; 283 - u8 not_common3[12]; 283 + u8 aux_channel; 284 + u8 not_common3[11]; 284 285 u8 iboost_level; 285 286 } __packed; 286 287