[Intel-gfx] [PATCH 5/9] drm/i915: Account for minimum ddb allocation restrictions
Matt Roper
matthew.d.roper at intel.com
Tue Jan 29 23:54:45 UTC 2019
On Fri, Dec 21, 2018 at 07:14:32PM +0200, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
>
> On icl+ bspec tells us to calculate a separate minimum ddb
> allocation from the blocks watermark. Both have to be checked
> against the actual ddb allocation, but since we do things the
> other way around we'll just calculat the minimum acceptable
> ddb allocation by taking the maximum of the two values.
>
> We'll also replace the memcmp() with a full trawl over the
> the watermarks so that it'll ignore the min_ddb_alloc
> because we can't directly read that out from the hw. I suppose
> we could reconstruct it from the other values, but I was
> too lazy to do that now.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
Matches the bspec.
Reviewed-by: Matt Roper <matthew.d.roper at intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 1 +
> drivers/gpu/drm/i915/intel_pm.c | 53 +++++++++++++++++++++++++++------
> 2 files changed, 45 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 815db160b966..7668d7197994 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1108,6 +1108,7 @@ struct skl_ddb_values {
> };
>
> struct skl_wm_level {
> + uint16_t min_ddb_alloc;
> uint16_t plane_res_b;
> uint8_t plane_res_l;
> bool plane_en;
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 3c5cba31f055..7464552c05f4 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -4371,8 +4371,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> continue;
>
> wm = &cstate->wm.skl.optimal.planes[plane_id];
> - blocks += wm->wm[level].plane_res_b + 1;
> - blocks += wm->uv_wm[level].plane_res_b + 1;
> + blocks += wm->wm[level].min_ddb_alloc;
> + blocks += wm->uv_wm[level].min_ddb_alloc;
> }
>
> if (blocks < alloc_size) {
> @@ -4413,7 +4413,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> extra = min_t(u16, alloc_size,
> DIV64_U64_ROUND_UP(alloc_size * rate,
> total_data_rate));
> - total[plane_id] = wm->wm[level].plane_res_b + 1 + extra;
> + total[plane_id] = wm->wm[level].min_ddb_alloc + extra;
> alloc_size -= extra;
> total_data_rate -= rate;
>
> @@ -4424,7 +4424,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> extra = min_t(u16, alloc_size,
> DIV64_U64_ROUND_UP(alloc_size * rate,
> total_data_rate));
> - uv_total[plane_id] = wm->uv_wm[level].plane_res_b + 1 + extra;
> + uv_total[plane_id] = wm->uv_wm[level].min_ddb_alloc + extra;
> alloc_size -= extra;
> total_data_rate -= rate;
> }
> @@ -4696,7 +4696,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *cstate,
> uint32_t latency = dev_priv->wm.skl_latency[level];
> uint_fixed_16_16_t method1, method2;
> uint_fixed_16_16_t selected_result;
> - uint32_t res_blocks, res_lines;
> + uint32_t res_blocks, res_lines, min_ddb_alloc = 0;
> struct intel_atomic_state *state =
> to_intel_atomic_state(cstate->base.state);
> bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state);
> @@ -4769,6 +4769,24 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *cstate,
> }
> }
>
> + if (INTEL_GEN(dev_priv) >= 11) {
> + if (wp->y_tiled) {
> + int extra_lines;
> +
> + if (res_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;
> +
> + min_ddb_alloc = mul_round_up_u32_fixed16(res_lines + extra_lines,
> + wp->plane_blocks_per_line);
> + } else {
> + min_ddb_alloc = res_blocks +
> + DIV_ROUND_UP(res_blocks, 10);
> + }
> + }
> +
> if (!skl_wm_has_lines(dev_priv, level))
> res_lines = 0;
>
> @@ -4783,6 +4801,8 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *cstate,
> */
> result->plane_res_b = res_blocks;
> result->plane_res_l = res_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;
> }
>
> @@ -5133,6 +5153,23 @@ static bool skl_plane_wm_equals(struct drm_i915_private *dev_priv,
> return skl_wm_level_equals(&wm1->trans_wm, &wm2->trans_wm);
> }
>
> +static bool skl_pipe_wm_equals(struct intel_crtc *crtc,
> + const struct skl_pipe_wm *wm1,
> + const struct skl_pipe_wm *wm2)
> +{
> + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> + enum plane_id plane_id;
> +
> + for_each_plane_id_on_crtc(crtc, plane_id) {
> + if (!skl_plane_wm_equals(dev_priv,
> + &wm1->planes[plane_id],
> + &wm2->planes[plane_id]))
> + return false;
> + }
> +
> + return wm1->linetime == wm2->linetime;
> +}
> +
> static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a,
> const struct skl_ddb_entry *b)
> {
> @@ -5159,16 +5196,14 @@ static int skl_update_pipe_wm(struct intel_crtc_state *cstate,
> struct skl_pipe_wm *pipe_wm, /* out */
> bool *changed /* out */)
> {
> + struct intel_crtc *crtc = to_intel_crtc(cstate->base.crtc);
> int ret;
>
> ret = skl_build_pipe_wm(cstate, pipe_wm);
> if (ret)
> return ret;
>
> - if (!memcmp(old_pipe_wm, pipe_wm, sizeof(*pipe_wm)))
> - *changed = false;
> - else
> - *changed = true;
> + *changed = !skl_pipe_wm_equals(crtc, old_pipe_wm, pipe_wm);
>
> return 0;
> }
> --
> 2.19.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
More information about the Intel-gfx
mailing list