drm/i915: Calculate pipe watermarks into CRTC state (v3)
authorMatt Roper <matthew.d.roper@intel.com>
Thu, 24 Sep 2015 22:53:15 +0000 (15:53 -0700)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 30 Sep 2015 15:15:56 +0000 (17:15 +0200)
A future patch will calculate these during the atomic 'check' phase
rather than at WM programming time, so let's store the watermark
values we're planning to use in the CRTC state; the values actually
active on the hardware remains in intel_crtc.

While we're at it, do some minor restructuring to keep ILK and SKL
values in a union.

v2: Don't move cxsr_allowed to state (Maarten)

v3: Only calculate watermarks in state.  Still keep active watermarks in
    intel_crtc itself.  (Ville)

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/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c

index 9431a12c42043aab59f682fd0c7f4b70788b6cdf..47732929c3e447f4288b350e96d9b1bec3d97dc8 100644 (file)
@@ -332,6 +332,21 @@ struct intel_crtc_scaler_state {
 /* drm_mode->private_flags */
 #define I915_MODE_FLAG_INHERITED 1
 
+struct intel_pipe_wm {
+       struct intel_wm_level wm[5];
+       uint32_t linetime;
+       bool fbc_wm_enabled;
+       bool pipe_enabled;
+       bool sprites_enabled;
+       bool sprites_scaled;
+};
+
+struct skl_pipe_wm {
+       struct skl_wm_level wm[8];
+       struct skl_wm_level trans_wm;
+       uint32_t linetime;
+};
+
 struct intel_crtc_state {
        struct drm_crtc_state base;
 
@@ -469,6 +484,17 @@ struct intel_crtc_state {
 
        /* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
        bool disable_lp_wm;
+
+       struct {
+               /*
+                * optimal watermarks, programmed post-vblank when this state
+                * is committed
+                */
+               union {
+                       struct intel_pipe_wm ilk;
+                       struct skl_pipe_wm skl;
+               } optimal;
+       } wm;
 };
 
 struct vlv_wm_state {
@@ -480,15 +506,6 @@ struct vlv_wm_state {
        bool cxsr;
 };
 
-struct intel_pipe_wm {
-       struct intel_wm_level wm[5];
-       uint32_t linetime;
-       bool fbc_wm_enabled;
-       bool pipe_enabled;
-       bool sprites_enabled;
-       bool sprites_scaled;
-};
-
 struct intel_mmio_flip {
        struct work_struct work;
        struct drm_i915_private *i915;
@@ -496,12 +513,6 @@ struct intel_mmio_flip {
        struct intel_crtc *crtc;
 };
 
-struct skl_pipe_wm {
-       struct skl_wm_level wm[8];
-       struct skl_wm_level trans_wm;
-       uint32_t linetime;
-};
-
 /*
  * Tracking of operations that need to be performed at the beginning/end of an
  * atomic commit, outside the atomic section where interrupts are disabled.
@@ -569,9 +580,10 @@ struct intel_crtc {
        /* per-pipe watermark state */
        struct {
                /* watermarks currently being used  */
-               struct intel_pipe_wm active;
-               /* SKL wm values currently in use */
-               struct skl_pipe_wm skl_active;
+               union {
+                       struct intel_pipe_wm ilk;
+                       struct skl_pipe_wm skl;
+               } active;
                /* allow CxSR on this pipe */
                bool cxsr_allowed;
        } wm;
index 2f064de550abcd32652045437c089f5970714c31..3857592dbf0f0941fbf78cd6c2b5eef7079132e6 100644 (file)
@@ -2331,7 +2331,7 @@ static void ilk_compute_wm_config(struct drm_device *dev,
 
        /* Compute the currently _active_ config */
        for_each_intel_crtc(dev, intel_crtc) {
-               const struct intel_pipe_wm *wm = &intel_crtc->wm.active;
+               const struct intel_pipe_wm *wm = &intel_crtc->wm.active.ilk;
 
                if (!wm->pipe_enabled)
                        continue;
@@ -2428,7 +2428,9 @@ static void ilk_merge_wm_level(struct drm_device *dev,
        ret_wm->enable = true;
 
        for_each_intel_crtc(dev, intel_crtc) {
-               const struct intel_pipe_wm *active = &intel_crtc->wm.active;
+               const struct intel_crtc_state *cstate =
+                       to_intel_crtc_state(intel_crtc->base.state);
+               const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
                const struct intel_wm_level *wm = &active->wm[level];
 
                if (!active->pipe_enabled)
@@ -2576,14 +2578,15 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 
        /* LP0 register values */
        for_each_intel_crtc(dev, intel_crtc) {
+               const struct intel_crtc_state *cstate =
+                       to_intel_crtc_state(intel_crtc->base.state);
                enum pipe pipe = intel_crtc->pipe;
-               const struct intel_wm_level *r =
-                       &intel_crtc->wm.active.wm[0];
+               const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0];
 
                if (WARN_ON(!r->enable))
                        continue;
 
-               results->wm_linetime[pipe] = intel_crtc->wm.active.linetime;
+               results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime;
 
                results->wm_pipe[pipe] =
                        (r->pri_val << WM0_PIPE_PLANE_SHIFT) |
@@ -3567,10 +3570,10 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
        skl_allocate_pipe_ddb(cstate, config, ddb);
        skl_compute_pipe_wm(cstate, ddb, pipe_wm);
 
-       if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm)))
+       if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
                return false;
 
-       intel_crtc->wm.skl_active = *pipe_wm;
+       intel_crtc->wm.active.skl = *pipe_wm;
 
        return true;
 }
@@ -3648,7 +3651,8 @@ static void skl_update_wm(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct skl_wm_values *results = &dev_priv->wm.skl_results;
-       struct skl_pipe_wm pipe_wm = {};
+       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 = {};
 
 
@@ -3659,10 +3663,10 @@ static void skl_update_wm(struct drm_crtc *crtc)
 
        skl_compute_wm_global_parameters(dev, &config);
 
-       if (!skl_update_pipe_wm(crtc, &config, &results->ddb, &pipe_wm))
+       if (!skl_update_pipe_wm(crtc, &config, &results->ddb, pipe_wm))
                return;
 
-       skl_compute_wm_results(dev, &pipe_wm, results, intel_crtc);
+       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);
@@ -3711,7 +3715,6 @@ static void ilk_update_wm(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
-       struct intel_pipe_wm pipe_wm = {};
 
        WARN_ON(cstate->base.active != intel_crtc->active);
 
@@ -3727,12 +3730,13 @@ static void ilk_update_wm(struct drm_crtc *crtc)
                intel_wait_for_vblank(crtc->dev, intel_crtc->pipe);
        }
 
-       intel_compute_pipe_wm(cstate, &pipe_wm);
+       intel_compute_pipe_wm(cstate, &cstate->wm.optimal.ilk);
 
-       if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
-               return;
+       if (!memcmp(&intel_crtc->wm.active.ilk,
+                   &cstate->wm.optimal.ilk,
+                   sizeof(cstate->wm.optimal.ilk)));
 
-       intel_crtc->wm.active = pipe_wm;
+       intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
 
        ilk_program_watermarks(dev_priv);
 }
@@ -3787,7 +3791,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct skl_wm_values *hw = &dev_priv->wm.skl_hw;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct skl_pipe_wm *active = &intel_crtc->wm.skl_active;
+       struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+       struct skl_pipe_wm *active = &cstate->wm.optimal.skl;
        enum pipe pipe = intel_crtc->pipe;
        int level, i, max_level;
        uint32_t temp;
@@ -3831,6 +3836,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 
        temp = hw->plane_trans[pipe][PLANE_CURSOR];
        skl_pipe_wm_active_state(temp, active, true, true, i, 0);
+
+       intel_crtc->wm.active.skl = *active;
 }
 
 void skl_wm_get_hw_state(struct drm_device *dev)
@@ -3850,7 +3857,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct ilk_wm_values *hw = &dev_priv->wm.hw;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_pipe_wm *active = &intel_crtc->wm.active;
+       struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+       struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
        enum pipe pipe = intel_crtc->pipe;
        static const unsigned int wm0_pipe_reg[] = {
                [PIPE_A] = WM0_PIPEA_ILK,
@@ -3889,6 +3897,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
                for (level = 0; level <= max_level; level++)
                        active->wm[level].enable = true;
        }
+
+       intel_crtc->wm.active.ilk = *active;
 }
 
 #define _FW_WM(value, plane) \