drm/i915: Terminate the FORCE WAKE after we have finished reading
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 8 Dec 2010 17:32:24 +0000 (17:32 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 9 Dec 2010 19:46:24 +0000 (19:46 +0000)
Once we have read the value out of the GT power well, we need to remove
the FORCE WAKE bit to allow the system to auto-power down.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_reg.h

index 2be344a8e93b3db7910e24eabb4f14a279eda1cc..5f20cd98861282ec4a3def76ae3a2780e5731678 100644 (file)
@@ -244,6 +244,28 @@ void intel_detect_pch (struct drm_device *dev)
        }
 }
 
+void __gen6_force_wake_get(struct drm_i915_private *dev_priv)
+{
+       int count;
+
+       count = 0;
+       while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
+               udelay(10);
+
+       I915_WRITE_NOTRACE(FORCEWAKE, 1);
+       POSTING_READ(FORCEWAKE);
+
+       count = 0;
+       while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0)
+               udelay(10);
+}
+
+void __gen6_force_wake_put(struct drm_i915_private *dev_priv)
+{
+       I915_WRITE_NOTRACE(FORCEWAKE, 0);
+       POSTING_READ(FORCEWAKE);
+}
+
 static int i915_drm_freeze(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
index b8a55008a1b536ceeb0826f2e2b76bc9ad302b5c..30780f2cab6f9b1115d4adc4b6cb47a255637237 100644 (file)
@@ -1341,17 +1341,20 @@ __i915_write(64, q)
  * must be set to prevent GT core from power down and stale values being
  * returned.
  */
+void __gen6_force_wake_get(struct drm_i915_private *dev_priv);
+void __gen6_force_wake_put (struct drm_i915_private *dev_priv);
 static inline u32 i915_safe_read(struct drm_i915_private *dev_priv, u32 reg)
 {
-       if (IS_GEN6(dev_priv->dev)) {
-               I915_WRITE_NOTRACE(FORCEWAKE, 1);
-               POSTING_READ(FORCEWAKE);
-               /* XXX How long do we really need to wait here?
-                * Will different registers/engines require different periods?
-                */
-               udelay(100);
-       }
-       return I915_READ(reg);
+       u32 val;
+
+       if (dev_priv->info->gen >= 6) {
+               __gen6_force_wake_get(dev_priv);
+               val = I915_READ(reg);
+               __gen6_force_wake_put(dev_priv);
+       } else
+               val = I915_READ(reg);
+
+       return val;
 }
 
 static inline void
index 3e03094cf1488ce0e8246855e6d02bd8c0c8308c..2a36e05f1b85dab617f701bff7f0871b5eb05b1c 100644 (file)
 #define  EDP_LINK_TRAIN_VOL_EMP_MASK_SNB       (0x3f<<22)
 
 #define  FORCEWAKE                             0xA18C
+#define  FORCEWAKE_ACK                         0x130090
 #endif /* _I915_REG_H_ */