[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