]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/i915/intel_crt.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / gpu / drm / i915 / intel_crt.c
index 8df574316063fb751d683b4b9d5c0d59b82f42f1..8a77ff4a72372c71da74054205f59be095c28bc3 100644 (file)
@@ -30,6 +30,7 @@
 #include "drm.h"
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
+#include "drm_edid.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
@@ -287,8 +288,9 @@ static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus)
        return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1;
 }
 
-static bool intel_crt_detect_ddc(struct intel_crt *crt)
+static bool intel_crt_detect_ddc(struct drm_connector *connector)
 {
+       struct intel_crt *crt = intel_attached_crt(connector);
        struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private;
 
        /* CRT should always be at 0, but check anyway */
@@ -301,8 +303,26 @@ static bool intel_crt_detect_ddc(struct intel_crt *crt)
        }
 
        if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
-               DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
-               return true;
+               struct edid *edid;
+               bool is_digital = false;
+
+               edid = drm_get_edid(connector,
+                       &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
+               /*
+                * This may be a DVI-I connector with a shared DDC
+                * link between analog and digital outputs, so we
+                * have to check the EDID input spec of the attached device.
+                */
+               if (edid != NULL) {
+                       is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
+                       connector->display_info.raw_edid = NULL;
+                       kfree(edid);
+               }
+
+               if (!is_digital) {
+                       DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
+                       return true;
+               }
        }
 
        return false;
@@ -458,7 +478,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)
                }
        }
 
-       if (intel_crt_detect_ddc(crt))
+       if (intel_crt_detect_ddc(connector))
                return connector_status_connected;
 
        if (!force)
@@ -472,7 +492,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)
                crtc = intel_get_load_detect_pipe(&crt->base, connector,
                                                  NULL, &dpms_mode);
                if (crtc) {
-                       if (intel_crt_detect_ddc(crt))
+                       if (intel_crt_detect_ddc(connector))
                                status = connector_status_connected;
                        else
                                status = intel_crt_load_detect(crtc, crt);
@@ -515,6 +535,15 @@ static int intel_crt_set_property(struct drm_connector *connector,
        return 0;
 }
 
+static void intel_crt_reset(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct intel_crt *crt = intel_attached_crt(connector);
+
+       if (HAS_PCH_SPLIT(dev))
+               crt->force_hotplug_required = 1;
+}
+
 /*
  * Routines for controlling stuff on the analog port
  */
@@ -528,6 +557,7 @@ static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = {
 };
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
+       .reset = intel_crt_reset,
        .dpms = drm_helper_connector_dpms,
        .detect = intel_crt_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,