[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