[Intel-gfx] [RFC][PATCH 2/2] drm/i915: dynamically re-register real sdvo output based on detected result

Ma Ling ling.ma at intel.com
Fri Apr 17 06:15:57 CEST 2009


´╗┐If sdvo have multiple outputs available, chose the real one and modify corresponding connector type.

Signed-off-by: Ma Ling <ling.ma at intel.com>
---
because we could call
 drivers/gpu/drm/i915/intel_sdvo.c |   63 +++++++++++++++++++++++++++++++++---
 1 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 96e9012..01be590 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -57,6 +57,12 @@ struct intel_sdvo_priv {
 	/* Pixel clock limitations reported by the SDVO device, in kHz */
 	int pixel_clock_min, pixel_clock_max;
 
+	/*
+	* For multiple function SDVO device,
+	* this is for current attached outputs.
+	*/
+	uint16_t attached_output;
+
 	/**
 	 * This is set if we're going to treat the device as TV-out.
 	 *
@@ -102,6 +108,8 @@ struct intel_sdvo_priv {
 };
 
 static struct edid *intel_sdvo_get_ddc_edid(struct intel_output *intel_output);
+static bool
+intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags);
 
 /**
  * Writes the SDVOB or SDVOC with the given value, but always writes both
@@ -1377,25 +1385,68 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
 	}
 }
 
+static bool
+intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
+{
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+	int caps = 0;
+
+	if (sdvo_priv->caps.output_flags &
+	    (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+		caps++;
+	if (sdvo_priv->caps.output_flags &
+	    (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1))
+		caps++;
+	if (sdvo_priv->caps.output_flags & (SDVO_OUTPUT_CVBS0 |
+	    SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_YPRPB0 |
+	    SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_CVBS1 |
+	    SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_YPRPB1 |
+	    SDVO_OUTPUT_SCART1))
+		caps++;
+	if (sdvo_priv->caps.output_flags & (SDVO_OUTPUT_LVDS0 |
+	    SDVO_OUTPUT_LVDS1))
+		caps++;
+
+	return (caps > 1);
+}
+
 static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector)
 {
-	u8 response[2];
+	uint16_t response;
 	u8 status;
 	struct intel_output *intel_output = to_intel_output(connector);
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 
 	intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
 	status = intel_sdvo_read_response(intel_output, &response, 2);
 
-	DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]);
+	DRM_DEBUG("SDVO response %d %d\n", response & 0xff, response >> 8);
 
 	if (status != SDVO_CMD_STATUS_SUCCESS)
 		return connector_status_unknown;
 
-	if ((response[0] != 0) || (response[1] != 0)) {
-		intel_sdvo_hdmi_sink_detect(connector);
-		return connector_status_connected;
-	} else
+	if (response == 0)
 		return connector_status_disconnected;
+
+	if (intel_sdvo_multifunc_encoder(intel_output) &&
+	    sdvo_priv->attached_output != response) {
+		if (intel_sdvo_output_setup(intel_output, response) != true)
+			return connector_status_unknown;
+		sdvo_priv->attached_output = response;
+	}
+
+	if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
+		/* Check EDID in DVI-I case */
+		struct edid *edid = intel_sdvo_get_ddc_edid(intel_output);
+		if (edid != NULL) {
+			int digital = edid->digital;
+			kfree(edid);
+			if (digital == 0)
+				return connector_status_disconnected;
+		}
+	}
+
+	return connector_status_connected;
 }
 
 #define MAX_EDID_EXT_NUM 4
-- 
1.5.4.4






More information about the Intel-gfx mailing list