drm/i915: Pre-calculate plane relative data rate
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 3 Mar 2022 19:12:01 +0000 (21:12 +0200)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 21 Mar 2022 15:48:39 +0000 (17:48 +0200)
Handle the plane relative data rate in exactly the same
way as we already handle the real data rate. Ie. pre-calculate
it during intel_plane_atomic_check_with_state(), and assign/clear
it for the Y plane as needed. This should guarantee that the
tracking is 100% consistent, and makes me have to think less
when the same apporach is used by both types of data rate.

We might even want to consider replacing the relative
data rate with the real data rate entirely, but it's not
clear if that will produce less optimal plane ddb
allocations. So for now lets keep using the current approach.

v2: Rebase due to async flip wm optimization

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-4-ville.syrjala@linux.intel.com
drivers/gpu/drm/i915/display/intel_atomic_plane.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/intel_pm.c

index b6c80824aea1a5fb9bdd6200347dacf7ef827920..3d87da283cfa8bd4db331ebbbdb8e08b1d0e8395 100644 (file)
@@ -193,6 +193,57 @@ unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
                fb->format->cpp[color_plane];
 }
 
+static bool
+use_min_ddb(const struct intel_crtc_state *crtc_state,
+           struct intel_plane *plane)
+{
+       struct drm_i915_private *i915 = to_i915(plane->base.dev);
+
+       return DISPLAY_VER(i915) >= 13 &&
+              crtc_state->uapi.async_flip &&
+              plane->async_flip;
+}
+
+static unsigned int
+intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
+                              const struct intel_plane_state *plane_state,
+                              int color_plane)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       int width, height;
+
+       if (plane->id == PLANE_CURSOR)
+               return 0;
+
+       if (!plane_state->uapi.visible)
+               return 0;
+
+       /*
+        * We calculate extra ddb based on ratio plane rate/total data rate
+        * in case, in some cases we should not allocate extra ddb for the plane,
+        * so do not count its data rate, if this is the case.
+        */
+       if (use_min_ddb(crtc_state, plane))
+               return 0;
+
+       /*
+        * Src coordinates are already rotated by 270 degrees for
+        * the 90/270 degree plane rotation cases (to match the
+        * GTT mapping), hence no need to account for rotation here.
+        */
+       width = drm_rect_width(&plane_state->uapi.src) >> 16;
+       height = drm_rect_height(&plane_state->uapi.src) >> 16;
+
+       /* UV plane does 1/2 pixel sub-sampling */
+       if (color_plane == 1) {
+               width /= 2;
+               height /= 2;
+       }
+
+       return width * height * fb->format->cpp[color_plane];
+}
+
 int intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
                               struct intel_plane *plane,
                               bool *need_cdclk_calc)
@@ -314,6 +365,8 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
        crtc_state->c8_planes &= ~BIT(plane->id);
        crtc_state->data_rate[plane->id] = 0;
        crtc_state->data_rate_y[plane->id] = 0;
+       crtc_state->rel_data_rate[plane->id] = 0;
+       crtc_state->rel_data_rate_y[plane->id] = 0;
        crtc_state->min_cdclk[plane->id] = 0;
 
        plane_state->uapi.visible = false;
@@ -545,9 +598,20 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
                        intel_plane_data_rate(new_crtc_state, new_plane_state, 0);
                new_crtc_state->data_rate[plane->id] =
                        intel_plane_data_rate(new_crtc_state, new_plane_state, 1);
+
+               new_crtc_state->rel_data_rate_y[plane->id] =
+                       intel_plane_relative_data_rate(new_crtc_state,
+                                                      new_plane_state, 0);
+               new_crtc_state->rel_data_rate[plane->id] =
+                       intel_plane_relative_data_rate(new_crtc_state,
+                                                      new_plane_state, 1);
        } else if (new_plane_state->uapi.visible) {
                new_crtc_state->data_rate[plane->id] =
                        intel_plane_data_rate(new_crtc_state, new_plane_state, 0);
+
+               new_crtc_state->rel_data_rate[plane->id] =
+                       intel_plane_relative_data_rate(new_crtc_state,
+                                                      new_plane_state, 0);
        }
 
        return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state,
index 853f943d5138d66ff4789a98faf6249b0549d7bb..39dbc7f69d4d3d3fde5238ae83f13d54badd6cc3 100644 (file)
@@ -781,6 +781,8 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc,
        fixup_plane_bitmasks(crtc_state);
        crtc_state->data_rate[plane->id] = 0;
        crtc_state->data_rate_y[plane->id] = 0;
+       crtc_state->rel_data_rate[plane->id] = 0;
+       crtc_state->rel_data_rate_y[plane->id] = 0;
        crtc_state->min_cdclk[plane->id] = 0;
 
        if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 &&
@@ -4815,6 +4817,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
                        crtc_state->active_planes &= ~BIT(plane->id);
                        crtc_state->update_planes |= BIT(plane->id);
                        crtc_state->data_rate[plane->id] = 0;
+                       crtc_state->rel_data_rate[plane->id] = 0;
                }
 
                plane_state->planar_slave = false;
@@ -4861,6 +4864,8 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
                crtc_state->update_planes |= BIT(linked->id);
                crtc_state->data_rate[linked->id] =
                        crtc_state->data_rate_y[plane->id];
+               crtc_state->rel_data_rate[linked->id] =
+                       crtc_state->rel_data_rate_y[plane->id];
                drm_dbg_kms(&dev_priv->drm, "Using %s as Y plane for %s\n",
                            linked->base.name, plane->base.name);
 
index 55ce91e4bb71e01c61a7d574431643796e3a06b2..96024f7d839d456875a86b8f3f16065a53788e2f 100644 (file)
@@ -1134,9 +1134,9 @@ struct intel_crtc_state {
        /* for planar Y */
        u32 data_rate_y[I915_MAX_PLANES];
 
-       /* FIXME unify with data_rate[] */
-       u64 plane_data_rate[I915_MAX_PLANES];
-       u64 uv_plane_data_rate[I915_MAX_PLANES];
+       /* FIXME unify with data_rate[]? */
+       u64 rel_data_rate[I915_MAX_PLANES];
+       u64 rel_data_rate_y[I915_MAX_PLANES];
 
        /* Gamma mode programmed on the pipe */
        u32 gamma_mode;
index 073a52e28a4d4fe1bf19a4fcb60b083dccaae610..34c381803632ed75224d4fab22573fc60322a62f 100644 (file)
@@ -4918,17 +4918,6 @@ static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes, bool
        return active_pipes & BIT(pipe) ? BIT(DBUF_S1) : 0;
 }
 
-static bool
-use_min_ddb(const struct intel_crtc_state *crtc_state,
-           struct intel_plane *plane)
-{
-       struct drm_i915_private *i915 = to_i915(plane->base.dev);
-
-       return DISPLAY_VER(i915) >= 13 &&
-              crtc_state->uapi.async_flip &&
-              plane->async_flip;
-}
-
 static bool
 use_minimal_wm0_only(const struct intel_crtc_state *crtc_state,
                     struct intel_plane *plane)
@@ -4941,134 +4930,24 @@ use_minimal_wm0_only(const struct intel_crtc_state *crtc_state,
 }
 
 static u64
-skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
-                            const struct intel_plane_state *plane_state,
-                            int color_plane)
+skl_total_relative_data_rate(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
-       const struct drm_framebuffer *fb = plane_state->hw.fb;
-       int width, height;
-
-       if (!plane_state->uapi.visible)
-               return 0;
-
-       if (plane->id == PLANE_CURSOR)
-               return 0;
-
-       /*
-        * We calculate extra ddb based on ratio plane rate/total data rate
-        * in case, in some cases we should not allocate extra ddb for the plane,
-        * so do not count its data rate, if this is the case.
-        */
-       if (use_min_ddb(crtc_state, plane))
-               return 0;
-
-       if (color_plane == 1 &&
-           !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
-               return 0;
-
-       /*
-        * Src coordinates are already rotated by 270 degrees for
-        * the 90/270 degree plane rotation cases (to match the
-        * GTT mapping), hence no need to account for rotation here.
-        */
-       width = drm_rect_width(&plane_state->uapi.src) >> 16;
-       height = drm_rect_height(&plane_state->uapi.src) >> 16;
-
-       /* UV plane does 1/2 pixel sub-sampling */
-       if (color_plane == 1) {
-               width /= 2;
-               height /= 2;
-       }
-
-       return width * height * fb->format->cpp[color_plane];
-}
-
-static u64
-skl_get_total_relative_data_rate(struct intel_atomic_state *state,
-                                struct intel_crtc *crtc)
-{
-       struct intel_crtc_state *crtc_state =
-               intel_atomic_get_new_crtc_state(state, crtc);
-       const struct intel_plane_state *plane_state;
-       struct intel_plane *plane;
-       u64 total_data_rate = 0;
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
        enum plane_id plane_id;
-       int i;
-
-       /* Calculate and cache data rate for each plane */
-       for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
-               if (plane->pipe != crtc->pipe)
-                       continue;
-
-               plane_id = plane->id;
-
-               /* packed/y */
-               crtc_state->plane_data_rate[plane_id] =
-                       skl_plane_relative_data_rate(crtc_state, plane_state, 0);
-
-               /* uv-plane */
-               crtc_state->uv_plane_data_rate[plane_id] =
-                       skl_plane_relative_data_rate(crtc_state, plane_state, 1);
-       }
+       u64 data_rate = 0;
 
        for_each_plane_id_on_crtc(crtc, plane_id) {
-               total_data_rate += crtc_state->plane_data_rate[plane_id];
-               total_data_rate += crtc_state->uv_plane_data_rate[plane_id];
-       }
-
-       return total_data_rate;
-}
-
-static u64
-icl_get_total_relative_data_rate(struct intel_atomic_state *state,
-                                struct intel_crtc *crtc)
-{
-       struct intel_crtc_state *crtc_state =
-               intel_atomic_get_new_crtc_state(state, crtc);
-       const struct intel_plane_state *plane_state;
-       struct intel_plane *plane;
-       u64 total_data_rate = 0;
-       enum plane_id plane_id;
-       int i;
-
-       /* Calculate and cache data rate for each plane */
-       for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
-               if (plane->pipe != crtc->pipe)
+               if (plane_id == PLANE_CURSOR)
                        continue;
 
-               plane_id = plane->id;
+               data_rate += crtc_state->rel_data_rate[plane_id];
 
-               if (!plane_state->planar_linked_plane) {
-                       crtc_state->plane_data_rate[plane_id] =
-                               skl_plane_relative_data_rate(crtc_state, plane_state, 0);
-               } else {
-                       enum plane_id y_plane_id;
-
-                       /*
-                        * The slave plane might not iterate in
-                        * intel_atomic_crtc_state_for_each_plane_state(),
-                        * and needs the master plane state which may be
-                        * NULL if we try get_new_plane_state(), so we
-                        * always calculate from the master.
-                        */
-                       if (plane_state->planar_slave)
-                               continue;
-
-                       /* Y plane rate is calculated on the slave */
-                       y_plane_id = plane_state->planar_linked_plane->id;
-                       crtc_state->plane_data_rate[y_plane_id] =
-                               skl_plane_relative_data_rate(crtc_state, plane_state, 0);
-
-                       crtc_state->plane_data_rate[plane_id] =
-                               skl_plane_relative_data_rate(crtc_state, plane_state, 1);
-               }
+               if (DISPLAY_VER(i915) < 11)
+                       data_rate += crtc_state->rel_data_rate_y[plane_id];
        }
 
-       for_each_plane_id_on_crtc(crtc, plane_id)
-               total_data_rate += crtc_state->plane_data_rate[plane_id];
-
-       return total_data_rate;
+       return data_rate;
 }
 
 const struct skl_wm_level *
@@ -5186,11 +5065,6 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
        if (!crtc_state->hw.active)
                return 0;
 
-       if (DISPLAY_VER(dev_priv) >= 11)
-               iter.data_rate = icl_get_total_relative_data_rate(state, crtc);
-       else
-               iter.data_rate = skl_get_total_relative_data_rate(state, crtc);
-
        iter.size = skl_ddb_entry_size(alloc);
        if (iter.size == 0)
                return 0;
@@ -5201,6 +5075,8 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
        skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR],
                           alloc->end - iter.total[PLANE_CURSOR], alloc->end);
 
+       iter.data_rate = skl_total_relative_data_rate(crtc_state);
+
        /*
         * Find the highest watermark level for which we can satisfy the block
         * requirement of active planes.
@@ -5255,13 +5131,19 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
                if (plane_id == PLANE_CURSOR)
                        continue;
 
-               iter.total[plane_id] =
-                       skl_allocate_plane_ddb(&iter, &wm->wm[level],
-                                              crtc_state->plane_data_rate[plane_id]);
-
-               iter.uv_total[plane_id] =
-                       skl_allocate_plane_ddb(&iter, &wm->uv_wm[level],
-                                              crtc_state->uv_plane_data_rate[plane_id]);
+               if (DISPLAY_VER(dev_priv) < 11 &&
+                   crtc_state->nv12_planes & BIT(plane_id)) {
+                       iter.total[plane_id] =
+                               skl_allocate_plane_ddb(&iter, &wm->wm[level],
+                                                      crtc_state->rel_data_rate_y[plane_id]);
+                       iter.uv_total[plane_id] =
+                               skl_allocate_plane_ddb(&iter, &wm->uv_wm[level],
+                                                      crtc_state->rel_data_rate[plane_id]);
+               } else {
+                       iter.total[plane_id] =
+                               skl_allocate_plane_ddb(&iter, &wm->wm[level],
+                                                      crtc_state->rel_data_rate[plane_id]);
+               }
        }
        drm_WARN_ON(&dev_priv->drm, iter.size != 0 || iter.data_rate != 0);
 
@@ -5281,15 +5163,18 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
                            DISPLAY_VER(dev_priv) >= 11 && iter.uv_total[plane_id]);
 
                /* Leave disabled planes at (0,0) */
-               if (iter.total[plane_id])
-                       iter.start = skl_ddb_entry_init(ddb, iter.start,
-                                                       iter.start + iter.total[plane_id]);
-
-               if (iter.uv_total[plane_id]) {
-                       /* hardware wants these swapped */
-                       *ddb_y = *ddb;
-                       iter.start = skl_ddb_entry_init(ddb, iter.start,
-                                                       iter.start + iter.uv_total[plane_id]);
+               if (DISPLAY_VER(dev_priv) < 11 &&
+                   crtc_state->nv12_planes & BIT(plane_id)) {
+                       if (iter.total[plane_id])
+                               iter.start = skl_ddb_entry_init(ddb_y, iter.start,
+                                                               iter.start + iter.total[plane_id]);
+                       if (iter.uv_total[plane_id])
+                               iter.start = skl_ddb_entry_init(ddb, iter.start,
+                                                               iter.start + iter.uv_total[plane_id]);
+               } else {
+                       if (iter.total[plane_id])
+                               iter.start = skl_ddb_entry_init(ddb, iter.start,
+                                                               iter.start + iter.total[plane_id]);
                }
        }