[Intel-gfx] [PATCH v4 12/23] drm/i915: Introduce MBUS relative dbuf offsets

Matt Roper matthew.d.roper at intel.com
Sat May 15 03:10:24 UTC 2021


From: Ville Syrjälä <ville.syrjala at linux.intel.com>

The dbuf slices are going to be split across several MBUS units.
The actual dbuf programming will use offsets relative to the
MBUS unit. To accommodate that we shall store the MBUS relative
offsets into the dbuf_state->ddb[] and crtc_state->plane_ddb*[].

For crtc_state->wm.skl.ddb however we want to stick to global
offsets as we use this to sanity check that the ddb allocations
don't overlap between pipes.

Cc: Clint Taylor <Clinton.A.Taylor at intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
Signed-off-by: Clinton Taylor <Clinton.A.Taylor at intel.com>
Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 40 ++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 411ec468d02a..cbbd966f710e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4057,6 +4057,20 @@ skl_ddb_entry_for_slices(struct drm_i915_private *dev_priv, u8 slice_mask,
 	WARN_ON(ddb->end > INTEL_INFO(dev_priv)->dbuf.size);
 }
 
+static unsigned int mbus_ddb_offset(struct drm_i915_private *i915, u8 slice_mask)
+{
+	struct skl_ddb_entry ddb;
+
+	if (slice_mask & (BIT(DBUF_S1) | BIT(DBUF_S2)))
+		slice_mask = BIT(DBUF_S1);
+	else if (slice_mask & (BIT(DBUF_S3) | BIT(DBUF_S4)))
+		slice_mask = BIT(DBUF_S3);
+
+	skl_ddb_entry_for_slices(i915, slice_mask, &ddb);
+
+	return ddb.start;
+}
+
 u32 skl_ddb_dbuf_slice_mask(struct drm_i915_private *dev_priv,
 			    const struct skl_ddb_entry *entry)
 {
@@ -4149,6 +4163,7 @@ skl_crtc_allocate_ddb(struct intel_atomic_state *state, struct intel_crtc *crtc)
 	struct intel_crtc_state *crtc_state;
 	struct skl_ddb_entry ddb_slices;
 	enum pipe pipe = crtc->pipe;
+	unsigned int mbus_offset;
 	u32 ddb_range_size;
 	u32 dbuf_slice_mask;
 	u32 start, end;
@@ -4163,6 +4178,7 @@ skl_crtc_allocate_ddb(struct intel_atomic_state *state, struct intel_crtc *crtc)
 	dbuf_slice_mask = new_dbuf_state->slices[pipe];
 
 	skl_ddb_entry_for_slices(dev_priv, dbuf_slice_mask, &ddb_slices);
+	mbus_offset = mbus_ddb_offset(dev_priv, dbuf_slice_mask);
 	ddb_range_size = skl_ddb_entry_size(&ddb_slices);
 
 	intel_crtc_dbuf_weights(new_dbuf_state, pipe,
@@ -4171,11 +4187,11 @@ skl_crtc_allocate_ddb(struct intel_atomic_state *state, struct intel_crtc *crtc)
 	start = ddb_range_size * weight_start / weight_total;
 	end = ddb_range_size * weight_end / weight_total;
 
-	new_dbuf_state->ddb[pipe].start = ddb_slices.start + start;
-	new_dbuf_state->ddb[pipe].end = ddb_slices.start + end;
-
+	new_dbuf_state->ddb[pipe].start = ddb_slices.start - mbus_offset + start;
+	new_dbuf_state->ddb[pipe].end = ddb_slices.start - mbus_offset + end;
 out:
-	if (skl_ddb_entry_equal(&old_dbuf_state->ddb[pipe],
+	if (old_dbuf_state->slices[pipe] == new_dbuf_state->slices[pipe] &&
+	    skl_ddb_entry_equal(&old_dbuf_state->ddb[pipe],
 				&new_dbuf_state->ddb[pipe]))
 		return 0;
 
@@ -4187,7 +4203,12 @@ skl_crtc_allocate_ddb(struct intel_atomic_state *state, struct intel_crtc *crtc)
 	if (IS_ERR(crtc_state))
 		return PTR_ERR(crtc_state);
 
-	crtc_state->wm.skl.ddb = new_dbuf_state->ddb[pipe];
+	/*
+	 * Used for checking overlaps, so we need absolute
+	 * offsets instead of MBUS relative offsets.
+	 */
+	crtc_state->wm.skl.ddb.start = mbus_offset + new_dbuf_state->ddb[pipe].start;
+	crtc_state->wm.skl.ddb.end = mbus_offset + new_dbuf_state->ddb[pipe].end;
 
 	drm_dbg_kms(&dev_priv->drm,
 		    "[CRTC:%d:%s] dbuf slices 0x%x -> 0x%x, ddb (%d - %d) -> (%d - %d), active pipes 0x%x -> 0x%x\n",
@@ -6416,6 +6437,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
 		struct intel_crtc_state *crtc_state =
 			to_intel_crtc_state(crtc->base.state);
 		enum pipe pipe = crtc->pipe;
+		unsigned int mbus_offset;
 		enum plane_id plane_id;
 
 		skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal);
@@ -6441,7 +6463,13 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
 
 		dbuf_state->weight[pipe] = intel_crtc_ddb_weight(crtc_state);
 
-		crtc_state->wm.skl.ddb = dbuf_state->ddb[pipe];
+		/*
+		 * Used for checking overlaps, so we need absolute
+		 * offsets instead of MBUS relative offsets.
+		 */
+		mbus_offset = mbus_ddb_offset(dev_priv, dbuf_state->slices[pipe]);
+		crtc_state->wm.skl.ddb.start = mbus_offset + dbuf_state->ddb[pipe].start;
+		crtc_state->wm.skl.ddb.end = mbus_offset + dbuf_state->ddb[pipe].end;
 
 		drm_dbg_kms(&dev_priv->drm,
 			    "[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x\n",
-- 
2.25.4



More information about the Intel-gfx mailing list