[Intel-gfx] [PATCH] drm/i915: read edid-extensions when sdvo device is connected with hdmi monitor
Ma Ling
ling.ma at intel.com
Wed Apr 8 08:23:56 CEST 2009
Currently drm_get_edid function will fetch basic edid, then determine to continue edid extensions
by edid->extensions field. However for sdvo output, after first i2c_stop of drm_get_edid function
we have to do switch ddc bus for following edid extensions, or i2c will fail to work.
The patch intends to fetch basic edid, then switch ddc bus to get edid extension
by drm_do_probe_ddc_edid, instead of drm_get_edid.
It fixed bug #21042
Signed-off-by: Ma Ling <ling.ma at intel.com>
---
drivers/gpu/drm/i915/intel_sdvo.c | 83 ++++++++++++++++++++++++++++++++++++-
1 files changed, 81 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 7b31f55..78c78ac 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"
@@ -1377,14 +1378,92 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
return connector_status_disconnected;
}
+#define MAX_EDID_EXT_NUM 4
+/**
+ * This function will fetch EDID by switch ddc bus, instead of drm_get_edid
+ * function.
+ */
+static struct edid *intel_sdvo_hdmi_get_edid(struct intel_output *intel_output)
+{
+ struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+ struct edid *edid;
+ int ret = 0;
+
+ edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1),
+ GFP_KERNEL);
+
+ if (edid == NULL) {
+ DRM_DEBUG("Failed to allocated EDID for SDVO HDMI\n");
+ goto end;
+ }
+
+ /* Read first EDID block */
+ ret = drm_do_probe_ddc_edid(&intel_output->ddc_bus->adapter,
+ (unsigned char *)edid, EDID_LENGTH);
+ if (ret != 0) {
+ DRM_DEBUG("Failed to read basic EDID for SDVO HDMI\n");
+ goto clean_up;
+ }
+
+ /* There are EDID extensions to be read */
+ if (edid->extensions != 0) {
+ int edid_ext_num = edid->extensions;
+
+ if (edid_ext_num > MAX_EDID_EXT_NUM) {
+ DRM_DEBUG("The number of extension(%d) is "
+ "over max (%d), actually read number (%d)\n",
+ edid_ext_num, MAX_EDID_EXT_NUM,
+ MAX_EDID_EXT_NUM);
+ /* Reset EDID extension number to be read */
+ edid_ext_num = MAX_EDID_EXT_NUM;
+ }
+ /* Must set the bus switch and get the edid again */
+ intel_sdvo_set_control_bus_switch(intel_output,
+ sdvo_priv->ddc_bus);
+ /* Read EDID including extensions too */
+ ret = drm_do_probe_ddc_edid(&intel_output->ddc_bus->adapter,
+ (unsigned char *)edid,
+ EDID_LENGTH * (edid_ext_num + 1));
+ if (ret != 0) {
+ DRM_DEBUG("Failed to read EDID EXT for SDVO HDMI\n");
+ goto clean_up;
+ }
+ }
+ goto end;
+
+clean_up:
+ kfree(edid);
+ edid = NULL;
+end:
+ return edid;
+}
+
+static void intel_sdvo_hdmi_ddc_get_modes(struct intel_output *intel_output)
+{
+ struct edid *edid;
+
+ edid = intel_sdvo_hdmi_get_edid(intel_output);
+ if (edid != NULL) {
+ drm_mode_connector_update_edid_property(&intel_output->base,
+ edid);
+ drm_add_edid_modes(&intel_output->base, edid);
+ kfree(edid);
+ }
+}
+
static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
/* set the bus switch and get the modes */
- intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
- intel_ddc_get_modes(intel_output);
+ intel_sdvo_set_control_bus_switch(intel_output,
+ sdvo_priv->ddc_bus);
+ if (sdvo_priv->is_hdmi == true)
+ intel_sdvo_hdmi_ddc_get_modes(intel_output);
+ else
+ intel_ddc_get_modes(intel_output);
+
#if 0
struct drm_device *dev = encoder->dev;
--
1.5.4.4
More information about the Intel-gfx
mailing list