drm/i915: Don't enable IPS when pixel rate exceeds 95%
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_pm.c
index 6414b27692d43a77984585b0c867cf6267b53f87..d091fec1e10187cf377cbdddb438bfa51f7dfd49 100644 (file)
@@ -1434,23 +1434,22 @@ static void i845_update_wm(struct drm_crtc *unused_crtc)
        I915_WRITE(FW_BLC, fwater_lo);
 }
 
-static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
-                                   struct drm_crtc *crtc)
+uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t pixel_rate;
 
-       pixel_rate = intel_crtc->config->base.adjusted_mode.crtc_clock;
+       pixel_rate = pipe_config->base.adjusted_mode.crtc_clock;
 
        /* We only use IF-ID interlacing. If we ever use PF-ID we'll need to
         * adjust the pixel_rate here. */
 
-       if (intel_crtc->config->pch_pfit.enabled) {
+       if (pipe_config->pch_pfit.enabled) {
                uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
-               uint32_t pfit_size = intel_crtc->config->pch_pfit.size;
+               uint32_t pfit_size = pipe_config->pch_pfit.size;
+
+               pipe_w = pipe_config->pipe_src_w;
+               pipe_h = pipe_config->pipe_src_h;
 
-               pipe_w = intel_crtc->config->pipe_src_w;
-               pipe_h = intel_crtc->config->pipe_src_h;
                pfit_w = (pfit_size >> 16) & 0xFFFF;
                pfit_h = pfit_size & 0xFFFF;
                if (pipe_w < pfit_w)
@@ -1815,7 +1814,7 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
        linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
                                     mode->crtc_clock);
        ips_linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
-                                        dev_priv->display.get_display_clock_speed(dev_priv->dev));
+                                        dev_priv->cdclk_freq);
 
        return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
               PIPE_WM_LINETIME_TIME(linetime);
@@ -2066,24 +2065,22 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
 
        p->active = true;
        p->pipe_htotal = intel_crtc->config->base.adjusted_mode.crtc_htotal;
-       p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
+       p->pixel_rate = ilk_pipe_pixel_rate(intel_crtc->config);
 
-       if (crtc->primary->state->fb) {
-               p->pri.enabled = true;
+       if (crtc->primary->state->fb)
                p->pri.bytes_per_pixel =
                        crtc->primary->state->fb->bits_per_pixel / 8;
-       } else {
-               p->pri.enabled = false;
-               p->pri.bytes_per_pixel = 0;
-       }
+       else
+               p->pri.bytes_per_pixel = 4;
+
+       p->cur.bytes_per_pixel = 4;
+       /*
+        * TODO: for now, assume primary and cursor planes are always enabled.
+        * Setting them to false makes the screen flicker.
+        */
+       p->pri.enabled = true;
+       p->cur.enabled = true;
 
-       if (crtc->cursor->state->fb) {
-               p->cur.enabled = true;
-               p->cur.bytes_per_pixel = 4;
-       } else {
-               p->cur.enabled = false;
-               p->cur.bytes_per_pixel = 0;
-       }
        p->pri.horiz_pixels = intel_crtc->config->pipe_src_w;
        p->cur.horiz_pixels = intel_crtc->base.cursor->state->crtc_w;
 
@@ -4143,32 +4140,40 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
                dev_priv->rps.last_adj = 0;
                I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
        }
+       mutex_unlock(&dev_priv->rps.hw_lock);
 
+       spin_lock(&dev_priv->rps.client_lock);
        while (!list_empty(&dev_priv->rps.clients))
                list_del_init(dev_priv->rps.clients.next);
-       mutex_unlock(&dev_priv->rps.hw_lock);
+       spin_unlock(&dev_priv->rps.client_lock);
 }
 
 void gen6_rps_boost(struct drm_i915_private *dev_priv,
                    struct intel_rps_client *rps,
                    unsigned long submitted)
 {
-       u32 val;
+       /* This is intentionally racy! We peek at the state here, then
+        * validate inside the RPS worker.
+        */
+       if (!(dev_priv->mm.busy &&
+             dev_priv->rps.enabled &&
+             dev_priv->rps.cur_freq < dev_priv->rps.max_freq_softlimit))
+               return;
 
        /* Force a RPS boost (and don't count it against the client) if
         * the GPU is severely congested.
         */
-       if (rps && time_after(jiffies, submitted + msecs_to_jiffies(20)))
+       if (rps && time_after(jiffies, submitted + DRM_I915_THROTTLE_JIFFIES))
                rps = NULL;
 
-       mutex_lock(&dev_priv->rps.hw_lock);
-       val = dev_priv->rps.max_freq_softlimit;
-       if (dev_priv->rps.enabled &&
-           dev_priv->mm.busy &&
-           dev_priv->rps.cur_freq < val &&
-           (rps == NULL || list_empty(&rps->link))) {
-               intel_set_rps(dev_priv->dev, val);
-               dev_priv->rps.last_adj = 0;
+       spin_lock(&dev_priv->rps.client_lock);
+       if (rps == NULL || list_empty(&rps->link)) {
+               spin_lock_irq(&dev_priv->irq_lock);
+               if (dev_priv->rps.interrupts_enabled) {
+                       dev_priv->rps.client_boost = true;
+                       queue_work(dev_priv->wq, &dev_priv->rps.work);
+               }
+               spin_unlock_irq(&dev_priv->irq_lock);
 
                if (rps != NULL) {
                        list_add(&rps->link, &dev_priv->rps.clients);
@@ -4176,7 +4181,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv,
                } else
                        dev_priv->rps.boosts++;
        }
-       mutex_unlock(&dev_priv->rps.hw_lock);
+       spin_unlock(&dev_priv->rps.client_lock);
 }
 
 void intel_set_rps(struct drm_device *dev, u8 val)
@@ -4956,9 +4961,9 @@ static void cherryview_init_gt_powersave(struct drm_device *dev)
 
        mutex_lock(&dev_priv->rps.hw_lock);
 
-       mutex_lock(&dev_priv->dpio_lock);
+       mutex_lock(&dev_priv->sb_lock);
        val = vlv_cck_read(dev_priv, CCK_FUSE_REG);
-       mutex_unlock(&dev_priv->dpio_lock);
+       mutex_unlock(&dev_priv->sb_lock);
 
        switch ((val >> 2) & 0x7) {
        case 0:
@@ -5878,13 +5883,15 @@ static void ibx_init_clock_gating(struct drm_device *dev)
 static void g4x_disable_trickle_feed(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe;
+       enum pipe pipe;
 
        for_each_pipe(dev_priv, pipe) {
                I915_WRITE(DSPCNTR(pipe),
                           I915_READ(DSPCNTR(pipe)) |
                           DISPPLANE_TRICKLE_FEED_DISABLE);
-               intel_flush_primary_plane(dev_priv, pipe);
+
+               I915_WRITE(DSPSURF(pipe), I915_READ(DSPSURF(pipe)));
+               POSTING_READ(DSPSURF(pipe));
        }
 }
 
@@ -6174,10 +6181,9 @@ static void broadwell_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe;
+       uint32_t misccpctl;
 
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+       ilk_init_lp_watermarks(dev);
 
        /* WaSwitchSolVfFArbitrationPriority:bdw */
        I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
@@ -6206,6 +6212,22 @@ static void broadwell_init_clock_gating(struct drm_device *dev)
        I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
                   GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
 
+       /*
+        * WaProgramL3SqcReg1Default:bdw
+        * WaTempDisableDOPClkGating:bdw
+        */
+       misccpctl = I915_READ(GEN7_MISCCPCTL);
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
+       I915_WRITE(GEN8_L3SQCREG1, BDW_WA_L3SQCREG1_DEFAULT);
+       I915_WRITE(GEN7_MISCCPCTL, misccpctl);
+
+       /*
+        * WaGttCachingOffByDefault:bdw
+        * GTT cache may not work with big pages, so if those
+        * are ever enabled GTT cache may need to be disabled.
+        */
+       I915_WRITE(HSW_GTT_CACHE_EN, GTT_CACHE_EN_ALL);
+
        lpt_init_clock_gating(dev);
 }
 
@@ -6481,6 +6503,12 @@ static void cherryview_init_clock_gating(struct drm_device *dev)
        /* WaDisableSDEUnitClockGating:chv */
        I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
                   GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
+
+       /*
+        * GTT cache may not work with big pages, so if those
+        * are ever enabled GTT cache may need to be disabled.
+        */
+       I915_WRITE(HSW_GTT_CACHE_EN, GTT_CACHE_EN_ALL);
 }
 
 static void g4x_init_clock_gating(struct drm_device *dev)
@@ -6892,6 +6920,7 @@ void intel_pm_setup(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        mutex_init(&dev_priv->rps.hw_lock);
+       spin_lock_init(&dev_priv->rps.client_lock);
 
        INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
                          intel_gen6_powersave_work);
This page took 0.041439 seconds and 5 git commands to generate.