Commit e153f52d authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Greg Kroah-Hartman

drm/i915: Check VBT for port presence in addition to the strap on VLV/CHV

[ Upstream commit 22f35042 ]

Apparently some CHV boards failed to hook up the port presence straps
for HDMI ports as well (earlier we assumed this problem only affected
eDP ports). So let's check the VBT in addition to the strap, and if
either one claims that the port is present go ahead and register the
relevant connector.

While at it, change port D to register DP before HDMI as we do for ports
B and C since
commit 457c52d8 ("drm/i915: Only ignore eDP ports that are connected")

Also print a debug message when we register a HDMI connector to aid
in diagnosing missing/incorrect ports. We already had such a print for
DP/eDP.

v2: Improve the comment in the code a bit, note the port D change in
    the commit message

Cc: Radoslav Duda <radosd@radosd.com>
Tested-by: default avatarRadoslav Duda <radosd@radosd.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96321Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1464945463-14364-1-git-send-email-ville.syrjala@linux.intel.comReviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarSasha Levin <alexander.levin@verizon.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent af115b1a
...@@ -3313,6 +3313,9 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) ...@@ -3313,6 +3313,9 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
} }
extern void intel_i2c_reset(struct drm_device *dev); extern void intel_i2c_reset(struct drm_device *dev);
/* intel_bios.c */
bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port);
/* intel_opregion.c */ /* intel_opregion.c */
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
extern int intel_opregion_setup(struct drm_device *dev); extern int intel_opregion_setup(struct drm_device *dev);
......
...@@ -1351,3 +1351,42 @@ intel_parse_bios(struct drm_device *dev) ...@@ -1351,3 +1351,42 @@ intel_parse_bios(struct drm_device *dev)
return 0; return 0;
} }
/**
* intel_bios_is_port_present - is the specified digital port present
* @dev_priv: i915 device instance
* @port: port to check
*
* Return true if the device in %port is present.
*/
bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port)
{
static const struct {
u16 dp, hdmi;
} port_mapping[] = {
[PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, },
[PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, },
[PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, },
[PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
};
int i;
/* FIXME maybe deal with port A as well? */
if (WARN_ON(port == PORT_A) || port >= ARRAY_SIZE(port_mapping))
return false;
if (!dev_priv->vbt.child_dev_num)
return false;
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
const union child_device_config *p_child =
&dev_priv->vbt.child_dev[i];
if ((p_child->common.dvo_port == port_mapping[port].dp ||
p_child->common.dvo_port == port_mapping[port].hdmi) &&
(p_child->common.device_type & (DEVICE_TYPE_TMDS_DVI_SIGNALING |
DEVICE_TYPE_DISPLAYPORT_OUTPUT)))
return true;
}
return false;
}
...@@ -14160,7 +14160,7 @@ static void intel_setup_outputs(struct drm_device *dev) ...@@ -14160,7 +14160,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(PCH_DP_D) & DP_DETECTED) if (I915_READ(PCH_DP_D) & DP_DETECTED)
intel_dp_init(dev, PCH_DP_D, PORT_D); intel_dp_init(dev, PCH_DP_D, PORT_D);
} else if (IS_VALLEYVIEW(dev)) { } else if (IS_VALLEYVIEW(dev)) {
bool has_edp; bool has_edp, has_port;
/* /*
* The DP_DETECTED bit is the latched state of the DDC * The DP_DETECTED bit is the latched state of the DDC
...@@ -14170,25 +14170,37 @@ static void intel_setup_outputs(struct drm_device *dev) ...@@ -14170,25 +14170,37 @@ static void intel_setup_outputs(struct drm_device *dev)
* Thus we can't rely on the DP_DETECTED bit alone to detect * Thus we can't rely on the DP_DETECTED bit alone to detect
* eDP ports. Consult the VBT as well as DP_DETECTED to * eDP ports. Consult the VBT as well as DP_DETECTED to
* detect eDP ports. * detect eDP ports.
*
* Sadly the straps seem to be missing sometimes even for HDMI
* ports (eg. on Voyo V3 - CHT x7-Z8700), so check both strap
* and VBT for the presence of the port. Additionally we can't
* trust the port type the VBT declares as we've seen at least
* HDMI ports that the VBT claim are DP or eDP.
*/ */
has_edp = intel_dp_is_edp(dev, PORT_B); has_edp = intel_dp_is_edp(dev, PORT_B);
if (I915_READ(VLV_DP_B) & DP_DETECTED || has_edp) has_port = intel_bios_is_port_present(dev_priv, PORT_B);
if (I915_READ(VLV_DP_B) & DP_DETECTED || has_port)
has_edp &= intel_dp_init(dev, VLV_DP_B, PORT_B); has_edp &= intel_dp_init(dev, VLV_DP_B, PORT_B);
if (I915_READ(VLV_HDMIB) & SDVO_DETECTED && !has_edp) if ((I915_READ(VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp)
intel_hdmi_init(dev, VLV_HDMIB, PORT_B); intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
has_edp = intel_dp_is_edp(dev, PORT_C); has_edp = intel_dp_is_edp(dev, PORT_C);
if (I915_READ(VLV_DP_C) & DP_DETECTED || has_edp) has_port = intel_bios_is_port_present(dev_priv, PORT_C);
if (I915_READ(VLV_DP_C) & DP_DETECTED || has_port)
has_edp &= intel_dp_init(dev, VLV_DP_C, PORT_C); has_edp &= intel_dp_init(dev, VLV_DP_C, PORT_C);
if (I915_READ(VLV_HDMIC) & SDVO_DETECTED && !has_edp) if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp)
intel_hdmi_init(dev, VLV_HDMIC, PORT_C); intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
if (IS_CHERRYVIEW(dev)) { if (IS_CHERRYVIEW(dev)) {
/* eDP not supported on port D, so don't check VBT */ /*
if (I915_READ(CHV_HDMID) & SDVO_DETECTED) * eDP not supported on port D,
intel_hdmi_init(dev, CHV_HDMID, PORT_D); * so no need to worry about it
if (I915_READ(CHV_DP_D) & DP_DETECTED) */
has_port = intel_bios_is_port_present(dev_priv, PORT_D);
if (I915_READ(CHV_DP_D) & DP_DETECTED || has_port)
intel_dp_init(dev, CHV_DP_D, PORT_D); intel_dp_init(dev, CHV_DP_D, PORT_D);
if (I915_READ(CHV_HDMID) & SDVO_DETECTED || has_port)
intel_hdmi_init(dev, CHV_HDMID, PORT_D);
} }
intel_dsi_init(dev); intel_dsi_init(dev);
......
...@@ -2030,6 +2030,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -2030,6 +2030,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
enum port port = intel_dig_port->port; enum port port = intel_dig_port->port;
uint8_t alternate_ddc_pin; uint8_t alternate_ddc_pin;
DRM_DEBUG_KMS("Adding HDMI connector on port %c\n",
port_name(port));
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA); DRM_MODE_CONNECTOR_HDMIA);
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment