drm/i915: simplify possible_clones computation
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_crt.c
index 75a70c46ef1be81bf77fddbfd43e8e09a213eb71..e1d02be368a5860e3eb081ae790991e17f3e09b3 100644 (file)
@@ -88,6 +88,9 @@ static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
        temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
        temp &= ~ADPA_DAC_ENABLE;
 
+       if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON)
+               mode = DRM_MODE_DPMS_OFF;
+
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                temp |= ADPA_DAC_ENABLE;
@@ -129,7 +132,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector,
 }
 
 static bool intel_crt_mode_fixup(struct drm_encoder *encoder,
-                                struct drm_display_mode *mode,
+                                const struct drm_display_mode *mode,
                                 struct drm_display_mode *adjusted_mode)
 {
        return true;
@@ -230,6 +233,42 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
        return ret;
 }
 
+static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 adpa;
+       bool ret;
+       u32 save_adpa;
+
+       save_adpa = adpa = I915_READ(ADPA);
+       DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa);
+
+       adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
+
+       I915_WRITE(ADPA, adpa);
+
+       if (wait_for((I915_READ(ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
+                    1000)) {
+               DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
+               I915_WRITE(ADPA, save_adpa);
+       }
+
+       /* Check the status to see if both blue and green are on now */
+       adpa = I915_READ(ADPA);
+       if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
+               ret = true;
+       else
+               ret = false;
+
+       DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret);
+
+       /* FIXME: debug force function and remove */
+       ret = true;
+
+       return ret;
+}
+
 /**
  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
  *
@@ -249,6 +288,9 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
        if (HAS_PCH_SPLIT(dev))
                return intel_ironlake_crt_detect_hotplug(connector);
 
+       if (IS_VALLEYVIEW(dev))
+               return valleyview_crt_detect_hotplug(connector);
+
        /*
         * On 4 series desktop, CRT detect sequence need to be done twice
         * to get a reliable result.
@@ -288,39 +330,34 @@ 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;
+       struct edid *edid;
+       struct i2c_adapter *i2c;
 
-       /* CRT should always be at 0, but check anyway */
-       if (crt->base.type != INTEL_OUTPUT_ANALOG)
-               return false;
+       BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
+
+       i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
+       edid = drm_get_edid(connector, i2c);
 
-       if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
-               struct edid *edid;
-               bool is_digital = false;
-               struct i2c_adapter *i2c;
+       if (edid) {
+               bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
 
-               i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
-               edid = drm_get_edid(connector, i2c);
                /*
                 * 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.
-                *
-                * On the other hand, what should we do if it is a broken EDID?
                 */
-               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;
-               } else {
-                       DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
                }
+
+               DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
+       } else {
+               DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [no valid EDID found]\n");
        }
 
+       kfree(edid);
+
        return false;
 }
 
@@ -453,18 +490,27 @@ intel_crt_detect(struct drm_connector *connector, bool force)
        struct intel_load_detect_pipe tmp;
 
        if (I915_HAS_HOTPLUG(dev)) {
+               /* We can not rely on the HPD pin always being correctly wired
+                * up, for example many KVM do not pass it through, and so
+                * only trust an assertion that the monitor is connected.
+                */
                if (intel_crt_detect_hotplug(connector)) {
                        DRM_DEBUG_KMS("CRT detected via hotplug\n");
                        return connector_status_connected;
-               } else {
+               } else
                        DRM_DEBUG_KMS("CRT not detected via hotplug\n");
-                       return connector_status_disconnected;
-               }
        }
 
        if (intel_crt_detect_ddc(connector))
                return connector_status_connected;
 
+       /* Load detection is broken on HPD capable machines. Whoever wants a
+        * broken monitor (without edid) to work behind a broken kvm (that fails
+        * to have the right resistors for HP detection) needs to fix this up.
+        * For now just bail out. */
+       if (I915_HAS_HOTPLUG(dev))
+               return connector_status_disconnected;
+
        if (!force)
                return connector->status;
 
@@ -612,9 +658,7 @@ void intel_crt_init(struct drm_device *dev)
        intel_connector_attach_encoder(intel_connector, &crt->base);
 
        crt->base.type = INTEL_OUTPUT_ANALOG;
-       crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT |
-                               1 << INTEL_ANALOG_CLONE_BIT |
-                               1 << INTEL_SDVO_LVDS_CLONE_BIT);
+       crt->base.cloneable = true;
        if (IS_HASWELL(dev))
                crt->base.crtc_mask = (1 << 0);
        else
This page took 0.029186 seconds and 5 git commands to generate.