]> Git Repo - J-linux.git/blobdiff - drivers/gpu/drm/i915/intel_pm.c
Merge tag 'drm-next-2021-04-28' of git://anongit.freedesktop.org/drm/drm
[J-linux.git] / drivers / gpu / drm / i915 / intel_pm.c
index 4ba20f959a71a4a09a5bf57eaf77bf5d92d840e5..0e2501b7fc2775d124ca4b7d5dc02c16ecbf33bc 100644 (file)
@@ -38,6 +38,7 @@
 #include "display/intel_display_types.h"
 #include "display/intel_fbc.h"
 #include "display/intel_sprite.h"
+#include "display/skl_universal_plane.h"
 
 #include "gt/intel_llc.h"
 
@@ -2338,7 +2339,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
 
        if (IS_I945GM(dev_priv))
                wm_info = &i945_wm_info;
-       else if (!IS_GEN(dev_priv, 2))
+       else if (!IS_DISPLAY_VER(dev_priv, 2))
                wm_info = &i915_wm_info;
        else
                wm_info = &i830_a_wm_info;
@@ -2352,7 +2353,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
                        crtc->base.primary->state->fb;
                int cpp;
 
-               if (IS_GEN(dev_priv, 2))
+               if (IS_DISPLAY_VER(dev_priv, 2))
                        cpp = 4;
                else
                        cpp = fb->format->cpp[0];
@@ -2367,7 +2368,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
                        planea_wm = wm_info->max_wm;
        }
 
-       if (IS_GEN(dev_priv, 2))
+       if (IS_DISPLAY_VER(dev_priv, 2))
                wm_info = &i830_bc_wm_info;
 
        fifo_size = dev_priv->display.get_fifo_size(dev_priv, PLANE_B);
@@ -2379,7 +2380,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
                        crtc->base.primary->state->fb;
                int cpp;
 
-               if (IS_GEN(dev_priv, 2))
+               if (IS_DISPLAY_VER(dev_priv, 2))
                        cpp = 4;
                else
                        cpp = fb->format->cpp[0];
@@ -2651,9 +2652,9 @@ static u32 ilk_compute_fbc_wm(const struct intel_crtc_state *crtc_state,
 static unsigned int
 ilk_display_fifo_size(const struct drm_i915_private *dev_priv)
 {
-       if (INTEL_GEN(dev_priv) >= 8)
+       if (DISPLAY_VER(dev_priv) >= 8)
                return 3072;
-       else if (INTEL_GEN(dev_priv) >= 7)
+       else if (DISPLAY_VER(dev_priv) >= 7)
                return 768;
        else
                return 512;
@@ -2663,10 +2664,10 @@ static unsigned int
 ilk_plane_wm_reg_max(const struct drm_i915_private *dev_priv,
                     int level, bool is_sprite)
 {
-       if (INTEL_GEN(dev_priv) >= 8)
+       if (DISPLAY_VER(dev_priv) >= 8)
                /* BDW primary/sprite plane watermarks */
                return level == 0 ? 255 : 2047;
-       else if (INTEL_GEN(dev_priv) >= 7)
+       else if (DISPLAY_VER(dev_priv) >= 7)
                /* IVB/HSW primary/sprite plane watermarks */
                return level == 0 ? 127 : 1023;
        else if (!is_sprite)
@@ -2680,7 +2681,7 @@ ilk_plane_wm_reg_max(const struct drm_i915_private *dev_priv,
 static unsigned int
 ilk_cursor_wm_reg_max(const struct drm_i915_private *dev_priv, int level)
 {
-       if (INTEL_GEN(dev_priv) >= 7)
+       if (DISPLAY_VER(dev_priv) >= 7)
                return level == 0 ? 63 : 255;
        else
                return level == 0 ? 31 : 63;
@@ -2688,7 +2689,7 @@ ilk_cursor_wm_reg_max(const struct drm_i915_private *dev_priv, int level)
 
 static unsigned int ilk_fbc_wm_reg_max(const struct drm_i915_private *dev_priv)
 {
-       if (INTEL_GEN(dev_priv) >= 8)
+       if (DISPLAY_VER(dev_priv) >= 8)
                return 31;
        else
                return 15;
@@ -2716,7 +2717,7 @@ static unsigned int ilk_plane_wm_max(const struct drm_i915_private *dev_priv,
                 * FIFO size is only half of the self
                 * refresh FIFO size on ILK/SNB.
                 */
-               if (INTEL_GEN(dev_priv) <= 6)
+               if (DISPLAY_VER(dev_priv) <= 6)
                        fifo_size /= 2;
        }
 
@@ -2851,7 +2852,7 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
 {
        struct intel_uncore *uncore = &dev_priv->uncore;
 
-       if (INTEL_GEN(dev_priv) >= 9) {
+       if (DISPLAY_VER(dev_priv) >= 9) {
                u32 val;
                int ret, i;
                int level, max_level = ilk_wm_max_level(dev_priv);
@@ -2943,14 +2944,14 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
                wm[2] = (sskpd >> 12) & 0xFF;
                wm[3] = (sskpd >> 20) & 0x1FF;
                wm[4] = (sskpd >> 32) & 0x1FF;
-       } else if (INTEL_GEN(dev_priv) >= 6) {
+       } else if (DISPLAY_VER(dev_priv) >= 6) {
                u32 sskpd = intel_uncore_read(uncore, MCH_SSKPD);
 
                wm[0] = (sskpd >> SSKPD_WM0_SHIFT) & SSKPD_WM_MASK;
                wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK;
                wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK;
                wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK;
-       } else if (INTEL_GEN(dev_priv) >= 5) {
+       } else if (DISPLAY_VER(dev_priv) >= 5) {
                u32 mltr = intel_uncore_read(uncore, MLTR_ILK);
 
                /* ILK primary LP0 latency is 700 ns */
@@ -2966,7 +2967,7 @@ static void intel_fixup_spr_wm_latency(struct drm_i915_private *dev_priv,
                                       u16 wm[5])
 {
        /* ILK sprite LP0 latency is 1300 ns */
-       if (IS_GEN(dev_priv, 5))
+       if (IS_DISPLAY_VER(dev_priv, 5))
                wm[0] = 13;
 }
 
@@ -2974,18 +2975,18 @@ static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv,
                                       u16 wm[5])
 {
        /* ILK cursor LP0 latency is 1300 ns */
-       if (IS_GEN(dev_priv, 5))
+       if (IS_DISPLAY_VER(dev_priv, 5))
                wm[0] = 13;
 }
 
 int ilk_wm_max_level(const struct drm_i915_private *dev_priv)
 {
        /* how many WM levels are we expecting */
-       if (INTEL_GEN(dev_priv) >= 9)
+       if (DISPLAY_VER(dev_priv) >= 9)
                return 7;
        else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                return 4;
-       else if (INTEL_GEN(dev_priv) >= 6)
+       else if (DISPLAY_VER(dev_priv) >= 6)
                return 3;
        else
                return 2;
@@ -3011,7 +3012,7 @@ static void intel_print_wm_latency(struct drm_i915_private *dev_priv,
                 * - latencies are in us on gen9.
                 * - before then, WM1+ latency values are in 0.5us units
                 */
-               if (INTEL_GEN(dev_priv) >= 9)
+               if (DISPLAY_VER(dev_priv) >= 9)
                        latency *= 10;
                else if (level > 0)
                        latency *= 5;
@@ -3104,7 +3105,7 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
        intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
        intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
 
-       if (IS_GEN(dev_priv, 6)) {
+       if (IS_DISPLAY_VER(dev_priv, 6)) {
                snb_wm_latency_quirk(dev_priv);
                snb_wm_lp3_irq_quirk(dev_priv);
        }
@@ -3175,7 +3176,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *crtc_state)
        usable_level = max_level;
 
        /* ILK/SNB: LP2+ watermarks only w/o sprites */
-       if (INTEL_GEN(dev_priv) <= 6 && pipe_wm->sprites_enabled)
+       if (DISPLAY_VER(dev_priv) <= 6 && pipe_wm->sprites_enabled)
                usable_level = 1;
 
        /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
@@ -3317,12 +3318,12 @@ static void ilk_wm_merge(struct drm_i915_private *dev_priv,
        int last_enabled_level = max_level;
 
        /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
-       if ((INTEL_GEN(dev_priv) <= 6 || IS_IVYBRIDGE(dev_priv)) &&
+       if ((DISPLAY_VER(dev_priv) <= 6 || IS_IVYBRIDGE(dev_priv)) &&
            config->num_pipes_active > 1)
                last_enabled_level = 0;
 
        /* ILK: FBC WM must be disabled always */
-       merged->fbc_wm_enabled = INTEL_GEN(dev_priv) >= 6;
+       merged->fbc_wm_enabled = DISPLAY_VER(dev_priv) >= 6;
 
        /* merge each WM1+ level */
        for (level = 1; level <= max_level; level++) {
@@ -3353,7 +3354,7 @@ static void ilk_wm_merge(struct drm_i915_private *dev_priv,
         * What we should check here is whether FBC can be
         * enabled sometime later.
         */
-       if (IS_GEN(dev_priv, 5) && !merged->fbc_wm_enabled &&
+       if (IS_DISPLAY_VER(dev_priv, 5) && !merged->fbc_wm_enabled &&
            intel_fbc_is_active(dev_priv)) {
                for (level = 2; level <= max_level; level++) {
                        struct intel_wm_level *wm = &merged->wm[level];
@@ -3410,7 +3411,7 @@ static void ilk_compute_wm_results(struct drm_i915_private *dev_priv,
                if (r->enable)
                        results->wm_lp[wm_lp - 1] |= WM1_LP_SR_EN;
 
-               if (INTEL_GEN(dev_priv) >= 8)
+               if (DISPLAY_VER(dev_priv) >= 8)
                        results->wm_lp[wm_lp - 1] |=
                                r->fbc_val << WM1_LP_FBC_SHIFT_BDW;
                else
@@ -3421,7 +3422,7 @@ static void ilk_compute_wm_results(struct drm_i915_private *dev_priv,
                 * Always set WM1S_LP_EN when spr_val != 0, even if the
                 * level is disabled. Doing otherwise could cause underruns.
                 */
-               if (INTEL_GEN(dev_priv) <= 6 && r->spr_val) {
+               if (DISPLAY_VER(dev_priv) <= 6 && r->spr_val) {
                        drm_WARN_ON(&dev_priv->drm, wm_lp != 1);
                        results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
                } else
@@ -3611,7 +3612,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
            previous->wm_lp_spr[0] != results->wm_lp_spr[0])
                intel_uncore_write(&dev_priv->uncore, WM1S_LP_ILK, results->wm_lp_spr[0]);
 
-       if (INTEL_GEN(dev_priv) >= 7) {
+       if (DISPLAY_VER(dev_priv) >= 7) {
                if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
                        intel_uncore_write(&dev_priv->uncore, WM2S_LP_IVB, results->wm_lp_spr[1]);
                if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
@@ -3659,14 +3660,14 @@ static bool skl_needs_memory_bw_wa(struct drm_i915_private *dev_priv)
 static bool
 intel_has_sagv(struct drm_i915_private *dev_priv)
 {
-       return (IS_GEN9_BC(dev_priv) || INTEL_GEN(dev_priv) >= 10) &&
+       return (IS_GEN9_BC(dev_priv) || DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) &&
                dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED;
 }
 
 static void
 skl_setup_sagv_block_time(struct drm_i915_private *dev_priv)
 {
-       if (INTEL_GEN(dev_priv) >= 12) {
+       if (DISPLAY_VER(dev_priv) >= 12) {
                u32 val = 0;
                int ret;
 
@@ -3679,17 +3680,17 @@ skl_setup_sagv_block_time(struct drm_i915_private *dev_priv)
                }
 
                drm_dbg(&dev_priv->drm, "Couldn't read SAGV block time!\n");
-       } else if (IS_GEN(dev_priv, 11)) {
+       } else if (IS_DISPLAY_VER(dev_priv, 11)) {
                dev_priv->sagv_block_time_us = 10;
                return;
-       } else if (IS_GEN(dev_priv, 10)) {
+       } else if (IS_DISPLAY_VER(dev_priv, 10)) {
                dev_priv->sagv_block_time_us = 20;
                return;
-       } else if (IS_GEN(dev_priv, 9)) {
+       } else if (IS_DISPLAY_VER(dev_priv, 9)) {
                dev_priv->sagv_block_time_us = 30;
                return;
        } else {
-               MISSING_CASE(INTEL_GEN(dev_priv));
+               MISSING_CASE(DISPLAY_VER(dev_priv));
        }
 
        /* Default to an unusable block time */
@@ -3796,7 +3797,7 @@ void intel_sagv_pre_plane_update(struct intel_atomic_state *state)
        if (!new_bw_state)
                return;
 
-       if (INTEL_GEN(dev_priv) < 11 && !intel_can_enable_sagv(dev_priv, new_bw_state)) {
+       if (DISPLAY_VER(dev_priv) < 11 && !intel_can_enable_sagv(dev_priv, new_bw_state)) {
                intel_disable_sagv(dev_priv);
                return;
        }
@@ -3847,7 +3848,7 @@ void intel_sagv_post_plane_update(struct intel_atomic_state *state)
        if (!new_bw_state)
                return;
 
-       if (INTEL_GEN(dev_priv) < 11 && intel_can_enable_sagv(dev_priv, new_bw_state)) {
+       if (DISPLAY_VER(dev_priv) < 11 && intel_can_enable_sagv(dev_priv, new_bw_state)) {
                intel_enable_sagv(dev_priv);
                return;
        }
@@ -3875,6 +3876,7 @@ static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state)
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum plane_id plane_id;
+       int max_level = INT_MAX;
 
        if (!intel_has_sagv(dev_priv))
                return false;
@@ -3891,20 +3893,31 @@ static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state)
                int level;
 
                /* Skip this plane if it's not enabled */
-               if (!wm->wm[0].plane_en)
+               if (!wm->wm[0].enable)
                        continue;
 
                /* Find the highest enabled wm level for this plane */
                for (level = ilk_wm_max_level(dev_priv);
-                    !wm->wm[level].plane_en; --level)
+                    !wm->wm[level].enable; --level)
                     { }
 
+               /* Highest common enabled wm level for all planes */
+               max_level = min(level, max_level);
+       }
+
+       /* No enabled planes? */
+       if (max_level == INT_MAX)
+               return true;
+
+       for_each_plane_id_on_crtc(crtc, plane_id) {
+               const struct skl_plane_wm *wm =
+                       &crtc_state->wm.skl.optimal.planes[plane_id];
+
                /*
-                * If any of the planes on this pipe don't enable wm levels that
-                * incur memory latencies higher than sagv_block_time_us we
-                * can't enable SAGV.
+                * All enabled planes must have enabled a common wm level that
+                * can tolerate memory latencies higher than sagv_block_time_us
                 */
-               if (!wm->wm[level].can_sagv)
+               if (wm->wm[0].enable && !wm->wm[max_level].can_sagv)
                        return false;
        }
 
@@ -3920,12 +3933,10 @@ static bool tgl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state)
                return true;
 
        for_each_plane_id_on_crtc(crtc, plane_id) {
-               const struct skl_ddb_entry *plane_alloc =
-                       &crtc_state->wm.skl.plane_ddb_y[plane_id];
                const struct skl_plane_wm *wm =
                        &crtc_state->wm.skl.optimal.planes[plane_id];
 
-               if (skl_ddb_entry_size(plane_alloc) < wm->sagv_wm0.min_ddb_alloc)
+               if (wm->wm[0].enable && !wm->sagv.wm0.enable)
                        return false;
        }
 
@@ -3937,7 +3948,7 @@ static bool intel_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-       if (INTEL_GEN(dev_priv) >= 12)
+       if (DISPLAY_VER(dev_priv) >= 12)
                return tgl_crtc_can_enable_sagv(crtc_state);
        else
                return skl_crtc_can_enable_sagv(crtc_state);
@@ -3946,7 +3957,7 @@ static bool intel_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state
 bool intel_can_enable_sagv(struct drm_i915_private *dev_priv,
                           const struct intel_bw_state *bw_state)
 {
-       if (INTEL_GEN(dev_priv) < 11 &&
+       if (DISPLAY_VER(dev_priv) < 11 &&
            bw_state->active_pipes && !is_power_of_2(bw_state->active_pipes))
                return false;
 
@@ -3999,7 +4010,7 @@ static int intel_compute_sagv_mask(struct intel_atomic_state *state)
                 * latter from the plane commit hooks (especially in the legacy
                 * cursor case)
                 */
-               pipe_wm->use_sagv_wm = INTEL_GEN(dev_priv) >= 12 &&
+               pipe_wm->use_sagv_wm = DISPLAY_VER(dev_priv) >= 12 &&
                                       intel_can_enable_sagv(dev_priv, new_bw_state);
        }
 
@@ -4023,7 +4034,7 @@ static int intel_dbuf_size(struct drm_i915_private *dev_priv)
 
        drm_WARN_ON(&dev_priv->drm, ddb_size == 0);
 
-       if (INTEL_GEN(dev_priv) < 11)
+       if (DISPLAY_VER(dev_priv) < 11)
                return ddb_size - 4; /* 4 blocks for bypass path allocation */
 
        return ddb_size;
@@ -4278,7 +4289,7 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv,
                                              val & PLANE_CTL_ORDER_RGBX,
                                              val & PLANE_CTL_ALPHA_MASK);
 
-       if (INTEL_GEN(dev_priv) >= 11) {
+       if (DISPLAY_VER(dev_priv) >= 11) {
                val = intel_uncore_read(&dev_priv->uncore, PLANE_BUF_CFG(pipe, plane_id));
                skl_ddb_entry_init_from_hw(dev_priv, ddb_y, val);
        } else {
@@ -4602,9 +4613,9 @@ static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes)
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
 
-       if (IS_GEN(dev_priv, 12))
+       if (IS_DISPLAY_VER(dev_priv, 12))
                return tgl_compute_dbuf_slices(pipe, active_pipes);
-       else if (IS_GEN(dev_priv, 11))
+       else if (IS_DISPLAY_VER(dev_priv, 11))
                return icl_compute_dbuf_slices(pipe, active_pipes);
        /*
         * For anything else just return one slice yet.
@@ -4746,20 +4757,61 @@ icl_get_total_relative_data_rate(struct intel_atomic_state *state,
        return total_data_rate;
 }
 
-static const struct skl_wm_level *
-skl_plane_wm_level(const struct intel_crtc_state *crtc_state,
+const struct skl_wm_level *
+skl_plane_wm_level(const struct skl_pipe_wm *pipe_wm,
                   enum plane_id plane_id,
                   int level)
 {
-       const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
        const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
 
        if (level == 0 && pipe_wm->use_sagv_wm)
-               return &wm->sagv_wm0;
+               return &wm->sagv.wm0;
 
        return &wm->wm[level];
 }
 
+const struct skl_wm_level *
+skl_plane_trans_wm(const struct skl_pipe_wm *pipe_wm,
+                  enum plane_id plane_id)
+{
+       const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
+
+       if (pipe_wm->use_sagv_wm)
+               return &wm->sagv.trans_wm;
+
+       return &wm->trans_wm;
+}
+
+/*
+ * We only disable the watermarks for each plane if
+ * they exceed the ddb allocation of said plane. This
+ * is done so that we don't end up touching cursor
+ * watermarks needlessly when some other plane reduces
+ * our max possible watermark level.
+ *
+ * Bspec has this to say about the PLANE_WM enable bit:
+ * "All the watermarks at this level for all enabled
+ *  planes must be enabled before the level will be used."
+ * So this is actually safe to do.
+ */
+static void
+skl_check_wm_level(struct skl_wm_level *wm, u64 total)
+{
+       if (wm->min_ddb_alloc > total)
+               memset(wm, 0, sizeof(*wm));
+}
+
+static void
+skl_check_nv12_wm_level(struct skl_wm_level *wm, struct skl_wm_level *uv_wm,
+                       u64 total, u64 uv_total)
+{
+       if (wm->min_ddb_alloc > total ||
+           uv_wm->min_ddb_alloc > uv_total) {
+               memset(wm, 0, sizeof(*wm));
+               memset(uv_wm, 0, sizeof(*uv_wm));
+       }
+}
+
 static int
 skl_allocate_plane_ddb(struct intel_atomic_state *state,
                       struct intel_crtc *crtc)
@@ -4786,7 +4838,7 @@ skl_allocate_plane_ddb(struct intel_atomic_state *state,
        if (!crtc_state->hw.active)
                return 0;
 
-       if (INTEL_GEN(dev_priv) >= 11)
+       if (DISPLAY_VER(dev_priv) >= 11)
                total_data_rate =
                        icl_get_total_relative_data_rate(state, crtc);
        else
@@ -4900,7 +4952,7 @@ skl_allocate_plane_ddb(struct intel_atomic_state *state,
 
                /* Gen11+ uses a separate plane for UV watermarks */
                drm_WARN_ON(&dev_priv->drm,
-                           INTEL_GEN(dev_priv) >= 11 && uv_total[plane_id]);
+                           DISPLAY_VER(dev_priv) >= 11 && uv_total[plane_id]);
 
                /* Leave disabled planes at (0,0) */
                if (total[plane_id]) {
@@ -4927,45 +4979,33 @@ skl_allocate_plane_ddb(struct intel_atomic_state *state,
                        struct skl_plane_wm *wm =
                                &crtc_state->wm.skl.optimal.planes[plane_id];
 
-                       /*
-                        * We only disable the watermarks for each plane if
-                        * they exceed the ddb allocation of said plane. This
-                        * is done so that we don't end up touching cursor
-                        * watermarks needlessly when some other plane reduces
-                        * our max possible watermark level.
-                        *
-                        * Bspec has this to say about the PLANE_WM enable bit:
-                        * "All the watermarks at this level for all enabled
-                        *  planes must be enabled before the level will be used."
-                        * So this is actually safe to do.
-                        */
-                       if (wm->wm[level].min_ddb_alloc > total[plane_id] ||
-                           wm->uv_wm[level].min_ddb_alloc > uv_total[plane_id])
-                               memset(&wm->wm[level], 0, sizeof(wm->wm[level]));
+                       skl_check_nv12_wm_level(&wm->wm[level], &wm->uv_wm[level],
+                                               total[plane_id], uv_total[plane_id]);
 
                        /*
                         * Wa_1408961008:icl, ehl
                         * Underruns with WM1+ disabled
                         */
-                       if (IS_GEN(dev_priv, 11) &&
-                           level == 1 && wm->wm[0].plane_en) {
-                               wm->wm[level].plane_res_b = wm->wm[0].plane_res_b;
-                               wm->wm[level].plane_res_l = wm->wm[0].plane_res_l;
+                       if (IS_DISPLAY_VER(dev_priv, 11) &&
+                           level == 1 && wm->wm[0].enable) {
+                               wm->wm[level].blocks = wm->wm[0].blocks;
+                               wm->wm[level].lines = wm->wm[0].lines;
                                wm->wm[level].ignore_lines = wm->wm[0].ignore_lines;
                        }
                }
        }
 
        /*
-        * Go back and disable the transition watermark if it turns out we
-        * don't have enough DDB blocks for it.
+        * Go back and disable the transition and SAGV watermarks
+        * if it turns out we don't have enough DDB blocks for them.
         */
        for_each_plane_id_on_crtc(crtc, plane_id) {
                struct skl_plane_wm *wm =
                        &crtc_state->wm.skl.optimal.planes[plane_id];
 
-               if (wm->trans_wm.plane_res_b >= total[plane_id])
-                       memset(&wm->trans_wm, 0, sizeof(wm->trans_wm));
+               skl_check_wm_level(&wm->trans_wm, total[plane_id]);
+               skl_check_wm_level(&wm->sagv.wm0, total[plane_id]);
+               skl_check_wm_level(&wm->sagv.trans_wm, total[plane_id]);
        }
 
        return 0;
@@ -4990,7 +5030,7 @@ skl_wm_method1(const struct drm_i915_private *dev_priv, u32 pixel_rate,
        wm_intermediate_val = latency * pixel_rate * cpp;
        ret = div_fixed16(wm_intermediate_val, 1000 * dbuf_block_size);
 
-       if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+       if (DISPLAY_VER(dev_priv) >= 10)
                ret = add_fixed16_u32(ret, 1);
 
        return ret;
@@ -5070,7 +5110,7 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
        wp->cpp = format->cpp[color_plane];
        wp->plane_pixel_rate = plane_pixel_rate;
 
-       if (INTEL_GEN(dev_priv) >= 11 &&
+       if (DISPLAY_VER(dev_priv) >= 11 &&
            modifier == I915_FORMAT_MOD_Yf_TILED  && wp->cpp == 1)
                wp->dbuf_block_size = 256;
        else
@@ -5104,7 +5144,7 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
                                           wp->y_min_scanlines,
                                           wp->dbuf_block_size);
 
-               if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+               if (DISPLAY_VER(dev_priv) >= 10)
                        interm_pbpl++;
 
                wp->plane_blocks_per_line = div_fixed16(interm_pbpl,
@@ -5113,8 +5153,7 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
                interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line,
                                           wp->dbuf_block_size);
 
-               if (!wp->x_tiled ||
-                   INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+               if (!wp->x_tiled || DISPLAY_VER(dev_priv) >= 10)
                        interm_pbpl++;
 
                wp->plane_blocks_per_line = u32_to_fixed16(interm_pbpl);
@@ -5153,7 +5192,7 @@ skl_compute_plane_wm_params(const struct intel_crtc_state *crtc_state,
 
 static bool skl_wm_has_lines(struct drm_i915_private *dev_priv, int level)
 {
-       if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+       if (DISPLAY_VER(dev_priv) >= 10)
                return true;
 
        /* The number of lines are ignored for the level 0 watermark. */
@@ -5170,7 +5209,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
        struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
        uint_fixed_16_16_t method1, method2;
        uint_fixed_16_16_t selected_result;
-       u32 res_blocks, res_lines, min_ddb_alloc = 0;
+       u32 blocks, lines, min_ddb_alloc = 0;
 
        if (latency == 0) {
                /* reject it */
@@ -5206,8 +5245,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
                     (wp->plane_bytes_per_line / wp->dbuf_block_size < 1)) {
                        selected_result = method2;
                } else if (latency >= wp->linetime_us) {
-                       if (IS_GEN(dev_priv, 9) &&
-                           !IS_GEMINILAKE(dev_priv))
+                       if (IS_DISPLAY_VER(dev_priv, 9))
                                selected_result = min_fixed16(method1, method2);
                        else
                                selected_result = method2;
@@ -5216,24 +5254,22 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
                }
        }
 
-       res_blocks = fixed16_to_u32_round_up(selected_result) + 1;
-       res_lines = div_round_up_fixed16(selected_result,
-                                        wp->plane_blocks_per_line);
+       blocks = fixed16_to_u32_round_up(selected_result) + 1;
+       lines = div_round_up_fixed16(selected_result,
+                                    wp->plane_blocks_per_line);
 
        if (IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) {
                /* Display WA #1125: skl,bxt,kbl */
                if (level == 0 && wp->rc_surface)
-                       res_blocks +=
-                               fixed16_to_u32_round_up(wp->y_tile_minimum);
+                       blocks += fixed16_to_u32_round_up(wp->y_tile_minimum);
 
                /* Display WA #1126: skl,bxt,kbl */
                if (level >= 1 && level <= 7) {
                        if (wp->y_tiled) {
-                               res_blocks +=
-                                   fixed16_to_u32_round_up(wp->y_tile_minimum);
-                               res_lines += wp->y_min_scanlines;
+                               blocks += fixed16_to_u32_round_up(wp->y_tile_minimum);
+                               lines += wp->y_min_scanlines;
                        } else {
-                               res_blocks++;
+                               blocks++;
                        }
 
                        /*
@@ -5242,51 +5278,50 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
                         * Assumption in DDB algorithm optimization for special
                         * cases. Also covers Display WA #1125 for RC.
                         */
-                       if (result_prev->plane_res_b > res_blocks)
-                               res_blocks = result_prev->plane_res_b;
+                       if (result_prev->blocks > blocks)
+                               blocks = result_prev->blocks;
                }
        }
 
-       if (INTEL_GEN(dev_priv) >= 11) {
+       if (DISPLAY_VER(dev_priv) >= 11) {
                if (wp->y_tiled) {
                        int extra_lines;
 
-                       if (res_lines % wp->y_min_scanlines == 0)
+                       if (lines % wp->y_min_scanlines == 0)
                                extra_lines = wp->y_min_scanlines;
                        else
                                extra_lines = wp->y_min_scanlines * 2 -
-                                       res_lines % wp->y_min_scanlines;
+                                       lines % wp->y_min_scanlines;
 
-                       min_ddb_alloc = mul_round_up_u32_fixed16(res_lines + extra_lines,
+                       min_ddb_alloc = mul_round_up_u32_fixed16(lines + extra_lines,
                                                                 wp->plane_blocks_per_line);
                } else {
-                       min_ddb_alloc = res_blocks +
-                               DIV_ROUND_UP(res_blocks, 10);
+                       min_ddb_alloc = blocks + DIV_ROUND_UP(blocks, 10);
                }
        }
 
        if (!skl_wm_has_lines(dev_priv, level))
-               res_lines = 0;
+               lines = 0;
 
-       if (res_lines > 31) {
+       if (lines > 31) {
                /* reject it */
                result->min_ddb_alloc = U16_MAX;
                return;
        }
 
        /*
-        * If res_lines is valid, assume we can use this watermark level
+        * If lines is valid, assume we can use this watermark level
         * for now.  We'll come back and disable it after we calculate the
         * DDB allocation if it turns out we don't actually have enough
         * blocks to satisfy it.
         */
-       result->plane_res_b = res_blocks;
-       result->plane_res_l = res_lines;
+       result->blocks = blocks;
+       result->lines = lines;
        /* Bspec says: value >= plane ddb allocation -> invalid, hence the +1 here */
-       result->min_ddb_alloc = max(min_ddb_alloc, res_blocks) + 1;
-       result->plane_en = true;
+       result->min_ddb_alloc = max(min_ddb_alloc, blocks) + 1;
+       result->enable = true;
 
-       if (INTEL_GEN(dev_priv) < 12)
+       if (DISPLAY_VER(dev_priv) < 12)
                result->can_sagv = latency >= dev_priv->sagv_block_time_us;
 }
 
@@ -5315,7 +5350,7 @@ static void tgl_compute_sagv_wm(const struct intel_crtc_state *crtc_state,
                                struct skl_plane_wm *plane_wm)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
-       struct skl_wm_level *sagv_wm = &plane_wm->sagv_wm0;
+       struct skl_wm_level *sagv_wm = &plane_wm->sagv.wm0;
        struct skl_wm_level *levels = plane_wm->wm;
        unsigned int latency = dev_priv->wm.skl_latency[0] + dev_priv->sagv_block_time_us;
 
@@ -5324,14 +5359,13 @@ static void tgl_compute_sagv_wm(const struct intel_crtc_state *crtc_state,
                             sagv_wm);
 }
 
-static void skl_compute_transition_wm(const struct intel_crtc_state *crtc_state,
-                                     const struct skl_wm_params *wp,
-                                     struct skl_plane_wm *wm)
+static void skl_compute_transition_wm(struct drm_i915_private *dev_priv,
+                                     struct skl_wm_level *trans_wm,
+                                     const struct skl_wm_level *wm0,
+                                     const struct skl_wm_params *wp)
 {
-       struct drm_device *dev = crtc_state->uapi.crtc->dev;
-       const struct drm_i915_private *dev_priv = to_i915(dev);
        u16 trans_min, trans_amount, trans_y_tile_min;
-       u16 wm0_sel_res_b, trans_offset_b, res_blocks;
+       u16 wm0_blocks, trans_offset, blocks;
 
        /* Transition WM don't make any sense if ipc is disabled */
        if (!dev_priv->ipc_enabled)
@@ -5344,47 +5378,48 @@ static void skl_compute_transition_wm(const struct intel_crtc_state *crtc_state,
        if (IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv))
                return;
 
-       if (INTEL_GEN(dev_priv) >= 11)
+       if (DISPLAY_VER(dev_priv) >= 11)
                trans_min = 4;
        else
                trans_min = 14;
 
        /* Display WA #1140: glk,cnl */
-       if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
+       if (IS_DISPLAY_VER(dev_priv, 10))
                trans_amount = 0;
        else
                trans_amount = 10; /* This is configurable amount */
 
-       trans_offset_b = trans_min + trans_amount;
+       trans_offset = trans_min + trans_amount;
 
        /*
         * The spec asks for Selected Result Blocks for wm0 (the real value),
         * not Result Blocks (the integer value). Pay attention to the capital
-        * letters. The value wm_l0->plane_res_b is actually Result Blocks, but
+        * letters. The value wm_l0->blocks is actually Result Blocks, but
         * since Result Blocks is the ceiling of Selected Result Blocks plus 1,
         * and since we later will have to get the ceiling of the sum in the
         * transition watermarks calculation, we can just pretend Selected
         * Result Blocks is Result Blocks minus 1 and it should work for the
         * current platforms.
         */
-       wm0_sel_res_b = wm->wm[0].plane_res_b - 1;
+       wm0_blocks = wm0->blocks - 1;
 
        if (wp->y_tiled) {
                trans_y_tile_min =
                        (u16)mul_round_up_u32_fixed16(2, wp->y_tile_minimum);
-               res_blocks = max(wm0_sel_res_b, trans_y_tile_min) +
-                               trans_offset_b;
+               blocks = max(wm0_blocks, trans_y_tile_min) + trans_offset;
        } else {
-               res_blocks = wm0_sel_res_b + trans_offset_b;
+               blocks = wm0_blocks + trans_offset;
        }
+       blocks++;
 
        /*
         * Just assume we can enable the transition watermark.  After
         * computing the DDB we'll come back and disable it if that
         * assumption turns out to be false.
         */
-       wm->trans_wm.plane_res_b = res_blocks + 1;
-       wm->trans_wm.plane_en = true;
+       trans_wm->blocks = blocks;
+       trans_wm->min_ddb_alloc = max_t(u16, wm0->min_ddb_alloc, blocks + 1);
+       trans_wm->enable = true;
 }
 
 static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state,
@@ -5404,10 +5439,15 @@ static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state,
 
        skl_compute_wm_levels(crtc_state, &wm_params, wm->wm);
 
-       if (INTEL_GEN(dev_priv) >= 12)
+       skl_compute_transition_wm(dev_priv, &wm->trans_wm,
+                                 &wm->wm[0], &wm_params);
+
+       if (DISPLAY_VER(dev_priv) >= 12) {
                tgl_compute_sagv_wm(crtc_state, &wm_params, wm);
 
-       skl_compute_transition_wm(crtc_state, &wm_params, wm);
+               skl_compute_transition_wm(dev_priv, &wm->sagv.trans_wm,
+                                         &wm->sagv.wm0, &wm_params);
+       }
 
        return 0;
 }
@@ -5524,7 +5564,7 @@ static int skl_build_pipe_wm(struct intel_atomic_state *state,
                if (plane->pipe != crtc->pipe)
                        continue;
 
-               if (INTEL_GEN(dev_priv) >= 11)
+               if (DISPLAY_VER(dev_priv) >= 11)
                        ret = icl_build_plane_wm(crtc_state, plane_state);
                else
                        ret = skl_build_plane_wm(crtc_state, plane_state);
@@ -5554,12 +5594,12 @@ static void skl_write_wm_level(struct drm_i915_private *dev_priv,
 {
        u32 val = 0;
 
-       if (level->plane_en)
+       if (level->enable)
                val |= PLANE_WM_EN;
        if (level->ignore_lines)
                val |= PLANE_WM_IGNORE_LINES;
-       val |= level->plane_res_b;
-       val |= level->plane_res_l << PLANE_WM_LINES_SHIFT;
+       val |= level->blocks;
+       val |= level->lines << PLANE_WM_LINES_SHIFT;
 
        intel_de_write_fw(dev_priv, reg, val);
 }
@@ -5571,25 +5611,21 @@ void skl_write_plane_wm(struct intel_plane *plane,
        int level, max_level = ilk_wm_max_level(dev_priv);
        enum plane_id plane_id = plane->id;
        enum pipe pipe = plane->pipe;
-       const struct skl_plane_wm *wm =
-               &crtc_state->wm.skl.optimal.planes[plane_id];
+       const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
+       const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
        const struct skl_ddb_entry *ddb_y =
                &crtc_state->wm.skl.plane_ddb_y[plane_id];
        const struct skl_ddb_entry *ddb_uv =
                &crtc_state->wm.skl.plane_ddb_uv[plane_id];
 
-       for (level = 0; level <= max_level; level++) {
-               const struct skl_wm_level *wm_level;
-
-               wm_level = skl_plane_wm_level(crtc_state, plane_id, level);
-
+       for (level = 0; level <= max_level; level++)
                skl_write_wm_level(dev_priv, PLANE_WM(pipe, plane_id, level),
-                                  wm_level);
-       }
+                                  skl_plane_wm_level(pipe_wm, plane_id, level));
+
        skl_write_wm_level(dev_priv, PLANE_WM_TRANS(pipe, plane_id),
-                          &wm->trans_wm);
+                          skl_plane_trans_wm(pipe_wm, plane_id));
 
-       if (INTEL_GEN(dev_priv) >= 11) {
+       if (DISPLAY_VER(dev_priv) >= 11) {
                skl_ddb_entry_write(dev_priv,
                                    PLANE_BUF_CFG(pipe, plane_id), ddb_y);
                return;
@@ -5611,20 +5647,16 @@ void skl_write_cursor_wm(struct intel_plane *plane,
        int level, max_level = ilk_wm_max_level(dev_priv);
        enum plane_id plane_id = plane->id;
        enum pipe pipe = plane->pipe;
-       const struct skl_plane_wm *wm =
-               &crtc_state->wm.skl.optimal.planes[plane_id];
+       const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
        const struct skl_ddb_entry *ddb =
                &crtc_state->wm.skl.plane_ddb_y[plane_id];
 
-       for (level = 0; level <= max_level; level++) {
-               const struct skl_wm_level *wm_level;
-
-               wm_level = skl_plane_wm_level(crtc_state, plane_id, level);
-
+       for (level = 0; level <= max_level; level++)
                skl_write_wm_level(dev_priv, CUR_WM(pipe, level),
-                                  wm_level);
-       }
-       skl_write_wm_level(dev_priv, CUR_WM_TRANS(pipe), &wm->trans_wm);
+                                  skl_plane_wm_level(pipe_wm, plane_id, level));
+
+       skl_write_wm_level(dev_priv, CUR_WM_TRANS(pipe),
+                          skl_plane_trans_wm(pipe_wm, plane_id));
 
        skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe), ddb);
 }
@@ -5632,10 +5664,10 @@ void skl_write_cursor_wm(struct intel_plane *plane,
 bool skl_wm_level_equals(const struct skl_wm_level *l1,
                         const struct skl_wm_level *l2)
 {
-       return l1->plane_en == l2->plane_en &&
+       return l1->enable == l2->enable &&
                l1->ignore_lines == l2->ignore_lines &&
-               l1->plane_res_l == l2->plane_res_l &&
-               l1->plane_res_b == l2->plane_res_b;
+               l1->lines == l2->lines &&
+               l1->blocks == l2->blocks;
 }
 
 static bool skl_plane_wm_equals(struct drm_i915_private *dev_priv,
@@ -5654,7 +5686,9 @@ static bool skl_plane_wm_equals(struct drm_i915_private *dev_priv,
                        return false;
        }
 
-       return skl_wm_level_equals(&wm1->trans_wm, &wm2->trans_wm);
+       return skl_wm_level_equals(&wm1->trans_wm, &wm2->trans_wm) &&
+               skl_wm_level_equals(&wm1->sagv.wm0, &wm2->sagv.wm0) &&
+               skl_wm_level_equals(&wm1->sagv.trans_wm, &wm2->sagv.trans_wm);
 }
 
 static bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a,
@@ -5884,85 +5918,114 @@ skl_print_wm_changes(struct intel_atomic_state *state)
                                continue;
 
                        drm_dbg_kms(&dev_priv->drm,
-                                   "[PLANE:%d:%s]   level %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm"
-                                   " -> %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm\n",
+                                   "[PLANE:%d:%s]   level %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm"
+                                   " -> %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm\n",
                                    plane->base.base.id, plane->base.name,
-                                   enast(old_wm->wm[0].plane_en), enast(old_wm->wm[1].plane_en),
-                                   enast(old_wm->wm[2].plane_en), enast(old_wm->wm[3].plane_en),
-                                   enast(old_wm->wm[4].plane_en), enast(old_wm->wm[5].plane_en),
-                                   enast(old_wm->wm[6].plane_en), enast(old_wm->wm[7].plane_en),
-                                   enast(old_wm->trans_wm.plane_en),
-                                   enast(old_wm->sagv_wm0.plane_en),
-                                   enast(new_wm->wm[0].plane_en), enast(new_wm->wm[1].plane_en),
-                                   enast(new_wm->wm[2].plane_en), enast(new_wm->wm[3].plane_en),
-                                   enast(new_wm->wm[4].plane_en), enast(new_wm->wm[5].plane_en),
-                                   enast(new_wm->wm[6].plane_en), enast(new_wm->wm[7].plane_en),
-                                   enast(new_wm->trans_wm.plane_en),
-                                   enast(new_wm->sagv_wm0.plane_en));
+                                   enast(old_wm->wm[0].enable), enast(old_wm->wm[1].enable),
+                                   enast(old_wm->wm[2].enable), enast(old_wm->wm[3].enable),
+                                   enast(old_wm->wm[4].enable), enast(old_wm->wm[5].enable),
+                                   enast(old_wm->wm[6].enable), enast(old_wm->wm[7].enable),
+                                   enast(old_wm->trans_wm.enable),
+                                   enast(old_wm->sagv.wm0.enable),
+                                   enast(old_wm->sagv.trans_wm.enable),
+                                   enast(new_wm->wm[0].enable), enast(new_wm->wm[1].enable),
+                                   enast(new_wm->wm[2].enable), enast(new_wm->wm[3].enable),
+                                   enast(new_wm->wm[4].enable), enast(new_wm->wm[5].enable),
+                                   enast(new_wm->wm[6].enable), enast(new_wm->wm[7].enable),
+                                   enast(new_wm->trans_wm.enable),
+                                   enast(new_wm->sagv.wm0.enable),
+                                   enast(new_wm->sagv.trans_wm.enable));
 
                        drm_dbg_kms(&dev_priv->drm,
-                                   "[PLANE:%d:%s]   lines %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d"
-                                     " -> %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d\n",
+                                   "[PLANE:%d:%s]   lines %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d"
+                                     " -> %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d\n",
                                    plane->base.base.id, plane->base.name,
-                                   enast(old_wm->wm[0].ignore_lines), old_wm->wm[0].plane_res_l,
-                                   enast(old_wm->wm[1].ignore_lines), old_wm->wm[1].plane_res_l,
-                                   enast(old_wm->wm[2].ignore_lines), old_wm->wm[2].plane_res_l,
-                                   enast(old_wm->wm[3].ignore_lines), old_wm->wm[3].plane_res_l,
-                                   enast(old_wm->wm[4].ignore_lines), old_wm->wm[4].plane_res_l,
-                                   enast(old_wm->wm[5].ignore_lines), old_wm->wm[5].plane_res_l,
-                                   enast(old_wm->wm[6].ignore_lines), old_wm->wm[6].plane_res_l,
-                                   enast(old_wm->wm[7].ignore_lines), old_wm->wm[7].plane_res_l,
-                                   enast(old_wm->trans_wm.ignore_lines), old_wm->trans_wm.plane_res_l,
-                                   enast(old_wm->sagv_wm0.ignore_lines), old_wm->sagv_wm0.plane_res_l,
-
-                                   enast(new_wm->wm[0].ignore_lines), new_wm->wm[0].plane_res_l,
-                                   enast(new_wm->wm[1].ignore_lines), new_wm->wm[1].plane_res_l,
-                                   enast(new_wm->wm[2].ignore_lines), new_wm->wm[2].plane_res_l,
-                                   enast(new_wm->wm[3].ignore_lines), new_wm->wm[3].plane_res_l,
-                                   enast(new_wm->wm[4].ignore_lines), new_wm->wm[4].plane_res_l,
-                                   enast(new_wm->wm[5].ignore_lines), new_wm->wm[5].plane_res_l,
-                                   enast(new_wm->wm[6].ignore_lines), new_wm->wm[6].plane_res_l,
-                                   enast(new_wm->wm[7].ignore_lines), new_wm->wm[7].plane_res_l,
-                                   enast(new_wm->trans_wm.ignore_lines), new_wm->trans_wm.plane_res_l,
-                                   enast(new_wm->sagv_wm0.ignore_lines), new_wm->sagv_wm0.plane_res_l);
+                                   enast(old_wm->wm[0].ignore_lines), old_wm->wm[0].lines,
+                                   enast(old_wm->wm[1].ignore_lines), old_wm->wm[1].lines,
+                                   enast(old_wm->wm[2].ignore_lines), old_wm->wm[2].lines,
+                                   enast(old_wm->wm[3].ignore_lines), old_wm->wm[3].lines,
+                                   enast(old_wm->wm[4].ignore_lines), old_wm->wm[4].lines,
+                                   enast(old_wm->wm[5].ignore_lines), old_wm->wm[5].lines,
+                                   enast(old_wm->wm[6].ignore_lines), old_wm->wm[6].lines,
+                                   enast(old_wm->wm[7].ignore_lines), old_wm->wm[7].lines,
+                                   enast(old_wm->trans_wm.ignore_lines), old_wm->trans_wm.lines,
+                                   enast(old_wm->sagv.wm0.ignore_lines), old_wm->sagv.wm0.lines,
+                                   enast(old_wm->sagv.trans_wm.ignore_lines), old_wm->sagv.trans_wm.lines,
+                                   enast(new_wm->wm[0].ignore_lines), new_wm->wm[0].lines,
+                                   enast(new_wm->wm[1].ignore_lines), new_wm->wm[1].lines,
+                                   enast(new_wm->wm[2].ignore_lines), new_wm->wm[2].lines,
+                                   enast(new_wm->wm[3].ignore_lines), new_wm->wm[3].lines,
+                                   enast(new_wm->wm[4].ignore_lines), new_wm->wm[4].lines,
+                                   enast(new_wm->wm[5].ignore_lines), new_wm->wm[5].lines,
+                                   enast(new_wm->wm[6].ignore_lines), new_wm->wm[6].lines,
+                                   enast(new_wm->wm[7].ignore_lines), new_wm->wm[7].lines,
+                                   enast(new_wm->trans_wm.ignore_lines), new_wm->trans_wm.lines,
+                                   enast(new_wm->sagv.wm0.ignore_lines), new_wm->sagv.wm0.lines,
+                                   enast(new_wm->sagv.trans_wm.ignore_lines), new_wm->sagv.trans_wm.lines);
 
                        drm_dbg_kms(&dev_priv->drm,
-                                   "[PLANE:%d:%s]  blocks %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d"
-                                   " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d\n",
+                                   "[PLANE:%d:%s]  blocks %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
+                                   " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n",
                                    plane->base.base.id, plane->base.name,
-                                   old_wm->wm[0].plane_res_b, old_wm->wm[1].plane_res_b,
-                                   old_wm->wm[2].plane_res_b, old_wm->wm[3].plane_res_b,
-                                   old_wm->wm[4].plane_res_b, old_wm->wm[5].plane_res_b,
-                                   old_wm->wm[6].plane_res_b, old_wm->wm[7].plane_res_b,
-                                   old_wm->trans_wm.plane_res_b,
-                                   old_wm->sagv_wm0.plane_res_b,
-                                   new_wm->wm[0].plane_res_b, new_wm->wm[1].plane_res_b,
-                                   new_wm->wm[2].plane_res_b, new_wm->wm[3].plane_res_b,
-                                   new_wm->wm[4].plane_res_b, new_wm->wm[5].plane_res_b,
-                                   new_wm->wm[6].plane_res_b, new_wm->wm[7].plane_res_b,
-                                   new_wm->trans_wm.plane_res_b,
-                                   new_wm->sagv_wm0.plane_res_b);
+                                   old_wm->wm[0].blocks, old_wm->wm[1].blocks,
+                                   old_wm->wm[2].blocks, old_wm->wm[3].blocks,
+                                   old_wm->wm[4].blocks, old_wm->wm[5].blocks,
+                                   old_wm->wm[6].blocks, old_wm->wm[7].blocks,
+                                   old_wm->trans_wm.blocks,
+                                   old_wm->sagv.wm0.blocks,
+                                   old_wm->sagv.trans_wm.blocks,
+                                   new_wm->wm[0].blocks, new_wm->wm[1].blocks,
+                                   new_wm->wm[2].blocks, new_wm->wm[3].blocks,
+                                   new_wm->wm[4].blocks, new_wm->wm[5].blocks,
+                                   new_wm->wm[6].blocks, new_wm->wm[7].blocks,
+                                   new_wm->trans_wm.blocks,
+                                   new_wm->sagv.wm0.blocks,
+                                   new_wm->sagv.trans_wm.blocks);
 
                        drm_dbg_kms(&dev_priv->drm,
-                                   "[PLANE:%d:%s] min_ddb %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d"
-                                   " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d\n",
+                                   "[PLANE:%d:%s] min_ddb %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
+                                   " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n",
                                    plane->base.base.id, plane->base.name,
                                    old_wm->wm[0].min_ddb_alloc, old_wm->wm[1].min_ddb_alloc,
                                    old_wm->wm[2].min_ddb_alloc, old_wm->wm[3].min_ddb_alloc,
                                    old_wm->wm[4].min_ddb_alloc, old_wm->wm[5].min_ddb_alloc,
                                    old_wm->wm[6].min_ddb_alloc, old_wm->wm[7].min_ddb_alloc,
                                    old_wm->trans_wm.min_ddb_alloc,
-                                   old_wm->sagv_wm0.min_ddb_alloc,
+                                   old_wm->sagv.wm0.min_ddb_alloc,
+                                   old_wm->sagv.trans_wm.min_ddb_alloc,
                                    new_wm->wm[0].min_ddb_alloc, new_wm->wm[1].min_ddb_alloc,
                                    new_wm->wm[2].min_ddb_alloc, new_wm->wm[3].min_ddb_alloc,
                                    new_wm->wm[4].min_ddb_alloc, new_wm->wm[5].min_ddb_alloc,
                                    new_wm->wm[6].min_ddb_alloc, new_wm->wm[7].min_ddb_alloc,
                                    new_wm->trans_wm.min_ddb_alloc,
-                                   new_wm->sagv_wm0.min_ddb_alloc);
+                                   new_wm->sagv.wm0.min_ddb_alloc,
+                                   new_wm->sagv.trans_wm.min_ddb_alloc);
                }
        }
 }
 
+static bool skl_plane_selected_wm_equals(struct intel_plane *plane,
+                                        const struct skl_pipe_wm *old_pipe_wm,
+                                        const struct skl_pipe_wm *new_pipe_wm)
+{
+       struct drm_i915_private *i915 = to_i915(plane->base.dev);
+       int level, max_level = ilk_wm_max_level(i915);
+
+       for (level = 0; level <= max_level; level++) {
+               /*
+                * We don't check uv_wm as the hardware doesn't actually
+                * use it. It only gets used for calculating the required
+                * ddb allocation.
+                */
+               if (!skl_wm_level_equals(skl_plane_wm_level(old_pipe_wm, plane->id, level),
+                                        skl_plane_wm_level(new_pipe_wm, plane->id, level)))
+                       return false;
+       }
+
+       return skl_wm_level_equals(skl_plane_trans_wm(old_pipe_wm, plane->id),
+                                  skl_plane_trans_wm(new_pipe_wm, plane->id));
+}
+
 /*
  * To make sure the cursor watermark registers are always consistent
  * with our computed state the following scenario needs special
@@ -6008,9 +6071,9 @@ static int skl_wm_add_affected_planes(struct intel_atomic_state *state,
                 * with the software state.
                 */
                if (!drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi) &&
-                   skl_plane_wm_equals(dev_priv,
-                                       &old_crtc_state->wm.skl.optimal.planes[plane_id],
-                                       &new_crtc_state->wm.skl.optimal.planes[plane_id]))
+                   skl_plane_selected_wm_equals(plane,
+                                                &old_crtc_state->wm.skl.optimal,
+                                                &new_crtc_state->wm.skl.optimal))
                        continue;
 
                plane_state = intel_atomic_get_plane_state(state, plane);
@@ -6092,7 +6155,7 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
        ilk_wm_merge(dev_priv, &config, &max, &lp_wm_1_2);
 
        /* 5/6 split only in single pipe config on IVB+ */
-       if (INTEL_GEN(dev_priv) >= 7 &&
+       if (DISPLAY_VER(dev_priv) >= 7 &&
            config.num_pipes_active == 1 && config.sprites_enabled) {
                ilk_compute_wm_maximums(dev_priv, 1, &config, INTEL_DDB_PART_5_6, &max);
                ilk_wm_merge(dev_priv, &config, &max, &lp_wm_5_6);
@@ -6141,10 +6204,10 @@ static void ilk_optimize_watermarks(struct intel_atomic_state *state,
 
 static void skl_wm_level_from_reg_val(u32 val, struct skl_wm_level *level)
 {
-       level->plane_en = val & PLANE_WM_EN;
+       level->enable = val & PLANE_WM_EN;
        level->ignore_lines = val & PLANE_WM_IGNORE_LINES;
-       level->plane_res_b = val & PLANE_WM_BLOCKS_MASK;
-       level->plane_res_l = (val >> PLANE_WM_LINES_SHIFT) &
+       level->blocks = val & PLANE_WM_BLOCKS_MASK;
+       level->lines = (val >> PLANE_WM_LINES_SHIFT) &
                PLANE_WM_LINES_MASK;
 }
 
@@ -6171,19 +6234,18 @@ void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
                        skl_wm_level_from_reg_val(val, &wm->wm[level]);
                }
 
-               if (INTEL_GEN(dev_priv) >= 12)
-                       wm->sagv_wm0 = wm->wm[0];
-
                if (plane_id != PLANE_CURSOR)
                        val = intel_uncore_read(&dev_priv->uncore, PLANE_WM_TRANS(pipe, plane_id));
                else
                        val = intel_uncore_read(&dev_priv->uncore, CUR_WM_TRANS(pipe));
 
                skl_wm_level_from_reg_val(val, &wm->trans_wm);
-       }
 
-       if (!crtc->active)
-               return;
+               if (DISPLAY_VER(dev_priv) >= 12) {
+                       wm->sagv.wm0 = wm->wm[0];
+                       wm->sagv.trans_wm = wm->trans_wm;
+               }
+       }
 }
 
 void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
@@ -6706,7 +6768,7 @@ void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv)
        hw->wm_lp[2] = intel_uncore_read(&dev_priv->uncore, WM3_LP_ILK);
 
        hw->wm_lp_spr[0] = intel_uncore_read(&dev_priv->uncore, WM1S_LP_ILK);
-       if (INTEL_GEN(dev_priv) >= 7) {
+       if (DISPLAY_VER(dev_priv) >= 7) {
                hw->wm_lp_spr[1] = intel_uncore_read(&dev_priv->uncore, WM2S_LP_IVB);
                hw->wm_lp_spr[2] = intel_uncore_read(&dev_priv->uncore, WM3S_LP_IVB);
        }
@@ -7072,7 +7134,7 @@ static void gen12lp_init_clock_gating(struct drm_i915_private *dev_priv)
                           ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL);
 
        /* Wa_1409825376:tgl (pre-prod)*/
-       if (IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_B1))
+       if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B1))
                intel_uncore_write(&dev_priv->uncore, GEN9_CLKGATE_DIS_3, intel_uncore_read(&dev_priv->uncore, GEN9_CLKGATE_DIS_3) |
                           TGL_VRH_GATING_DIS);
 
@@ -7171,12 +7233,12 @@ static void kbl_init_clock_gating(struct drm_i915_private *dev_priv)
                   FBC_LLC_FULLY_OPEN);
 
        /* WaDisableSDEUnitClockGating:kbl */
-       if (IS_KBL_GT_REVID(dev_priv, 0, KBL_REVID_B0))
+       if (IS_KBL_GT_STEP(dev_priv, 0, STEP_B0))
                intel_uncore_write(&dev_priv->uncore, GEN8_UCGCTL6, intel_uncore_read(&dev_priv->uncore, GEN8_UCGCTL6) |
                           GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
 
        /* WaDisableGamClockGating:kbl */
-       if (IS_KBL_GT_REVID(dev_priv, 0, KBL_REVID_B0))
+       if (IS_KBL_GT_STEP(dev_priv, 0, STEP_B0))
                intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL1, intel_uncore_read(&dev_priv->uncore, GEN6_UCGCTL1) |
                           GEN6_GAMUNIT_CLOCK_GATE_DISABLE);
 
@@ -7621,15 +7683,15 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
                skl_setup_sagv_block_time(dev_priv);
 
        /* For FIFO watermark updates */
-       if (INTEL_GEN(dev_priv) >= 9) {
+       if (DISPLAY_VER(dev_priv) >= 9) {
                skl_setup_wm_latency(dev_priv);
                dev_priv->display.compute_global_watermarks = skl_compute_wm;
        } else if (HAS_PCH_SPLIT(dev_priv)) {
                ilk_setup_wm_latency(dev_priv);
 
-               if ((IS_GEN(dev_priv, 5) && dev_priv->wm.pri_latency[1] &&
+               if ((IS_DISPLAY_VER(dev_priv, 5) && dev_priv->wm.pri_latency[1] &&
                     dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
-                   (!IS_GEN(dev_priv, 5) && dev_priv->wm.pri_latency[0] &&
+                   (!IS_DISPLAY_VER(dev_priv, 5) && dev_priv->wm.pri_latency[0] &&
                     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
                        dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
                        dev_priv->display.compute_intermediate_wm =
@@ -7672,12 +7734,12 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
                        dev_priv->display.update_wm = NULL;
                } else
                        dev_priv->display.update_wm = pnv_update_wm;
-       } else if (IS_GEN(dev_priv, 4)) {
+       } else if (IS_DISPLAY_VER(dev_priv, 4)) {
                dev_priv->display.update_wm = i965_update_wm;
-       } else if (IS_GEN(dev_priv, 3)) {
+       } else if (IS_DISPLAY_VER(dev_priv, 3)) {
                dev_priv->display.update_wm = i9xx_update_wm;
                dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
-       } else if (IS_GEN(dev_priv, 2)) {
+       } else if (IS_DISPLAY_VER(dev_priv, 2)) {
                if (INTEL_NUM_PIPES(dev_priv) == 1) {
                        dev_priv->display.update_wm = i845_update_wm;
                        dev_priv->display.get_fifo_size = i845_get_fifo_size;
This page took 0.082797 seconds and 4 git commands to generate.