[Intel-gfx] [PATCH 2/2] drm/i915: dynamically re-register real sdvo output

Ma Ling ling.ma at intel.com
Mon May 18 10:17:06 CEST 2009


If sdvo device have multiple outputs available, chose the real one.

Signed-off-by: Ma Ling <ling.ma at intel.com>
---
The patch is based on [PATCH V5] drm/i915: sdvo read edid-extensions by i2c bus

 drivers/gpu/drm/i915/intel_sdvo.c |   67 +++++++++++++++++++++++++++++++++---
 1 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index c9f06dc..373e746 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -30,6 +30,7 @@
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
+#include "drm_edid.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
@@ -56,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.
 	 *
@@ -100,6 +107,9 @@ struct intel_sdvo_priv {
 	u32 save_SDVOX;
 };
 
+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
  * SDVOB and SDVOC to work around apparent hardware issues (according to
@@ -1374,25 +1384,70 @@ 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;
+		edid = drm_get_edid(&intel_output->base,
+				    &intel_output->ddc_bus->adapter);
+		if (edid != NULL) {
+			int digital = edid->digital;
+			kfree(edid);
+			if (digital == 0)
+				return connector_status_disconnected;
+		}
+	}
+
+	return connector_status_connected;
 }
 
 static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
-- 
1.5.4.4






More information about the Intel-gfx mailing list