]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/i915/intel_pm.c
drm/i915/chv: remove pre-production hardware workarounds
[karo-tx-linux.git] / drivers / gpu / drm / i915 / intel_pm.c
index 3857592dbf0f0941fbf78cd6c2b5eef7079132e6..3f9b3c0782232dc528c147a36894aa75abcba80e 100644 (file)
@@ -1772,13 +1772,6 @@ struct ilk_wm_maximums {
        uint16_t fbc;
 };
 
-/* used in computing the new watermarks state */
-struct intel_wm_config {
-       unsigned int num_pipes_active;
-       bool sprites_enabled;
-       bool sprites_scaled;
-};
-
 /*
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
@@ -2029,9 +2022,11 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
                                 const struct intel_crtc *intel_crtc,
                                 int level,
                                 struct intel_crtc_state *cstate,
+                                struct intel_plane_state *pristate,
+                                struct intel_plane_state *sprstate,
+                                struct intel_plane_state *curstate,
                                 struct intel_wm_level *result)
 {
-       struct intel_plane *intel_plane;
        uint16_t pri_latency = dev_priv->wm.pri_latency[level];
        uint16_t spr_latency = dev_priv->wm.spr_latency[level];
        uint16_t cur_latency = dev_priv->wm.cur_latency[level];
@@ -2043,29 +2038,11 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
                cur_latency *= 5;
        }
 
-       for_each_intel_plane_on_crtc(dev_priv->dev, intel_crtc, intel_plane) {
-               struct intel_plane_state *pstate =
-                       to_intel_plane_state(intel_plane->base.state);
-
-               switch (intel_plane->base.type) {
-               case DRM_PLANE_TYPE_PRIMARY:
-                       result->pri_val = ilk_compute_pri_wm(cstate, pstate,
-                                                            pri_latency,
-                                                            level);
-                       result->fbc_val = ilk_compute_fbc_wm(cstate, pstate,
-                                                            result->pri_val);
-                       break;
-               case DRM_PLANE_TYPE_OVERLAY:
-                       result->spr_val = ilk_compute_spr_wm(cstate, pstate,
-                                                            spr_latency);
-                       break;
-               case DRM_PLANE_TYPE_CURSOR:
-                       result->cur_val = ilk_compute_cur_wm(cstate, pstate,
-                                                            cur_latency);
-                       break;
-               }
-       }
-
+       result->pri_val = ilk_compute_pri_wm(cstate, pristate,
+                                            pri_latency, level);
+       result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
+       result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
+       result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
        result->enable = true;
 }
 
@@ -2324,34 +2301,19 @@ static void skl_setup_wm_latency(struct drm_device *dev)
        intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
 }
 
-static void ilk_compute_wm_config(struct drm_device *dev,
-                                 struct intel_wm_config *config)
-{
-       struct intel_crtc *intel_crtc;
-
-       /* Compute the currently _active_ config */
-       for_each_intel_crtc(dev, intel_crtc) {
-               const struct intel_pipe_wm *wm = &intel_crtc->wm.active.ilk;
-
-               if (!wm->pipe_enabled)
-                       continue;
-
-               config->sprites_enabled |= wm->sprites_enabled;
-               config->sprites_scaled |= wm->sprites_scaled;
-               config->num_pipes_active++;
-       }
-}
-
 /* Compute new watermarks for the pipe */
-static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
-                                 struct intel_pipe_wm *pipe_wm)
+static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc,
+                              struct drm_atomic_state *state)
 {
-       struct drm_crtc *crtc = cstate->base.crtc;
-       struct drm_device *dev = crtc->dev;
+       struct intel_pipe_wm *pipe_wm;
+       struct drm_device *dev = intel_crtc->base.dev;
        const struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_crtc_state *cstate = NULL;
        struct intel_plane *intel_plane;
+       struct drm_plane_state *ps;
+       struct intel_plane_state *pristate = NULL;
        struct intel_plane_state *sprstate = NULL;
+       struct intel_plane_state *curstate = NULL;
        int level, max_level = ilk_wm_max_level(dev);
        /* LP0 watermark maximums depend on this pipe alone */
        struct intel_wm_config config = {
@@ -2359,11 +2321,24 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
        };
        struct ilk_wm_maximums max;
 
+       cstate = intel_atomic_get_crtc_state(state, intel_crtc);
+       if (IS_ERR(cstate))
+               return PTR_ERR(cstate);
+
+       pipe_wm = &cstate->wm.optimal.ilk;
+
        for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
-               if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY) {
-                       sprstate = to_intel_plane_state(intel_plane->base.state);
-                       break;
-               }
+               ps = drm_atomic_get_plane_state(state,
+                                               &intel_plane->base);
+               if (IS_ERR(ps))
+                       return PTR_ERR(ps);
+
+               if (intel_plane->base.type == DRM_PLANE_TYPE_PRIMARY)
+                       pristate = to_intel_plane_state(ps);
+               else if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY)
+                       sprstate = to_intel_plane_state(ps);
+               else if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
+                       curstate = to_intel_plane_state(ps);
        }
 
        config.sprites_enabled = sprstate->visible;
@@ -2372,7 +2347,7 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
                drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16);
 
        pipe_wm->pipe_enabled = cstate->base.active;
-       pipe_wm->sprites_enabled = sprstate->visible;
+       pipe_wm->sprites_enabled = config.sprites_enabled;
        pipe_wm->sprites_scaled = config.sprites_scaled;
 
        /* ILK/SNB: LP2+ watermarks only w/o sprites */
@@ -2383,24 +2358,27 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
        if (config.sprites_scaled)
                max_level = 0;
 
-       ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, &pipe_wm->wm[0]);
+       ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate,
+                            pristate, sprstate, curstate, &pipe_wm->wm[0]);
 
        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
+               pipe_wm->linetime = hsw_compute_linetime_wm(dev,
+                                                           &intel_crtc->base);
 
        /* LP0 watermarks always use 1/2 DDB partitioning */
        ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
 
        /* At least LP0 must be valid */
        if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
-               return false;
+               return -EINVAL;
 
        ilk_compute_wm_reg_maximums(dev, 1, &max);
 
        for (level = 1; level <= max_level; level++) {
                struct intel_wm_level wm = {};
 
-               ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate, &wm);
+               ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate,
+                                    pristate, sprstate, curstate, &wm);
 
                /*
                 * Disable any watermark level that exceeds the
@@ -2413,7 +2391,7 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
                pipe_wm->wm[level] = wm;
        }
 
-       return true;
+       return 0;
 }
 
 /*
@@ -2968,11 +2946,12 @@ skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate)
 
 static void
 skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
-                     const struct intel_wm_config *config,
                      struct skl_ddb_allocation *ddb /* out */)
 {
        struct drm_crtc *crtc = cstate->base.crtc;
        struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct intel_wm_config *config = &dev_priv->wm.config;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_plane *intel_plane;
        enum pipe pipe = intel_crtc->pipe;
@@ -3147,15 +3126,6 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
        return false;
 }
 
-static void skl_compute_wm_global_parameters(struct drm_device *dev,
-                                            struct intel_wm_config *config)
-{
-       struct drm_crtc *crtc;
-
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-               config->num_pipes_active += to_intel_crtc(crtc)->active;
-}
-
 static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
                                 struct intel_crtc_state *cstate,
                                 struct intel_plane *intel_plane,
@@ -3560,14 +3530,13 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
 }
 
 static bool skl_update_pipe_wm(struct drm_crtc *crtc,
-                              struct intel_wm_config *config,
                               struct skl_ddb_allocation *ddb, /* out */
                               struct skl_pipe_wm *pipe_wm /* out */)
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
 
-       skl_allocate_pipe_ddb(cstate, config, ddb);
+       skl_allocate_pipe_ddb(cstate, ddb);
        skl_compute_pipe_wm(cstate, ddb, pipe_wm);
 
        if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
@@ -3580,7 +3549,6 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
 
 static void skl_update_other_pipe_wm(struct drm_device *dev,
                                     struct drm_crtc *crtc,
-                                    struct intel_wm_config *config,
                                     struct skl_wm_values *r)
 {
        struct intel_crtc *intel_crtc;
@@ -3610,7 +3578,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
                if (!intel_crtc->active)
                        continue;
 
-               wm_changed = skl_update_pipe_wm(&intel_crtc->base, config,
+               wm_changed = skl_update_pipe_wm(&intel_crtc->base,
                                                &r->ddb, &pipe_wm);
 
                /*
@@ -3653,7 +3621,6 @@ static void skl_update_wm(struct drm_crtc *crtc)
        struct skl_wm_values *results = &dev_priv->wm.skl_results;
        struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
        struct skl_pipe_wm *pipe_wm = &cstate->wm.optimal.skl;
-       struct intel_wm_config config = {};
 
 
        /* Clear all dirty flags */
@@ -3661,15 +3628,13 @@ static void skl_update_wm(struct drm_crtc *crtc)
 
        skl_clear_wm(results, intel_crtc->pipe);
 
-       skl_compute_wm_global_parameters(dev, &config);
-
-       if (!skl_update_pipe_wm(crtc, &config, &results->ddb, pipe_wm))
+       if (!skl_update_pipe_wm(crtc, &results->ddb, pipe_wm))
                return;
 
        skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
        results->dirty[intel_crtc->pipe] = true;
 
-       skl_update_other_pipe_wm(dev, crtc, &config, results);
+       skl_update_other_pipe_wm(dev, crtc, results);
        skl_write_wm_values(dev_priv, results);
        skl_flush_wm_values(dev_priv, results);
 
@@ -3682,20 +3647,18 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
        struct drm_device *dev = dev_priv->dev;
        struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
        struct ilk_wm_maximums max;
-       struct intel_wm_config config = {};
+       struct intel_wm_config *config = &dev_priv->wm.config;
        struct ilk_wm_values results = {};
        enum intel_ddb_partitioning partitioning;
 
-       ilk_compute_wm_config(dev, &config);
-
-       ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
-       ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
+       ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_1_2, &max);
+       ilk_wm_merge(dev, config, &max, &lp_wm_1_2);
 
        /* 5/6 split only in single pipe config on IVB+ */
        if (INTEL_INFO(dev)->gen >= 7 &&
-           config.num_pipes_active == 1 && config.sprites_enabled) {
-               ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
-               ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
+           config->num_pipes_active == 1 && config->sprites_enabled) {
+               ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_5_6, &max);
+               ilk_wm_merge(dev, config, &max, &lp_wm_5_6);
 
                best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
        } else {
@@ -3730,12 +3693,6 @@ static void ilk_update_wm(struct drm_crtc *crtc)
                intel_wait_for_vblank(crtc->dev, intel_crtc->pipe);
        }
 
-       intel_compute_pipe_wm(cstate, &cstate->wm.optimal.ilk);
-
-       if (!memcmp(&intel_crtc->wm.active.ilk,
-                   &cstate->wm.optimal.ilk,
-                   sizeof(cstate->wm.optimal.ilk)));
-
        intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
 
        ilk_program_watermarks(dev_priv);
@@ -4773,7 +4730,6 @@ static void gen9_enable_rc6(struct drm_device *dev)
                I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA);
 
        I915_WRITE(GEN6_RC_SLEEP, 0);
-       I915_WRITE(GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */
 
        /* 2c: Program Coarse Power Gating Policies. */
        I915_WRITE(GEN9_MEDIA_PG_IDLE_HYSTERESIS, 25);
@@ -4784,16 +4740,19 @@ static void gen9_enable_rc6(struct drm_device *dev)
                rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
        DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
                        "on" : "off");
-
+       /* WaRsUseTimeoutMode */
        if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_D0) ||
-           (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_A0))
+           (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_A0)) {
+               I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */
                I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
                           GEN7_RC_CTL_TO_MODE |
                           rc6_mask);
-       else
+       } else {
+               I915_WRITE(GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */
                I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
                           GEN6_RC_CTL_EI_MODE(1) |
                           rc6_mask);
+       }
 
        /*
         * 3b: Enable Coarse Power Gating only when RC6 is enabled.
@@ -5102,32 +5061,27 @@ static int cherryview_rps_max_freq(struct drm_i915_private *dev_priv)
        struct drm_device *dev = dev_priv->dev;
        u32 val, rp0;
 
-       if (dev->pdev->revision >= 0x20) {
-               val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE);
+       val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE);
 
-               switch (INTEL_INFO(dev)->eu_total) {
-               case 8:
-                               /* (2 * 4) config */
-                               rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS4EU_FUSE_SHIFT);
-                               break;
-               case 12:
-                               /* (2 * 6) config */
-                               rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS6EU_FUSE_SHIFT);
-                               break;
-               case 16:
-                               /* (2 * 8) config */
-               default:
-                               /* Setting (2 * 8) Min RP0 for any other combination */
-                               rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS8EU_FUSE_SHIFT);
-                               break;
-               }
-               rp0 = (rp0 & FB_GFX_FREQ_FUSE_MASK);
-       } else {
-               /* For pre-production hardware */
-               val = vlv_punit_read(dev_priv, PUNIT_GPU_STATUS_REG);
-               rp0 = (val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) &
-                      PUNIT_GPU_STATUS_MAX_FREQ_MASK;
+       switch (INTEL_INFO(dev)->eu_total) {
+       case 8:
+               /* (2 * 4) config */
+               rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS4EU_FUSE_SHIFT);
+               break;
+       case 12:
+               /* (2 * 6) config */
+               rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS6EU_FUSE_SHIFT);
+               break;
+       case 16:
+               /* (2 * 8) config */
+       default:
+               /* Setting (2 * 8) Min RP0 for any other combination */
+               rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS8EU_FUSE_SHIFT);
+               break;
        }
+
+       rp0 = (rp0 & FB_GFX_FREQ_FUSE_MASK);
+
        return rp0;
 }
 
@@ -5143,18 +5097,11 @@ static int cherryview_rps_rpe_freq(struct drm_i915_private *dev_priv)
 
 static int cherryview_rps_guar_freq(struct drm_i915_private *dev_priv)
 {
-       struct drm_device *dev = dev_priv->dev;
        u32 val, rp1;
 
-       if (dev->pdev->revision >= 0x20) {
-               val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE);
-               rp1 = (val & FB_GFX_FREQ_FUSE_MASK);
-       } else {
-               /* For pre-production hardware */
-               val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
-               rp1 = ((val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) &
-                      PUNIT_GPU_STATUS_MAX_FREQ_MASK);
-       }
+       val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE);
+       rp1 = (val & FB_GFX_FREQ_FUSE_MASK);
+
        return rp1;
 }
 
@@ -7056,6 +7003,7 @@ void intel_init_pm(struct drm_device *dev)
                    (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
                     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
                        dev_priv->display.update_wm = ilk_update_wm;
+                       dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
                } else {
                        DRM_DEBUG_KMS("Failed to read display plane latency. "
                                      "Disable CxSR\n");