drm/i915: SDVO hotplug have different interrupt status bits for i915/i965/g4x
Chris Wilson [Fri, 11 May 2012 17:01:33 +0000 (18:01 +0100)]
commit 084b612ecf8e59973576b2f644e6949609c79375 upstream.

Note that gen3 is the only platform where we've got the bit
definitions right, hence the workaround of disabling sdvo hotplug
support on i945g/gm is not due to misdiagnosis of broken hotplug irq
handling ...

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
[danvet: add some blurb about sdvo hotplug fail on i945g/gm I've
wondered about while reviewing.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
[bwh: Backported to 3.2:
 - Adjust context
 - Handle all three cases in i915_driver_irq_postinstall() as there
   are not separate functions for gen3 and gen4+
 - Carry on using IS_SDVOB() in intel_sdvo_init()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Julien Cristau <jcristau@debian.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_sdvo.c

index 26c67a7..54fcbc1 100644 (file)
@@ -2051,10 +2051,22 @@ static int i915_driver_irq_postinstall(struct drm_device *dev)
                        hotplug_en |= HDMIC_HOTPLUG_INT_EN;
                if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
                        hotplug_en |= HDMID_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
-                       hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
-                       hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+               if (IS_G4X(dev)) {
+                       if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X)
+                               hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+                       if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X)
+                               hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+               } else if (IS_GEN4(dev)) {
+                       if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965)
+                               hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+                       if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965)
+                               hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+               } else {
+                       if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915)
+                               hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+                       if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915)
+                               hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+               }
                if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
                        hotplug_en |= CRT_HOTPLUG_INT_EN;
 
index eaf3806..06c0fc3 100644 (file)
 #define   DPC_HOTPLUG_INT_STATUS               (1 << 28)
 #define   HDMID_HOTPLUG_INT_STATUS             (1 << 27)
 #define   DPD_HOTPLUG_INT_STATUS               (1 << 27)
+/* CRT/TV common between gen3+ */
 #define   CRT_HOTPLUG_INT_STATUS               (1 << 11)
 #define   TV_HOTPLUG_INT_STATUS                        (1 << 10)
 #define   CRT_HOTPLUG_MONITOR_MASK             (3 << 8)
 #define   CRT_HOTPLUG_MONITOR_COLOR            (3 << 8)
 #define   CRT_HOTPLUG_MONITOR_MONO             (2 << 8)
 #define   CRT_HOTPLUG_MONITOR_NONE             (0 << 8)
-#define   SDVOC_HOTPLUG_INT_STATUS             (1 << 7)
-#define   SDVOB_HOTPLUG_INT_STATUS             (1 << 6)
+/* SDVO is different across gen3/4 */
+#define   SDVOC_HOTPLUG_INT_STATUS_G4X         (1 << 3)
+#define   SDVOB_HOTPLUG_INT_STATUS_G4X         (1 << 2)
+#define   SDVOC_HOTPLUG_INT_STATUS_I965                (3 << 4)
+#define   SDVOB_HOTPLUG_INT_STATUS_I965                (3 << 2)
+#define   SDVOC_HOTPLUG_INT_STATUS_I915                (1 << 7)
+#define   SDVOB_HOTPLUG_INT_STATUS_I915                (1 << 6)
 
 /* SDVO port control */
 #define SDVOB                  0x61140
index b96e8c8..53cbcc3 100644 (file)
@@ -2528,6 +2528,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *intel_encoder;
        struct intel_sdvo *intel_sdvo;
+       u32 hotplug_mask;
        int i;
 
        intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
@@ -2558,10 +2559,18 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
                }
        }
 
-       if (IS_SDVOB(sdvo_reg))
-               dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
-       else
-               dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
+       hotplug_mask = 0;
+       if (IS_G4X(dev)) {
+               hotplug_mask = IS_SDVOB(sdvo_reg) ?
+                       SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X;
+       } else if (IS_GEN4(dev)) {
+               hotplug_mask = IS_SDVOB(sdvo_reg) ?
+                       SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965;
+       } else {
+               hotplug_mask = IS_SDVOB(sdvo_reg) ?
+                       SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
+       }
+       dev_priv->hotplug_supported_mask |= hotplug_mask;
 
        drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);