[Intel-gfx] [PATCH] drm/i915: Try to initialize eDP for both ports B and C on VLV

ville.syrjala at linux.intel.com ville.syrjala at linux.intel.com
Thu Oct 31 17:46:22 CET 2013


From: Ville Syrjälä <ville.syrjala at linux.intel.com>

On VLV both ports B and C can support either DP or eDP. Try to
initialize eDP first on each port, and if that fails fall back to
regular DP connector.

intel_dp_init_typed() is now like the old intel_dp_init, except you pass
in the connector type. If you pass DRM_MODE_CONNECTOR_Unknown, the code
falls back to the old port/VBT based auto detection to determine the
actual type.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71051
Tested-by: Robert Hooker <robert.hooker at canonical.com>
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c     |  3 +-
 drivers/gpu/drm/i915/intel_display.c | 11 ++++--
 drivers/gpu/drm/i915/intel_dp.c      | 66 ++++++++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_drv.h     |  5 ++-
 4 files changed, 54 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 31f4fe2..dd2660c 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1356,7 +1356,8 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port)
 		return NULL;
 
 	intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
-	if (!intel_dp_init_connector(intel_dig_port, connector)) {
+	if (!intel_dp_init_connector(intel_dig_port, connector,
+				     DRM_MODE_CONNECTOR_Unknown)) {
 		kfree(connector);
 		return NULL;
 	}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8f40ae3..16225eb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9984,15 +9984,20 @@ static void intel_setup_outputs(struct drm_device *dev)
 			intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB,
 					PORT_B);
 			if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED)
-				intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
+				if (!intel_dp_init_typed(dev, VLV_DISPLAY_BASE + DP_B,
+							 PORT_B, DRM_MODE_CONNECTOR_eDP))
+					intel_dp_init_typed(dev, VLV_DISPLAY_BASE + DP_B,
+							    PORT_B, DRM_MODE_CONNECTOR_DisplayPort);
 		}
 
 		if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED) {
 			intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC,
 					PORT_C);
 			if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED)
-				intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C,
-					      PORT_C);
+				if (!intel_dp_init_typed(dev, VLV_DISPLAY_BASE + DP_C,
+							 PORT_C, DRM_MODE_CONNECTOR_eDP))
+					intel_dp_init_typed(dev, VLV_DISPLAY_BASE + DP_C,
+							    PORT_C, DRM_MODE_CONNECTOR_DisplayPort);
 		}
 
 		intel_dsi_init(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b3cc333..a97f186 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3540,7 +3540,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 
 bool
 intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
-			struct intel_connector *intel_connector)
+			struct intel_connector *intel_connector,
+			int type)
 {
 	struct drm_connector *connector = &intel_connector->base;
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
@@ -3549,33 +3550,32 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum port port = intel_dig_port->port;
 	const char *name = NULL;
-	int type, error;
+	int error;
 
 	/* Preserve the current hw state. */
 	intel_dp->DP = I915_READ(intel_dp->output_reg);
 	intel_dp->attached_connector = intel_connector;
 
-	type = DRM_MODE_CONNECTOR_DisplayPort;
-	/*
-	 * FIXME : We need to initialize built-in panels before external panels.
-	 * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
-	 */
-	switch (port) {
-	case PORT_A:
-		type = DRM_MODE_CONNECTOR_eDP;
-		break;
-	case PORT_C:
-		if (IS_VALLEYVIEW(dev))
-			type = DRM_MODE_CONNECTOR_eDP;
-		break;
-	case PORT_D:
-		if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev))
+	if (type == DRM_MODE_CONNECTOR_Unknown) {
+		type = DRM_MODE_CONNECTOR_DisplayPort;
+
+		switch (port) {
+		case PORT_A:
 			type = DRM_MODE_CONNECTOR_eDP;
-		break;
-	default:	/* silence GCC warning */
-		break;
+			break;
+		case PORT_D:
+			if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev))
+				type = DRM_MODE_CONNECTOR_eDP;
+			break;
+		default:	/* silence GCC warning */
+			break;
+		}
 	}
 
+	if (WARN_ON(type != DRM_MODE_CONNECTOR_DisplayPort &&
+		    type != DRM_MODE_CONNECTOR_eDP))
+		return false;
+
 	/*
 	 * For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
 	 * for DP the encoder type can be set by the caller to
@@ -3598,7 +3598,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 			  ironlake_panel_vdd_work);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
-	drm_sysfs_connector_add(connector);
+	error = drm_sysfs_connector_add(connector);
+	if (error) {
+		drm_connector_cleanup(connector);
+		return false;
+	}
 
 	if (HAS_DDI(dev))
 		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
@@ -3680,8 +3684,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	return true;
 }
 
-void
-intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+bool
+intel_dp_init_typed(struct drm_device *dev, int output_reg,
+		    enum port port, int type)
 {
 	struct intel_digital_port *intel_dig_port;
 	struct intel_encoder *intel_encoder;
@@ -3690,12 +3695,12 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 
 	intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
 	if (!intel_dig_port)
-		return;
+		return false;
 
 	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
 		kfree(intel_dig_port);
-		return;
+		return false;
 	}
 
 	intel_encoder = &intel_dig_port->base;
@@ -3727,9 +3732,18 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 	intel_encoder->cloneable = false;
 	intel_encoder->hot_plug = intel_dp_hot_plug;
 
-	if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
+	if (!intel_dp_init_connector(intel_dig_port, intel_connector, type)) {
 		drm_encoder_cleanup(encoder);
 		kfree(intel_dig_port);
 		kfree(intel_connector);
+		return false;
 	}
+
+	return true;
+}
+
+void
+intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+{
+	intel_dp_init_typed(dev, output_reg, port, DRM_MODE_CONNECTOR_Unknown);
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9d2624f..ff982d9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -697,8 +697,11 @@ void intel_display_set_init_power(struct drm_device *dev, bool enable);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
+bool intel_dp_init_typed(struct drm_device *dev, int output_reg,
+			 enum port port, int type);
 bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
-			     struct intel_connector *intel_connector);
+			     struct intel_connector *intel_connector,
+			     int type);
 void intel_dp_start_link_train(struct intel_dp *intel_dp);
 void intel_dp_complete_link_train(struct intel_dp *intel_dp);
 void intel_dp_stop_link_train(struct intel_dp *intel_dp);
-- 
1.8.1.5




More information about the Intel-gfx mailing list