drm/i915/gen4: Extra CRT hotplug paranoia
authorAdam Jackson <ajax@redhat.com>
Mon, 24 May 2010 20:46:29 +0000 (16:46 -0400)
committerEric Anholt <eric@anholt.net>
Wed, 26 May 2010 20:53:20 +0000 (13:53 -0700)
Disable the CRT plug interrupt while doing the force cycle, explicitly
clear any CRT interrupt we may have generated, and restore when done.
Should mitigate interrupt storms from hotplug detection.

Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_crt.c

index 784cf3c914e9293e0e7ed3e49d64d51667e6c41c..7a726840efa7339114a226b6006cca43d40e4e0f 100644 (file)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV       (0 << 2)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV       (1 << 2)
 #define CRT_HOTPLUG_MASK                       (0x3fc) /* Bits 9-2 */
-#define CRT_FORCE_HOTPLUG_MASK                 0xfffffe1f
 
 #define PORT_HOTPLUG_STAT      0x61114
 #define   HDMIB_HOTPLUG_INT_STATUS             (1 << 29)
index d5c130202396bff52d96b877abd0b1f8a77cd767..22ff38455731ae00b5b5446d5472391935d6c5bf 100644 (file)
@@ -217,7 +217,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 hotplug_en;
+       u32 hotplug_en, orig, stat;
+       bool ret = false;
        int i, tries = 0;
 
        if (HAS_PCH_SPLIT(dev))
@@ -232,8 +233,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
                tries = 2;
        else
                tries = 1;
-       hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-       hotplug_en &= CRT_FORCE_HOTPLUG_MASK;
+       hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
+       hotplug_en &= CRT_HOTPLUG_MASK;
        hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
 
        if (IS_G4X(dev))
@@ -255,11 +256,17 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
                } while (time_after(timeout, jiffies));
        }
 
-       if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) !=
-           CRT_HOTPLUG_MONITOR_NONE)
-               return true;
+       stat = I915_READ(PORT_HOTPLUG_STAT);
+       if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE)
+               ret = true;
+
+       /* clear the interrupt we just generated, if any */
+       I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
 
-       return false;
+       /* and put the bits back */
+       I915_WRITE(PORT_HOTPLUG_EN, orig);
+
+       return ret;
 }
 
 static bool intel_crt_detect_ddc(struct drm_encoder *encoder)