drm/i915: Calculate watermark configuration during atomic check (v2)
authorMatt Roper <matthew.d.roper@intel.com>
Thu, 24 Sep 2015 22:53:18 +0000 (15:53 -0700)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 30 Sep 2015 15:19:02 +0000 (17:19 +0200)
v2: Don't forget to actually check the cstate->active value when
    tallying up the number of active CRTC's.  (Ander)

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c

index 00fef94d285b275c3ca29693c8322c151c1309d4..b17dac647787f6513fc7ec8aa0b2e8ee2866a7c5 100644 (file)
@@ -1692,6 +1692,13 @@ struct i915_execbuffer_params {
        struct drm_i915_gem_request     *request;
 };
 
+/* used in computing the new watermarks state */
+struct intel_wm_config {
+       unsigned int num_pipes_active;
+       bool sprites_enabled;
+       bool sprites_scaled;
+};
+
 struct drm_i915_private {
        struct drm_device *dev;
        struct kmem_cache *objects;
@@ -1912,6 +1919,9 @@ struct drm_i915_private {
                 */
                uint16_t skl_latency[8];
 
+               /* Committed wm config */
+               struct intel_wm_config config;
+
                /*
                 * The skl_wm_values structure is a bit too big for stack
                 * allocation, so we keep the staging struct where we store
index b6a68bd1743c18d06b8a40909e9f5d32c7722581..bbeb6d3aca1e08a71ba80b41cf686518d324c490 100644 (file)
@@ -13039,6 +13039,45 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
        return 0;
 }
 
+/*
+ * Handle calculation of various watermark data at the end of the atomic check
+ * phase.  The code here should be run after the per-crtc and per-plane 'check'
+ * handlers to ensure that all derived state has been updated.
+ */
+static void calc_watermark_data(struct drm_atomic_state *state)
+{
+       struct drm_device *dev = state->dev;
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *cstate;
+       struct drm_plane *plane;
+       struct drm_plane_state *pstate;
+
+       /*
+        * Calculate watermark configuration details now that derived
+        * plane/crtc state is all properly updated.
+        */
+       drm_for_each_crtc(crtc, dev) {
+               cstate = drm_atomic_get_existing_crtc_state(state, crtc) ?:
+                       crtc->state;
+
+               if (cstate->active)
+                       intel_state->wm_config.num_pipes_active++;
+       }
+       drm_for_each_legacy_plane(plane, dev) {
+               pstate = drm_atomic_get_existing_plane_state(state, plane) ?:
+                       plane->state;
+
+               if (!to_intel_plane_state(pstate)->visible)
+                       continue;
+
+               intel_state->wm_config.sprites_enabled = true;
+               if (pstate->crtc_w != pstate->src_w >> 16 ||
+                   pstate->crtc_h != pstate->src_h >> 16)
+                       intel_state->wm_config.sprites_scaled = true;
+       }
+}
+
 /**
  * intel_atomic_check - validate state object
  * @dev: drm device
@@ -13047,6 +13086,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
 static int intel_atomic_check(struct drm_device *dev,
                              struct drm_atomic_state *state)
 {
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
        int ret, i;
@@ -13110,10 +13150,15 @@ static int intel_atomic_check(struct drm_device *dev,
                if (ret)
                        return ret;
        } else
-               to_intel_atomic_state(state)->cdclk =
-                       to_i915(state->dev)->cdclk_freq;
+               intel_state->cdclk = to_i915(state->dev)->cdclk_freq;
 
-       return drm_atomic_helper_check_planes(state->dev, state);
+       ret = drm_atomic_helper_check_planes(state->dev, state);
+       if (ret)
+               return ret;
+
+       calc_watermark_data(state);
+
+       return 0;
 }
 
 /**
@@ -13153,6 +13198,7 @@ static int intel_atomic_commit(struct drm_device *dev,
                return ret;
 
        drm_atomic_helper_swap_state(dev, state);
+       dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
 
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
index 47732929c3e447f4288b350e96d9b1bec3d97dc8..dfd2d10d3d3c1aa2941bb13a9c236ab3aac7d72f 100644 (file)
@@ -248,6 +248,7 @@ struct intel_atomic_state {
        unsigned int cdclk;
        bool dpll_set;
        struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
+       struct intel_wm_config wm_config;
 };
 
 struct intel_plane_state {
index 52c8b6aa5e0e4707da855f6fd1d954948e76d7d2..eb9a66d3a47703ce865c12e1f73811571a11ed67 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.
@@ -2308,24 +2301,6 @@ 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 int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc,
                               struct drm_atomic_state *state)
@@ -2971,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;
@@ -3150,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,
@@ -3563,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)))
@@ -3583,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;
@@ -3613,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);
 
                /*
@@ -3656,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 */
@@ -3664,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);
 
@@ -3685,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 {