drm/i915: Fix CRT hotplug regression in 2.6.35-rc1
authorAndy Lutomirski <luto@MIT.EDU>
Sat, 12 Jun 2010 09:21:18 +0000 (05:21 -0400)
committerEric Anholt <eric@anholt.net>
Thu, 1 Jul 2010 22:35:57 +0000 (15:35 -0700)
Commit 7a772c492fcfffae812ffca78a628e76fa57fe58 has two bugs which
made the hotplug problems on my laptop worse instead of better.

First, it did not, in fact, disable the CRT plug interrupt -- it
disabled all the other hotplug interrupts.  It seems rather doubtful
that that bit of the patch fixed anything, so let's just remove it.
(If you want to add it back, you probably meant ~CRT_HOTPLUG_INT_EN.)

Second, on at least my GM45, setting CRT_HOTPLUG_ACTIVATION_PERIOD_64
and CRT_HOTPLUG_VOLTAGE_COMPARE_50 (when they were previously unset)
causes a hotplug interrupt about three seconds later.  The old code
never restored PORT_HOTPLUG_EN so this could only happen once, but
they new code restores those registers.  So just set those bits when
we set up the interrupt in the first place.

Signed-off-by: Andy Lutomirski <luto@mit.edu>
Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_crt.c

index 70e1e4b6674467c69ae1fd8b0e69c68c8688f314..d676e55eb212561c7464a13898927b90d577b500 100644 (file)
@@ -1434,8 +1434,18 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
                        hotplug_en |= SDVOC_HOTPLUG_INT_EN;
                if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
                        hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
+               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
                        hotplug_en |= CRT_HOTPLUG_INT_EN;
+
+                       /* Programming the CRT detection parameters tends
+                          to generate a spurious hotplug event about three
+                          seconds later.  So just do it once.
+                       */
+                       if (IS_G4X(dev))
+                               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+                       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+               }
+
                /* Ignore TV since it's buggy */
 
                I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
index 2cae38a572477229d7f0872b9f4c6187dcb2a7ac..150400f405346de04d5693bfedc91d36f0a85a2c 100644 (file)
 #define CRT_HOTPLUG_DETECT_DELAY_2G            (1 << 4)
 #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 PORT_HOTPLUG_STAT      0x61114
 #define   HDMIB_HOTPLUG_INT_STATUS             (1 << 29)
index 22ff38455731ae00b5b5446d5472391935d6c5bf..ee0732b222a1a5e6e9e6fe0ae50c001867006298 100644 (file)
@@ -234,14 +234,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
        else
                tries = 1;
        hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
-       hotplug_en &= CRT_HOTPLUG_MASK;
        hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
 
-       if (IS_G4X(dev))
-               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-
-       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-
        for (i = 0; i < tries ; i++) {
                unsigned long timeout;
                /* turn on the FORCE_DETECT */