diff mbox series

[v2,18/20] drm/i915: Encapsulate dbuf state handling harder

Message ID 20200225171125.28885-19-ville.syrjala@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Proper dbuf global state | expand

Commit Message

Ville Syrjälä Feb. 25, 2020, 5:11 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

In order to make the dbuf state computation less fragile
let's make it stand on its own feet by now requiring someone
to peek into a crystall ball ahead of time to figure out
which pipes need to be added to the state under which potential
future conditions. Instead we compute each piece of the state
as we go along, and if any fallout occurs that affects more than
the current set of pipes we add the affected pipes to the state
naturally.

That requires that we track a few extra thigns in the global
dbuf state: dbuf slices for each pipe, and the weight each
pipe has when distributing the same set of slice(s) between
multiple pipes. Easy enough.

We do need to follow a somewhat careful sequence of computations
though as there are several steps involved in cooking up the dbuf
state. Thoguh we could avoid some of that by computing more things
on demand instead of relying on earlier step of the algorithm to
have filled it out. I think the end result is still reasonable
as the entire sequence is pretty much consolidated into a single
function instead of being spread around all over.

The rough sequence is this:
1. calculate active_pipes
2. calculate dbuf slices for every pipe
3. calculate total enabled slices
4. calculate new dbuf weights for any crtc in the state
5. calculate new ddb entry for every pipe based on the sets of
   slices and weights, and add any affected crtc to the state
6. calculate new plane ddb entries for all crtcs in the state,
   and add any affected plane to the state so that we'll perform
   the requisite hw reprogramming

And as a nice bonus we get to throw dev_priv->wm.distrust_bios_wm
out the window.

Cc: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c  |  15 -
 .../drm/i915/display/intel_display_debugfs.c  |   1 -
 drivers/gpu/drm/i915/i915_drv.h               |   9 -
 drivers/gpu/drm/i915/intel_pm.c               | 356 +++++++-----------
 drivers/gpu/drm/i915/intel_pm.h               |   2 +
 5 files changed, 138 insertions(+), 245 deletions(-)

Comments

Lisovskiy, Stanislav Jan. 21, 2021, 12:55 p.m. UTC | #1
On Tue, Feb 25, 2020 at 07:11:23PM +0200, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> In order to make the dbuf state computation less fragile
> let's make it stand on its own feet by now requiring someone
> to peek into a crystall ball ahead of time to figure out
> which pipes need to be added to the state under which potential
> future conditions. Instead we compute each piece of the state
> as we go along, and if any fallout occurs that affects more than
> the current set of pipes we add the affected pipes to the state
> naturally.
> 
> That requires that we track a few extra thigns in the global
> dbuf state: dbuf slices for each pipe, and the weight each
> pipe has when distributing the same set of slice(s) between
> multiple pipes. Easy enough.
> 
> We do need to follow a somewhat careful sequence of computations
> though as there are several steps involved in cooking up the dbuf
> state. Thoguh we could avoid some of that by computing more things
> on demand instead of relying on earlier step of the algorithm to
> have filled it out. I think the end result is still reasonable
> as the entire sequence is pretty much consolidated into a single
> function instead of being spread around all over.
> 
> The rough sequence is this:
> 1. calculate active_pipes
> 2. calculate dbuf slices for every pipe
> 3. calculate total enabled slices
> 4. calculate new dbuf weights for any crtc in the state
> 5. calculate new ddb entry for every pipe based on the sets of
>    slices and weights, and add any affected crtc to the state
> 6. calculate new plane ddb entries for all crtcs in the state,
>    and add any affected plane to the state so that we'll perform
>    the requisite hw reprogramming
> 
> And as a nice bonus we get to throw dev_priv->wm.distrust_bios_wm
> out the window.

So nice that we finally get those long awaited separate states for
dbuf, cdclk and etc.

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>

> 
> Cc: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  |  15 -
>  .../drm/i915/display/intel_display_debugfs.c  |   1 -
>  drivers/gpu/drm/i915/i915_drv.h               |   9 -
>  drivers/gpu/drm/i915/intel_pm.c               | 356 +++++++-----------
>  drivers/gpu/drm/i915/intel_pm.h               |   2 +
>  5 files changed, 138 insertions(+), 245 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 26e4462151a6..e3df43f3932d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -14856,20 +14856,6 @@ static int intel_atomic_check(struct drm_device *dev,
>  	if (new_cdclk_state && new_cdclk_state->force_min_cdclk_changed)
>  		any_ms = true;
>  
> -	/*
> -	 * distrust_bios_wm will force a full dbuf recomputation
> -	 * but the hardware state will only get updated accordingly
> -	 * if state->modeset==true. Hence distrust_bios_wm==true &&
> -	 * state->modeset==false is an invalid combination which
> -	 * would cause the hardware and software dbuf state to get
> -	 * out of sync. We must prevent that.
> -	 *
> -	 * FIXME clean up this mess and introduce better
> -	 * state tracking for dbuf.
> -	 */
> -	if (dev_priv->wm.distrust_bios_wm)
> -		any_ms = true;
> -
>  	if (any_ms) {
>  		ret = intel_modeset_checks(state);
>  		if (ret)
> @@ -15769,7 +15755,6 @@ static int intel_atomic_commit(struct drm_device *dev,
>  		intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);
>  		return ret;
>  	}
> -	dev_priv->wm.distrust_bios_wm = false;
>  	intel_shared_dpll_swap_state(state);
>  	intel_atomic_track_fbs(state);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> index 46954cc7b6c0..b505de6287e6 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> @@ -998,7 +998,6 @@ static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf,
>  		if (!dev_priv->ipc_enabled && enable)
>  			drm_info(&dev_priv->drm,
>  				 "Enabling IPC: WM will be proper only after next commit\n");
> -		dev_priv->wm.distrust_bios_wm = true;
>  		dev_priv->ipc_enabled = enable;
>  		intel_enable_ipc(dev_priv);
>  	}
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index d03c84f373e6..317e6a468e2e 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1183,15 +1183,6 @@ struct drm_i915_private {
>  		 * crtc_state->wm.need_postvbl_update.
>  		 */
>  		struct mutex wm_mutex;
> -
> -		/*
> -		 * Set during HW readout of watermarks/DDB.  Some platforms
> -		 * need to know when we're still using BIOS-provided values
> -		 * (which we don't fully trust).
> -		 *
> -		 * FIXME get rid of this.
> -		 */
> -		bool distrust_bios_wm;
>  	} wm;
>  
>  	struct dram_info {
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 085043528f80..c11508fb3fac 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3865,56 +3865,22 @@ static unsigned int intel_crtc_ddb_weight(const struct intel_crtc_state *crtc_st
>  	return hdisplay;
>  }
>  
> -static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc,
> -				  u8 active_pipes);
> -
> -static int intel_crtc_dbuf_weights(struct intel_atomic_state *state,
> -				   struct intel_crtc *for_crtc,
> -				   unsigned int *weight_start,
> -				   unsigned int *weight_end,
> -				   unsigned int *weight_total)
> +static void intel_crtc_dbuf_weights(const struct intel_dbuf_state *dbuf_state,
> +				    enum pipe for_pipe,
> +				    unsigned int *weight_start,
> +				    unsigned int *weight_end,
> +				    unsigned int *weight_total)
>  {
> -	const struct intel_dbuf_state *old_dbuf_state =
> -		intel_atomic_get_old_dbuf_state(state);
> -	struct intel_dbuf_state *new_dbuf_state =
> -		intel_atomic_get_new_dbuf_state(state);
> -	u8 active_pipes = new_dbuf_state->active_pipes;
> -	enum pipe for_pipe = for_crtc->pipe;
> -	const struct intel_crtc_state *crtc_state;
> -	struct intel_crtc *crtc;
> -	u8 dbuf_slice_mask;
> -	u8 total_slice_mask;
> -	int i, ret;
> -
> -	/*
> -	 * Get allowed DBuf slices for correspondent pipe and platform.
> -	 */
> -	dbuf_slice_mask = skl_compute_dbuf_slices(for_crtc, active_pipes);
> -	total_slice_mask = dbuf_slice_mask;
> +	struct drm_i915_private *dev_priv =
> +		to_i915(dbuf_state->base.state->base.dev);
> +	enum pipe pipe;
>  
>  	*weight_start = 0;
>  	*weight_end = 0;
>  	*weight_total = 0;
>  
> -	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
> -		enum pipe pipe = crtc->pipe;
> -		unsigned int weight;
> -		u8 pipe_dbuf_slice_mask;
> -
> -		if (!crtc_state->hw.active)
> -			continue;
> -
> -		pipe_dbuf_slice_mask =
> -			skl_compute_dbuf_slices(crtc, active_pipes);
> -
> -		/*
> -		 * According to BSpec pipe can share one dbuf slice with another
> -		 * pipes or pipe can use multiple dbufs, in both cases we
> -		 * account for other pipes only if they have exactly same mask.
> -		 * However we need to account how many slices we should enable
> -		 * in total.
> -		 */
> -		total_slice_mask |= pipe_dbuf_slice_mask;
> +	for_each_pipe(dev_priv, pipe) {
> +		int weight = dbuf_state->weight[pipe];
>  
>  		/*
>  		 * Do not account pipes using other slice sets
> @@ -3923,12 +3889,10 @@ static int intel_crtc_dbuf_weights(struct intel_atomic_state *state,
>  		 * i.e no partial intersection), so it is enough to check for
>  		 * equality for now.
>  		 */
> -		if (dbuf_slice_mask != pipe_dbuf_slice_mask)
> +		if (dbuf_state->slices[pipe] != dbuf_state->slices[for_pipe])
>  			continue;
>  
> -		weight = intel_crtc_ddb_weight(crtc_state);
>  		*weight_total += weight;
> -
>  		if (pipe < for_pipe) {
>  			*weight_start += weight;
>  			*weight_end += weight;
> @@ -3936,87 +3900,65 @@ static int intel_crtc_dbuf_weights(struct intel_atomic_state *state,
>  			*weight_end += weight;
>  		}
>  	}
> -
> -	/*
> -	 * FIXME: For now we always enable slice S1 as per
> -	 * the Bspec display initialization sequence.
> -	 */
> -	new_dbuf_state->enabled_slices = total_slice_mask | BIT(DBUF_S1);
> -
> -	if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices) {
> -		ret = intel_atomic_serialize_global_state(&new_dbuf_state->base);
> -		if (ret)
> -			return ret;
> -	}
> -
> -	return 0;
>  }
>  
>  static int
> -skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
> -				   const struct intel_crtc_state *crtc_state,
> -				   const u64 total_data_rate,
> -				   struct skl_ddb_entry *alloc, /* out */
> -				   int *num_active /* out */)
> +skl_crtc_allocate_ddb(struct intel_atomic_state *state, struct intel_crtc *crtc)
>  {
> -	struct intel_atomic_state *state =
> -		to_intel_atomic_state(crtc_state->uapi.state);
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -	unsigned int weight_start, weight_end, weight_total;
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +	unsigned int weight_total, weight_start, weight_end;
>  	const struct intel_dbuf_state *old_dbuf_state =
>  		intel_atomic_get_old_dbuf_state(state);
>  	struct intel_dbuf_state *new_dbuf_state =
>  		intel_atomic_get_new_dbuf_state(state);
> -	u8 active_pipes = new_dbuf_state->active_pipes;
> +	struct intel_crtc_state *crtc_state;
>  	struct skl_ddb_entry ddb_slices;
> +	enum pipe pipe = crtc->pipe;
>  	u32 ddb_range_size;
>  	u32 dbuf_slice_mask;
>  	u32 start, end;
>  	int ret;
>  
> -	*num_active = hweight8(active_pipes);
> -
> -	if (!crtc_state->hw.active) {
> -		alloc->start = 0;
> -		alloc->end = 0;
> -		return 0;
> +	if (new_dbuf_state->weight[pipe] == 0) {
> +		new_dbuf_state->ddb[pipe].start = 0;
> +		new_dbuf_state->ddb[pipe].end = 0;
> +		goto out;
>  	}
>  
> -	/*
> -	 * If the state doesn't change the active CRTC's or there is no
> -	 * modeset request, then there's no need to recalculate;
> -	 * the existing pipe allocation limits should remain unchanged.
> -	 * Note that we're safe from racing commits since any racing commit
> -	 * that changes the active CRTC list or do modeset would need to
> -	 * grab _all_ crtc locks, including the one we currently hold.
> -	 */
> -	if (old_dbuf_state->active_pipes == new_dbuf_state->active_pipes &&
> -	    !dev_priv->wm.distrust_bios_wm)
> -		return 0;
> -
> -	/*
> -	 * Get allowed DBuf slices for correspondent pipe and platform.
> -	 */
> -	dbuf_slice_mask = skl_compute_dbuf_slices(crtc, active_pipes);
> +	dbuf_slice_mask = new_dbuf_state->slices[pipe];
>  
>  	skl_ddb_entry_for_slices(dev_priv, dbuf_slice_mask, &ddb_slices);
>  	ddb_range_size = skl_ddb_entry_size(&ddb_slices);
>  
> -	ret = intel_crtc_dbuf_weights(state, crtc,
> -				      &weight_start, &weight_end, &weight_total);
> -	if (ret)
> -		return ret;
> +	intel_crtc_dbuf_weights(new_dbuf_state, pipe,
> +				&weight_start, &weight_end, &weight_total);
>  
>  	start = ddb_range_size * weight_start / weight_total;
>  	end = ddb_range_size * weight_end / weight_total;
>  
> -	alloc->start = ddb_slices.start + start;
> -	alloc->end = ddb_slices.start + end;
> +	new_dbuf_state->ddb[pipe].start = ddb_slices.start + start;
> +	new_dbuf_state->ddb[pipe].end = ddb_slices.start + end;
> +
> +out:
> +	if (skl_ddb_entry_equal(&old_dbuf_state->ddb[pipe],
> +				&new_dbuf_state->ddb[pipe]))
> +		return 0;
> +
> +	ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
> +	if (ret)
> +		return ret;
> +
> +	crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
> +	if (IS_ERR(crtc_state))
> +		return PTR_ERR(crtc_state);
>  
>  	drm_dbg_kms(&dev_priv->drm,
> -		    "[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x\n",
> +		    "[CRTC:%d:%s] dbuf slices 0x%x -> 0x%x, ddb (%d - %d) -> (%d - %d), active pipes 0x%x -> 0x%x\n",
>  		    crtc->base.base.id, crtc->base.name,
> -		    dbuf_slice_mask, alloc->start, alloc->end, active_pipes);
> +		    old_dbuf_state->slices[pipe], new_dbuf_state->slices[pipe],
> +		    old_dbuf_state->ddb[pipe].start, old_dbuf_state->ddb[pipe].end,
> +		    new_dbuf_state->ddb[pipe].start, new_dbuf_state->ddb[pipe].end,
> +		    old_dbuf_state->active_pipes, new_dbuf_state->active_pipes);
>  
>  	return 0;
>  }
> @@ -4549,35 +4491,32 @@ icl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state,
>  }
>  
>  static int
> -skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state)
> +skl_allocate_plane_ddb(struct intel_atomic_state *state,
> +		       struct intel_crtc *crtc)
>  {
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
>  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -	struct intel_atomic_state *state =
> -		to_intel_atomic_state(crtc_state->uapi.state);
> -	struct intel_dbuf_state *dbuf_state =
> +	struct intel_crtc_state *crtc_state =
> +		intel_atomic_get_new_crtc_state(state, crtc);
> +	const struct intel_dbuf_state *dbuf_state =
>  		intel_atomic_get_new_dbuf_state(state);
> -	struct skl_ddb_entry *alloc = &dbuf_state->ddb[crtc->pipe];
> +	const struct skl_ddb_entry *alloc = &dbuf_state->ddb[crtc->pipe];
> +	int num_active = hweight8(dbuf_state->active_pipes);
>  	u16 alloc_size, start = 0;
>  	u16 total[I915_MAX_PLANES] = {};
>  	u16 uv_total[I915_MAX_PLANES] = {};
>  	u64 total_data_rate;
>  	enum plane_id plane_id;
> -	int num_active;
>  	u64 plane_data_rate[I915_MAX_PLANES] = {};
>  	u64 uv_plane_data_rate[I915_MAX_PLANES] = {};
>  	u32 blocks;
>  	int level;
> -	int ret;
>  
>  	/* Clear the partitioning for disabled planes. */
>  	memset(crtc_state->wm.skl.plane_ddb_y, 0, sizeof(crtc_state->wm.skl.plane_ddb_y));
>  	memset(crtc_state->wm.skl.plane_ddb_uv, 0, sizeof(crtc_state->wm.skl.plane_ddb_uv));
>  
> -	if (!crtc_state->hw.active) {
> -		alloc->start = alloc->end = 0;
> +	if (!crtc_state->hw.active)
>  		return 0;
> -	}
>  
>  	if (INTEL_GEN(dev_priv) >= 11)
>  		total_data_rate =
> @@ -4589,13 +4528,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state)
>  							 plane_data_rate,
>  							 uv_plane_data_rate);
>  
> -
> -	ret = skl_ddb_get_pipe_allocation_limits(dev_priv, crtc_state,
> -						 total_data_rate,
> -						 alloc, &num_active);
> -	if (ret)
> -		return ret;
> -
>  	alloc_size = skl_ddb_entry_size(alloc);
>  	if (alloc_size == 0)
>  		return 0;
> @@ -5475,39 +5407,114 @@ skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state,
>  	return 0;
>  }
>  
> +static u8 intel_dbuf_enabled_slices(const struct intel_dbuf_state *dbuf_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dbuf_state->base.state->base.dev);
> +	u8 enabled_slices;
> +	enum pipe pipe;
> +
> +	/*
> +	 * FIXME: For now we always enable slice S1 as per
> +	 * the Bspec display initialization sequence.
> +	 */
> +	enabled_slices = BIT(DBUF_S1);
> +
> +	for_each_pipe(dev_priv, pipe)
> +		enabled_slices |= dbuf_state->slices[pipe];
> +
> +	return enabled_slices;
> +}
> +
>  static int
>  skl_compute_ddb(struct intel_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	const struct intel_dbuf_state *old_dbuf_state;
> -	const struct intel_dbuf_state *new_dbuf_state;
> +	struct intel_dbuf_state *new_dbuf_state = NULL;
>  	const struct intel_crtc_state *old_crtc_state;
>  	struct intel_crtc_state *new_crtc_state;
>  	struct intel_crtc *crtc;
>  	int ret, i;
>  
> -	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
> -					    new_crtc_state, i) {
> -		ret = skl_allocate_pipe_ddb(new_crtc_state);
> +	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
> +		new_dbuf_state = intel_atomic_get_dbuf_state(state);
> +		if (IS_ERR(new_dbuf_state))
> +			return PTR_ERR(new_dbuf_state);
> +
> +		old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
> +		break;
> +	}
> +
> +	if (!new_dbuf_state)
> +		return 0;
> +
> +	new_dbuf_state->active_pipes =
> +		intel_calc_active_pipes(state, old_dbuf_state->active_pipes);
> +
> +	if (old_dbuf_state->active_pipes != new_dbuf_state->active_pipes) {
> +		ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
>  		if (ret)
>  			return ret;
> +	}
>  
> -		ret = skl_ddb_add_affected_planes(old_crtc_state,
> -						  new_crtc_state);
> +	for_each_intel_crtc(&dev_priv->drm, crtc) {
> +		enum pipe pipe = crtc->pipe;
> +
> +		new_dbuf_state->slices[pipe] =
> +			skl_compute_dbuf_slices(crtc, new_dbuf_state->active_pipes);
> +
> +		if (old_dbuf_state->slices[pipe] == new_dbuf_state->slices[pipe])
> +			continue;
> +
> +		ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
>  		if (ret)
>  			return ret;
>  	}
>  
> -	old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
> -	new_dbuf_state = intel_atomic_get_new_dbuf_state(state);
> +	new_dbuf_state->enabled_slices = intel_dbuf_enabled_slices(new_dbuf_state);
> +
> +	if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices) {
> +		ret = intel_atomic_serialize_global_state(&new_dbuf_state->base);
> +		if (ret)
> +			return ret;
>  
> -	if (new_dbuf_state &&
> -	    new_dbuf_state->enabled_slices != old_dbuf_state->enabled_slices)
>  		drm_dbg_kms(&dev_priv->drm,
>  			    "Enabled dbuf slices 0x%x -> 0x%x (out of %d dbuf slices)\n",
>  			    old_dbuf_state->enabled_slices,
>  			    new_dbuf_state->enabled_slices,
>  			    INTEL_INFO(dev_priv)->num_supported_dbuf_slices);
> +	}
> +
> +	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
> +		enum pipe pipe = crtc->pipe;
> +
> +		new_dbuf_state->weight[crtc->pipe] = intel_crtc_ddb_weight(new_crtc_state);
> +
> +		if (old_dbuf_state->weight[pipe] == new_dbuf_state->weight[pipe])
> +			continue;
> +
> +		ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	for_each_intel_crtc(&dev_priv->drm, crtc) {
> +		ret = skl_crtc_allocate_ddb(state, crtc);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
> +					    new_crtc_state, i) {
> +		ret = skl_allocate_plane_ddb(state, crtc);
> +		if (ret)
> +			return ret;
> +
> +		ret = skl_ddb_add_affected_planes(old_crtc_state,
> +						  new_crtc_state);
> +		if (ret)
> +			return ret;
> +	}
>  
>  	return 0;
>  }
> @@ -5636,83 +5643,6 @@ skl_print_wm_changes(struct intel_atomic_state *state)
>  	}
>  }
>  
> -static int intel_add_affected_pipes(struct intel_atomic_state *state,
> -				    u8 pipe_mask)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> -	struct intel_crtc *crtc;
> -
> -	for_each_intel_crtc(&dev_priv->drm, crtc) {
> -		struct intel_crtc_state *crtc_state;
> -
> -		if ((pipe_mask & BIT(crtc->pipe)) == 0)
> -			continue;
> -
> -		crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
> -		if (IS_ERR(crtc_state))
> -			return PTR_ERR(crtc_state);
> -	}
> -
> -	return 0;
> -}
> -
> -static int
> -skl_ddb_add_affected_pipes(struct intel_atomic_state *state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> -	struct intel_crtc_state *crtc_state;
> -	struct intel_crtc *crtc;
> -	int i, ret;
> -
> -	if (dev_priv->wm.distrust_bios_wm) {
> -		/*
> -		 * skl_ddb_get_pipe_allocation_limits() currently requires
> -		 * all active pipes to be included in the state so that
> -		 * it can redistribute the dbuf among them, and it really
> -		 * wants to recompute things when distrust_bios_wm is set
> -		 * so we add all the pipes to the state.
> -		 */
> -		ret = intel_add_affected_pipes(state, ~0);
> -		if (ret)
> -			return ret;
> -	}
> -
> -	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
> -		struct intel_dbuf_state *new_dbuf_state;
> -		const struct intel_dbuf_state *old_dbuf_state;
> -
> -		new_dbuf_state = intel_atomic_get_dbuf_state(state);
> -		if (IS_ERR(new_dbuf_state))
> -			return ret;
> -
> -		old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
> -
> -		new_dbuf_state->active_pipes =
> -			intel_calc_active_pipes(state, old_dbuf_state->active_pipes);
> -
> -		if (old_dbuf_state->active_pipes == new_dbuf_state->active_pipes)
> -			break;
> -
> -		ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
> -		if (ret)
> -			return ret;
> -
> -		/*
> -		 * skl_ddb_get_pipe_allocation_limits() currently requires
> -		 * all active pipes to be included in the state so that
> -		 * it can redistribute the dbuf among them.
> -		 */
> -		ret = intel_add_affected_pipes(state,
> -					       new_dbuf_state->active_pipes);
> -		if (ret)
> -			return ret;
> -
> -		break;
> -	}
> -
> -	return 0;
> -}
> -
>  /*
>   * To make sure the cursor watermark registers are always consistent
>   * with our computed state the following scenario needs special
> @@ -5781,15 +5711,6 @@ skl_compute_wm(struct intel_atomic_state *state)
>  	struct intel_crtc_state *old_crtc_state;
>  	int ret, i;
>  
> -	ret = skl_ddb_add_affected_pipes(state);
> -	if (ret)
> -		return ret;
> -
> -	/*
> -	 * Calculate WM's for all pipes that are part of this transaction.
> -	 * Note that skl_ddb_add_affected_pipes may have added more CRTC's that
> -	 * weren't otherwise being modified if pipe allocations had to change.
> -	 */
>  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>  					    new_crtc_state, i) {
>  		ret = skl_build_pipe_wm(new_crtc_state);
> @@ -5944,11 +5865,6 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
>  
>  		skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal);
>  	}
> -
> -	if (dev_priv->active_pipes) {
> -		/* Fully recompute DDB on first atomic commit */
> -		dev_priv->wm.distrust_bios_wm = true;
> -	}
>  }
>  
>  static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc)
> diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
> index d9f84d93280d..3a82b8046f10 100644
> --- a/drivers/gpu/drm/i915/intel_pm.h
> +++ b/drivers/gpu/drm/i915/intel_pm.h
> @@ -66,6 +66,8 @@ struct intel_dbuf_state {
>  	struct intel_global_state base;
>  
>  	struct skl_ddb_entry ddb[I915_MAX_PIPES];
> +	unsigned int weight[I915_MAX_PIPES];
> +	u8 slices[I915_MAX_PIPES];
>  
>  	u8 enabled_slices;
>  	u8 active_pipes;
> -- 
> 2.24.1
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 26e4462151a6..e3df43f3932d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -14856,20 +14856,6 @@  static int intel_atomic_check(struct drm_device *dev,
 	if (new_cdclk_state && new_cdclk_state->force_min_cdclk_changed)
 		any_ms = true;
 
-	/*
-	 * distrust_bios_wm will force a full dbuf recomputation
-	 * but the hardware state will only get updated accordingly
-	 * if state->modeset==true. Hence distrust_bios_wm==true &&
-	 * state->modeset==false is an invalid combination which
-	 * would cause the hardware and software dbuf state to get
-	 * out of sync. We must prevent that.
-	 *
-	 * FIXME clean up this mess and introduce better
-	 * state tracking for dbuf.
-	 */
-	if (dev_priv->wm.distrust_bios_wm)
-		any_ms = true;
-
 	if (any_ms) {
 		ret = intel_modeset_checks(state);
 		if (ret)
@@ -15769,7 +15755,6 @@  static int intel_atomic_commit(struct drm_device *dev,
 		intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);
 		return ret;
 	}
-	dev_priv->wm.distrust_bios_wm = false;
 	intel_shared_dpll_swap_state(state);
 	intel_atomic_track_fbs(state);
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 46954cc7b6c0..b505de6287e6 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -998,7 +998,6 @@  static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf,
 		if (!dev_priv->ipc_enabled && enable)
 			drm_info(&dev_priv->drm,
 				 "Enabling IPC: WM will be proper only after next commit\n");
-		dev_priv->wm.distrust_bios_wm = true;
 		dev_priv->ipc_enabled = enable;
 		intel_enable_ipc(dev_priv);
 	}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d03c84f373e6..317e6a468e2e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1183,15 +1183,6 @@  struct drm_i915_private {
 		 * crtc_state->wm.need_postvbl_update.
 		 */
 		struct mutex wm_mutex;
-
-		/*
-		 * Set during HW readout of watermarks/DDB.  Some platforms
-		 * need to know when we're still using BIOS-provided values
-		 * (which we don't fully trust).
-		 *
-		 * FIXME get rid of this.
-		 */
-		bool distrust_bios_wm;
 	} wm;
 
 	struct dram_info {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 085043528f80..c11508fb3fac 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3865,56 +3865,22 @@  static unsigned int intel_crtc_ddb_weight(const struct intel_crtc_state *crtc_st
 	return hdisplay;
 }
 
-static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc,
-				  u8 active_pipes);
-
-static int intel_crtc_dbuf_weights(struct intel_atomic_state *state,
-				   struct intel_crtc *for_crtc,
-				   unsigned int *weight_start,
-				   unsigned int *weight_end,
-				   unsigned int *weight_total)
+static void intel_crtc_dbuf_weights(const struct intel_dbuf_state *dbuf_state,
+				    enum pipe for_pipe,
+				    unsigned int *weight_start,
+				    unsigned int *weight_end,
+				    unsigned int *weight_total)
 {
-	const struct intel_dbuf_state *old_dbuf_state =
-		intel_atomic_get_old_dbuf_state(state);
-	struct intel_dbuf_state *new_dbuf_state =
-		intel_atomic_get_new_dbuf_state(state);
-	u8 active_pipes = new_dbuf_state->active_pipes;
-	enum pipe for_pipe = for_crtc->pipe;
-	const struct intel_crtc_state *crtc_state;
-	struct intel_crtc *crtc;
-	u8 dbuf_slice_mask;
-	u8 total_slice_mask;
-	int i, ret;
-
-	/*
-	 * Get allowed DBuf slices for correspondent pipe and platform.
-	 */
-	dbuf_slice_mask = skl_compute_dbuf_slices(for_crtc, active_pipes);
-	total_slice_mask = dbuf_slice_mask;
+	struct drm_i915_private *dev_priv =
+		to_i915(dbuf_state->base.state->base.dev);
+	enum pipe pipe;
 
 	*weight_start = 0;
 	*weight_end = 0;
 	*weight_total = 0;
 
-	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
-		enum pipe pipe = crtc->pipe;
-		unsigned int weight;
-		u8 pipe_dbuf_slice_mask;
-
-		if (!crtc_state->hw.active)
-			continue;
-
-		pipe_dbuf_slice_mask =
-			skl_compute_dbuf_slices(crtc, active_pipes);
-
-		/*
-		 * According to BSpec pipe can share one dbuf slice with another
-		 * pipes or pipe can use multiple dbufs, in both cases we
-		 * account for other pipes only if they have exactly same mask.
-		 * However we need to account how many slices we should enable
-		 * in total.
-		 */
-		total_slice_mask |= pipe_dbuf_slice_mask;
+	for_each_pipe(dev_priv, pipe) {
+		int weight = dbuf_state->weight[pipe];
 
 		/*
 		 * Do not account pipes using other slice sets
@@ -3923,12 +3889,10 @@  static int intel_crtc_dbuf_weights(struct intel_atomic_state *state,
 		 * i.e no partial intersection), so it is enough to check for
 		 * equality for now.
 		 */
-		if (dbuf_slice_mask != pipe_dbuf_slice_mask)
+		if (dbuf_state->slices[pipe] != dbuf_state->slices[for_pipe])
 			continue;
 
-		weight = intel_crtc_ddb_weight(crtc_state);
 		*weight_total += weight;
-
 		if (pipe < for_pipe) {
 			*weight_start += weight;
 			*weight_end += weight;
@@ -3936,87 +3900,65 @@  static int intel_crtc_dbuf_weights(struct intel_atomic_state *state,
 			*weight_end += weight;
 		}
 	}
-
-	/*
-	 * FIXME: For now we always enable slice S1 as per
-	 * the Bspec display initialization sequence.
-	 */
-	new_dbuf_state->enabled_slices = total_slice_mask | BIT(DBUF_S1);
-
-	if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices) {
-		ret = intel_atomic_serialize_global_state(&new_dbuf_state->base);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
 }
 
 static int
-skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
-				   const struct intel_crtc_state *crtc_state,
-				   const u64 total_data_rate,
-				   struct skl_ddb_entry *alloc, /* out */
-				   int *num_active /* out */)
+skl_crtc_allocate_ddb(struct intel_atomic_state *state, struct intel_crtc *crtc)
 {
-	struct intel_atomic_state *state =
-		to_intel_atomic_state(crtc_state->uapi.state);
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	unsigned int weight_start, weight_end, weight_total;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	unsigned int weight_total, weight_start, weight_end;
 	const struct intel_dbuf_state *old_dbuf_state =
 		intel_atomic_get_old_dbuf_state(state);
 	struct intel_dbuf_state *new_dbuf_state =
 		intel_atomic_get_new_dbuf_state(state);
-	u8 active_pipes = new_dbuf_state->active_pipes;
+	struct intel_crtc_state *crtc_state;
 	struct skl_ddb_entry ddb_slices;
+	enum pipe pipe = crtc->pipe;
 	u32 ddb_range_size;
 	u32 dbuf_slice_mask;
 	u32 start, end;
 	int ret;
 
-	*num_active = hweight8(active_pipes);
-
-	if (!crtc_state->hw.active) {
-		alloc->start = 0;
-		alloc->end = 0;
-		return 0;
+	if (new_dbuf_state->weight[pipe] == 0) {
+		new_dbuf_state->ddb[pipe].start = 0;
+		new_dbuf_state->ddb[pipe].end = 0;
+		goto out;
 	}
 
-	/*
-	 * If the state doesn't change the active CRTC's or there is no
-	 * modeset request, then there's no need to recalculate;
-	 * the existing pipe allocation limits should remain unchanged.
-	 * Note that we're safe from racing commits since any racing commit
-	 * that changes the active CRTC list or do modeset would need to
-	 * grab _all_ crtc locks, including the one we currently hold.
-	 */
-	if (old_dbuf_state->active_pipes == new_dbuf_state->active_pipes &&
-	    !dev_priv->wm.distrust_bios_wm)
-		return 0;
-
-	/*
-	 * Get allowed DBuf slices for correspondent pipe and platform.
-	 */
-	dbuf_slice_mask = skl_compute_dbuf_slices(crtc, active_pipes);
+	dbuf_slice_mask = new_dbuf_state->slices[pipe];
 
 	skl_ddb_entry_for_slices(dev_priv, dbuf_slice_mask, &ddb_slices);
 	ddb_range_size = skl_ddb_entry_size(&ddb_slices);
 
-	ret = intel_crtc_dbuf_weights(state, crtc,
-				      &weight_start, &weight_end, &weight_total);
-	if (ret)
-		return ret;
+	intel_crtc_dbuf_weights(new_dbuf_state, pipe,
+				&weight_start, &weight_end, &weight_total);
 
 	start = ddb_range_size * weight_start / weight_total;
 	end = ddb_range_size * weight_end / weight_total;
 
-	alloc->start = ddb_slices.start + start;
-	alloc->end = ddb_slices.start + end;
+	new_dbuf_state->ddb[pipe].start = ddb_slices.start + start;
+	new_dbuf_state->ddb[pipe].end = ddb_slices.start + end;
+
+out:
+	if (skl_ddb_entry_equal(&old_dbuf_state->ddb[pipe],
+				&new_dbuf_state->ddb[pipe]))
+		return 0;
+
+	ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
+	if (ret)
+		return ret;
+
+	crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
 
 	drm_dbg_kms(&dev_priv->drm,
-		    "[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x\n",
+		    "[CRTC:%d:%s] dbuf slices 0x%x -> 0x%x, ddb (%d - %d) -> (%d - %d), active pipes 0x%x -> 0x%x\n",
 		    crtc->base.base.id, crtc->base.name,
-		    dbuf_slice_mask, alloc->start, alloc->end, active_pipes);
+		    old_dbuf_state->slices[pipe], new_dbuf_state->slices[pipe],
+		    old_dbuf_state->ddb[pipe].start, old_dbuf_state->ddb[pipe].end,
+		    new_dbuf_state->ddb[pipe].start, new_dbuf_state->ddb[pipe].end,
+		    old_dbuf_state->active_pipes, new_dbuf_state->active_pipes);
 
 	return 0;
 }
@@ -4549,35 +4491,32 @@  icl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state,
 }
 
 static int
-skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state)
+skl_allocate_plane_ddb(struct intel_atomic_state *state,
+		       struct intel_crtc *crtc)
 {
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	struct intel_atomic_state *state =
-		to_intel_atomic_state(crtc_state->uapi.state);
-	struct intel_dbuf_state *dbuf_state =
+	struct intel_crtc_state *crtc_state =
+		intel_atomic_get_new_crtc_state(state, crtc);
+	const struct intel_dbuf_state *dbuf_state =
 		intel_atomic_get_new_dbuf_state(state);
-	struct skl_ddb_entry *alloc = &dbuf_state->ddb[crtc->pipe];
+	const struct skl_ddb_entry *alloc = &dbuf_state->ddb[crtc->pipe];
+	int num_active = hweight8(dbuf_state->active_pipes);
 	u16 alloc_size, start = 0;
 	u16 total[I915_MAX_PLANES] = {};
 	u16 uv_total[I915_MAX_PLANES] = {};
 	u64 total_data_rate;
 	enum plane_id plane_id;
-	int num_active;
 	u64 plane_data_rate[I915_MAX_PLANES] = {};
 	u64 uv_plane_data_rate[I915_MAX_PLANES] = {};
 	u32 blocks;
 	int level;
-	int ret;
 
 	/* Clear the partitioning for disabled planes. */
 	memset(crtc_state->wm.skl.plane_ddb_y, 0, sizeof(crtc_state->wm.skl.plane_ddb_y));
 	memset(crtc_state->wm.skl.plane_ddb_uv, 0, sizeof(crtc_state->wm.skl.plane_ddb_uv));
 
-	if (!crtc_state->hw.active) {
-		alloc->start = alloc->end = 0;
+	if (!crtc_state->hw.active)
 		return 0;
-	}
 
 	if (INTEL_GEN(dev_priv) >= 11)
 		total_data_rate =
@@ -4589,13 +4528,6 @@  skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state)
 							 plane_data_rate,
 							 uv_plane_data_rate);
 
-
-	ret = skl_ddb_get_pipe_allocation_limits(dev_priv, crtc_state,
-						 total_data_rate,
-						 alloc, &num_active);
-	if (ret)
-		return ret;
-
 	alloc_size = skl_ddb_entry_size(alloc);
 	if (alloc_size == 0)
 		return 0;
@@ -5475,39 +5407,114 @@  skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state,
 	return 0;
 }
 
+static u8 intel_dbuf_enabled_slices(const struct intel_dbuf_state *dbuf_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(dbuf_state->base.state->base.dev);
+	u8 enabled_slices;
+	enum pipe pipe;
+
+	/*
+	 * FIXME: For now we always enable slice S1 as per
+	 * the Bspec display initialization sequence.
+	 */
+	enabled_slices = BIT(DBUF_S1);
+
+	for_each_pipe(dev_priv, pipe)
+		enabled_slices |= dbuf_state->slices[pipe];
+
+	return enabled_slices;
+}
+
 static int
 skl_compute_ddb(struct intel_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	const struct intel_dbuf_state *old_dbuf_state;
-	const struct intel_dbuf_state *new_dbuf_state;
+	struct intel_dbuf_state *new_dbuf_state = NULL;
 	const struct intel_crtc_state *old_crtc_state;
 	struct intel_crtc_state *new_crtc_state;
 	struct intel_crtc *crtc;
 	int ret, i;
 
-	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
-					    new_crtc_state, i) {
-		ret = skl_allocate_pipe_ddb(new_crtc_state);
+	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+		new_dbuf_state = intel_atomic_get_dbuf_state(state);
+		if (IS_ERR(new_dbuf_state))
+			return PTR_ERR(new_dbuf_state);
+
+		old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
+		break;
+	}
+
+	if (!new_dbuf_state)
+		return 0;
+
+	new_dbuf_state->active_pipes =
+		intel_calc_active_pipes(state, old_dbuf_state->active_pipes);
+
+	if (old_dbuf_state->active_pipes != new_dbuf_state->active_pipes) {
+		ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
 		if (ret)
 			return ret;
+	}
 
-		ret = skl_ddb_add_affected_planes(old_crtc_state,
-						  new_crtc_state);
+	for_each_intel_crtc(&dev_priv->drm, crtc) {
+		enum pipe pipe = crtc->pipe;
+
+		new_dbuf_state->slices[pipe] =
+			skl_compute_dbuf_slices(crtc, new_dbuf_state->active_pipes);
+
+		if (old_dbuf_state->slices[pipe] == new_dbuf_state->slices[pipe])
+			continue;
+
+		ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
 		if (ret)
 			return ret;
 	}
 
-	old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
-	new_dbuf_state = intel_atomic_get_new_dbuf_state(state);
+	new_dbuf_state->enabled_slices = intel_dbuf_enabled_slices(new_dbuf_state);
+
+	if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices) {
+		ret = intel_atomic_serialize_global_state(&new_dbuf_state->base);
+		if (ret)
+			return ret;
 
-	if (new_dbuf_state &&
-	    new_dbuf_state->enabled_slices != old_dbuf_state->enabled_slices)
 		drm_dbg_kms(&dev_priv->drm,
 			    "Enabled dbuf slices 0x%x -> 0x%x (out of %d dbuf slices)\n",
 			    old_dbuf_state->enabled_slices,
 			    new_dbuf_state->enabled_slices,
 			    INTEL_INFO(dev_priv)->num_supported_dbuf_slices);
+	}
+
+	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+		enum pipe pipe = crtc->pipe;
+
+		new_dbuf_state->weight[crtc->pipe] = intel_crtc_ddb_weight(new_crtc_state);
+
+		if (old_dbuf_state->weight[pipe] == new_dbuf_state->weight[pipe])
+			continue;
+
+		ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
+		if (ret)
+			return ret;
+	}
+
+	for_each_intel_crtc(&dev_priv->drm, crtc) {
+		ret = skl_crtc_allocate_ddb(state, crtc);
+		if (ret)
+			return ret;
+	}
+
+	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
+					    new_crtc_state, i) {
+		ret = skl_allocate_plane_ddb(state, crtc);
+		if (ret)
+			return ret;
+
+		ret = skl_ddb_add_affected_planes(old_crtc_state,
+						  new_crtc_state);
+		if (ret)
+			return ret;
+	}
 
 	return 0;
 }
@@ -5636,83 +5643,6 @@  skl_print_wm_changes(struct intel_atomic_state *state)
 	}
 }
 
-static int intel_add_affected_pipes(struct intel_atomic_state *state,
-				    u8 pipe_mask)
-{
-	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-	struct intel_crtc *crtc;
-
-	for_each_intel_crtc(&dev_priv->drm, crtc) {
-		struct intel_crtc_state *crtc_state;
-
-		if ((pipe_mask & BIT(crtc->pipe)) == 0)
-			continue;
-
-		crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
-		if (IS_ERR(crtc_state))
-			return PTR_ERR(crtc_state);
-	}
-
-	return 0;
-}
-
-static int
-skl_ddb_add_affected_pipes(struct intel_atomic_state *state)
-{
-	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-	struct intel_crtc_state *crtc_state;
-	struct intel_crtc *crtc;
-	int i, ret;
-
-	if (dev_priv->wm.distrust_bios_wm) {
-		/*
-		 * skl_ddb_get_pipe_allocation_limits() currently requires
-		 * all active pipes to be included in the state so that
-		 * it can redistribute the dbuf among them, and it really
-		 * wants to recompute things when distrust_bios_wm is set
-		 * so we add all the pipes to the state.
-		 */
-		ret = intel_add_affected_pipes(state, ~0);
-		if (ret)
-			return ret;
-	}
-
-	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
-		struct intel_dbuf_state *new_dbuf_state;
-		const struct intel_dbuf_state *old_dbuf_state;
-
-		new_dbuf_state = intel_atomic_get_dbuf_state(state);
-		if (IS_ERR(new_dbuf_state))
-			return ret;
-
-		old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
-
-		new_dbuf_state->active_pipes =
-			intel_calc_active_pipes(state, old_dbuf_state->active_pipes);
-
-		if (old_dbuf_state->active_pipes == new_dbuf_state->active_pipes)
-			break;
-
-		ret = intel_atomic_lock_global_state(&new_dbuf_state->base);
-		if (ret)
-			return ret;
-
-		/*
-		 * skl_ddb_get_pipe_allocation_limits() currently requires
-		 * all active pipes to be included in the state so that
-		 * it can redistribute the dbuf among them.
-		 */
-		ret = intel_add_affected_pipes(state,
-					       new_dbuf_state->active_pipes);
-		if (ret)
-			return ret;
-
-		break;
-	}
-
-	return 0;
-}
-
 /*
  * To make sure the cursor watermark registers are always consistent
  * with our computed state the following scenario needs special
@@ -5781,15 +5711,6 @@  skl_compute_wm(struct intel_atomic_state *state)
 	struct intel_crtc_state *old_crtc_state;
 	int ret, i;
 
-	ret = skl_ddb_add_affected_pipes(state);
-	if (ret)
-		return ret;
-
-	/*
-	 * Calculate WM's for all pipes that are part of this transaction.
-	 * Note that skl_ddb_add_affected_pipes may have added more CRTC's that
-	 * weren't otherwise being modified if pipe allocations had to change.
-	 */
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
 		ret = skl_build_pipe_wm(new_crtc_state);
@@ -5944,11 +5865,6 @@  void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
 
 		skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal);
 	}
-
-	if (dev_priv->active_pipes) {
-		/* Fully recompute DDB on first atomic commit */
-		dev_priv->wm.distrust_bios_wm = true;
-	}
 }
 
 static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc)
diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
index d9f84d93280d..3a82b8046f10 100644
--- a/drivers/gpu/drm/i915/intel_pm.h
+++ b/drivers/gpu/drm/i915/intel_pm.h
@@ -66,6 +66,8 @@  struct intel_dbuf_state {
 	struct intel_global_state base;
 
 	struct skl_ddb_entry ddb[I915_MAX_PIPES];
+	unsigned int weight[I915_MAX_PIPES];
+	u8 slices[I915_MAX_PIPES];
 
 	u8 enabled_slices;
 	u8 active_pipes;