drm/i915: set IDICOS to medium uncore resources
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_pm.c
index 452a9bce81627768b05ce81ccf36fbe6225a9553..404b474eaea32237c2d45586e0bc39f8f17ae619 100644 (file)
@@ -405,7 +405,9 @@ void intel_update_fbc(struct drm_device *dev)
         *   - going to an unsupported config (interlace, pixel multiply, etc.)
         */
        list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
-               if (tmp_crtc->enabled && tmp_crtc->fb) {
+               if (tmp_crtc->enabled &&
+                   !to_intel_crtc(tmp_crtc)->primary_disabled &&
+                   tmp_crtc->fb) {
                        if (crtc) {
                                DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
                                dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
@@ -1883,6 +1885,33 @@ static void sandybridge_update_wm(struct drm_device *dev)
                   cursor_wm);
 }
 
+static void
+haswell_update_linetime_wm(struct drm_device *dev, int pipe,
+                                struct drm_display_mode *mode)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 temp;
+
+       temp = I915_READ(PIPE_WM_LINETIME(pipe));
+       temp &= ~PIPE_WM_LINETIME_MASK;
+
+       /* The WM are computed with base on how long it takes to fill a single
+        * row at the given clock rate, multiplied by 8.
+        * */
+       temp |= PIPE_WM_LINETIME_TIME(
+               ((mode->crtc_hdisplay * 1000) / mode->clock) * 8);
+
+       /* IPS watermarks are only used by pipe A, and are ignored by
+        * pipes B and C.  They are calculated similarly to the common
+        * linetime values, except that we are using CD clock frequency
+        * in MHz instead of pixel rate for the division.
+        *
+        * This is a placeholder for the IPS watermark calculation code.
+        */
+
+       I915_WRITE(PIPE_WM_LINETIME(pipe), temp);
+}
+
 static bool
 sandybridge_compute_sprite_wm(struct drm_device *dev, int plane,
                              uint32_t sprite_width, int pixel_size,
@@ -2078,6 +2107,15 @@ void intel_update_watermarks(struct drm_device *dev)
                dev_priv->display.update_wm(dev);
 }
 
+void intel_update_linetime_watermarks(struct drm_device *dev,
+               int pipe, struct drm_display_mode *mode)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->display.update_linetime_wm)
+               dev_priv->display.update_linetime_wm(dev, pipe, mode);
+}
+
 void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
                                    uint32_t sprite_width, int pixel_size)
 {
@@ -2234,10 +2272,33 @@ void ironlake_disable_drps(struct drm_device *dev)
 void gen6_set_rps(struct drm_device *dev, u8 val)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 swreq;
+       u32 limits;
+
+       limits = 0;
+       if (val >= dev_priv->max_delay)
+               val = dev_priv->max_delay;
+       else
+               limits |= dev_priv->max_delay << 24;
 
-       swreq = (val & 0x3ff) << 25;
-       I915_WRITE(GEN6_RPNSWREQ, swreq);
+       if (val <= dev_priv->min_delay)
+               val = dev_priv->min_delay;
+       else
+               limits |= dev_priv->min_delay << 16;
+
+       if (val == dev_priv->cur_delay)
+               return;
+
+       I915_WRITE(GEN6_RPNSWREQ,
+                  GEN6_FREQUENCY(val) |
+                  GEN6_OFFSET(0) |
+                  GEN6_AGGRESSIVE_TURBO);
+
+       /* Make sure we continue to get interrupts
+        * until we hit the minimum or maximum frequencies.
+        */
+       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
+
+       dev_priv->cur_delay = val;
 }
 
 void gen6_disable_rps(struct drm_device *dev)
@@ -2290,11 +2351,11 @@ int intel_enable_rc6(const struct drm_device *dev)
 
 void gen6_enable_rps(struct drm_i915_private *dev_priv)
 {
-       u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-       u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
+       struct intel_ring_buffer *ring;
+       u32 rp_state_cap;
+       u32 gt_perf_status;
        u32 pcu_mbox, rc6_mask = 0;
        u32 gtfifodbg;
-       int cur_freq, min_freq, max_freq;
        int rc6_mode;
        int i;
 
@@ -2315,6 +2376,14 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
 
        gen6_gt_force_wake_get(dev_priv);
 
+       rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+       gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
+
+       /* In units of 100MHz */
+       dev_priv->max_delay = rp_state_cap & 0xff;
+       dev_priv->min_delay = (rp_state_cap & 0xff0000) >> 16;
+       dev_priv->cur_delay = 0;
+
        /* disable the counters and set deterministic thresholds */
        I915_WRITE(GEN6_RC_CONTROL, 0);
 
@@ -2324,8 +2393,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
        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);
+       for_each_ring(ring, dev_priv, i)
+               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
 
        I915_WRITE(GEN6_RC_SLEEP, 0);
        I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
@@ -2362,8 +2431,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
 
        I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000);
        I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
-                  18 << 24 |
-                  6 << 16);
+                  dev_priv->max_delay << 24 |
+                  dev_priv->min_delay << 16);
        I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000);
        I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000);
        I915_WRITE(GEN6_RP_UP_EI, 100000);
@@ -2371,7 +2440,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
        I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
        I915_WRITE(GEN6_RP_CONTROL,
                   GEN6_RP_MEDIA_TURBO |
-                  GEN6_RP_MEDIA_HW_MODE |
+                  GEN6_RP_MEDIA_HW_NORMAL_MODE |
                   GEN6_RP_MEDIA_IS_GFX |
                   GEN6_RP_ENABLE |
                   GEN6_RP_UP_BUSY_AVG |
@@ -2389,10 +2458,6 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
                     500))
                DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
 
-       min_freq = (rp_state_cap & 0xff0000) >> 16;
-       max_freq = rp_state_cap & 0xff;
-       cur_freq = (gt_perf_status & 0xff00) >> 8;
-
        /* Check for overclock support */
        if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
                     500))
@@ -2403,14 +2468,11 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
                     500))
                DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
        if (pcu_mbox & (1<<31)) { /* OC supported */
-               max_freq = pcu_mbox & 0xff;
+               dev_priv->max_delay = pcu_mbox & 0xff;
                DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
        }
 
-       /* In units of 100MHz */
-       dev_priv->max_delay = max_freq;
-       dev_priv->min_delay = min_freq;
-       dev_priv->cur_delay = cur_freq;
+       gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8);
 
        /* requires MSI enabled */
        I915_WRITE(GEN6_PMIER,
@@ -3322,6 +3384,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe;
        uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+       uint32_t snpcr;
 
        I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
 
@@ -3367,6 +3430,11 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
        /* WaDisable4x2SubspanOptimization */
        I915_WRITE(CACHE_MODE_1,
                   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
+
+       snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+       snpcr &= ~GEN6_MBC_SNPCR_MASK;
+       snpcr |= GEN6_MBC_SNPCR_MED;
+       I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 }
 
 static void valleyview_init_clock_gating(struct drm_device *dev)
@@ -3543,8 +3611,9 @@ static void gen6_sanitize_pm(struct drm_device *dev)
                limits |= (dev_priv->min_delay & 0x3f) << 16;
 
        if (old != limits) {
-               DRM_ERROR("Power management discrepancy: GEN6_RP_INTERRUPT_LIMITS expected %08x, was %08x\n",
-                         limits, old);
+               /* Note that the known failure case is to read back 0. */
+               DRM_DEBUG_DRIVER("Power management discrepancy: GEN6_RP_INTERRUPT_LIMITS "
+                                "expected %08x, was %08x\n", limits, old);
                I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
        }
 
@@ -3689,6 +3758,7 @@ void intel_init_pm(struct drm_device *dev)
                        if (SNB_READ_WM0_LATENCY()) {
                                dev_priv->display.update_wm = sandybridge_update_wm;
                                dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
+                               dev_priv->display.update_linetime_wm = haswell_update_linetime_wm;
                        } else {
                                DRM_DEBUG_KMS("Failed to read display plane latency. "
                                              "Disable CxSR\n");
This page took 0.03157 seconds and 5 git commands to generate.