drm/i915: Enable RC6 autodownclocking on Sandybridge
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 6d4faff8121b8c5d2aad2d69a2b711ab03d5475c..17c213fef0ecadba022d8d9e9bc5ce96f76377cb 100644 (file)
@@ -5842,6 +5842,91 @@ void intel_init_emon(struct drm_device *dev)
        dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
 }
 
+static void gen6_enable_rc6(struct drm_i915_private *dev_priv)
+{
+       int i;
+
+       /* Here begins a magic sequence of register writes to enable
+        * auto-downclocking.
+        *
+        * Perhaps there might be some value in exposing these to
+        * userspace...
+        */
+       I915_WRITE(GEN6_RC_STATE, 0);
+       __gen6_force_wake_get(dev_priv);
+
+       /* disable the counters and set determistic thresholds */
+       I915_WRITE(GEN6_RC_CONTROL, 0);
+
+       I915_WRITE(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16);
+       I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30);
+       I915_WRITE(GEN6_RC6pp_WAKE_RATE_LIMIT, 30);
+       I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
+       I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
+
+       for (i = 0; i < I915_NUM_RINGS; i++)
+               I915_WRITE(RING_MAX_IDLE(dev_priv->ring[i].mmio_base), 10);
+
+       I915_WRITE(GEN6_RC_SLEEP, 0);
+       I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
+       I915_WRITE(GEN6_RC6_THRESHOLD, 50000);
+       I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
+       I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
+
+       I915_WRITE(GEN6_RC_CONTROL,
+                  GEN6_RC_CTL_RC6p_ENABLE |
+                  GEN6_RC_CTL_RC6_ENABLE |
+                  GEN6_RC_CTL_HW_ENABLE);
+
+       I915_WRITE(GEN6_RC_NORMAL_FREQ,
+                  GEN6_FREQUENCY(10) |
+                  GEN6_OFFSET(0) |
+                  GEN6_AGGRESSIVE_TURBO);
+       I915_WRITE(GEN6_RC_VIDEO_FREQ,
+                  GEN6_FREQUENCY(12));
+
+       I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000);
+       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
+                  18 << 24 |
+                  6 << 16);
+       I915_WRITE(GEN6_RP_UP_THRESHOLD, 90000);
+       I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 100000);
+       I915_WRITE(GEN6_RP_UP_EI, 100000);
+       I915_WRITE(GEN6_RP_DOWN_EI, 300000);
+       I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
+       I915_WRITE(GEN6_RP_CONTROL,
+                  GEN6_RP_MEDIA_TURBO |
+                  GEN6_RP_USE_NORMAL_FREQ |
+                  GEN6_RP_MEDIA_IS_GFX |
+                  GEN6_RP_ENABLE |
+                  GEN6_RP_UP_BUSY_MAX |
+                  GEN6_RP_DOWN_BUSY_MIN);
+
+       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+                    500))
+               DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
+
+       I915_WRITE(GEN6_PCODE_DATA, 0);
+       I915_WRITE(GEN6_PCODE_MAILBOX,
+                  GEN6_PCODE_READY |
+                  GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
+       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+                    500))
+               DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
+
+       /* requires MSI enabled */
+       I915_WRITE(GEN6_PMIER,
+                  GEN6_PM_MBOX_EVENT |
+                  GEN6_PM_THERMAL_EVENT |
+                  GEN6_PM_RP_DOWN_TIMEOUT |
+                  GEN6_PM_RP_UP_THRESHOLD |
+                  GEN6_PM_RP_DOWN_THRESHOLD |
+                  GEN6_PM_RP_UP_EI_EXPIRED |
+                  GEN6_PM_RP_DOWN_EI_EXPIRED);
+
+       __gen6_force_wake_put(dev_priv);
+}
+
 void intel_enable_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5924,6 +6009,7 @@ void intel_enable_clock_gating(struct drm_device *dev)
                                   _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
                                   _3D_CHICKEN2_WM_READ_PIPELINED);
                }
+
        } else if (IS_G4X(dev)) {
                uint32_t dspclk_gate;
                I915_WRITE(RENCLK_GATE_D1, 0);
@@ -5997,6 +6083,9 @@ void intel_enable_clock_gating(struct drm_device *dev)
                                   I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
                }
        }
+
+       if (IS_GEN6(dev))
+               gen6_enable_rc6(dev_priv);
 }
 
 void intel_disable_clock_gating(struct drm_device *dev)
This page took 0.036984 seconds and 5 git commands to generate.