[PATCH] drm/i915/skl: distribute DDB based on panel resolution

Mahesh Kumar mahesh1.kumar at intel.com
Thu Jul 26 14:42:56 UTC 2018


We distribute DDB equally among all pipes irrespective of display
buffer requirement of each pipe. This leads to a situation where high
resolution y-tiled display can not be enabled with 2 low resolution
displays.

Main contributing factor for DDB requirement is width of the display.
This patch make changes to distribute ddb based on display width.
So now display with higher width will get bigger chunk of DDB.

Signed-off-by: Mahesh Kumar <mahesh1.kumar at intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 57 +++++++++++++++++++++++++++++++++++------
 1 file changed, 49 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7312ecb73415..1db4f0b43fdb 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3802,6 +3802,52 @@ static unsigned int intel_get_ddb_size(struct drm_i915_private *dev_priv,
 	return ddb_size;
 }
 
+static void
+skl_ddb_get_pipe_allocation(struct drm_i915_private *dev_priv,
+			    const struct intel_crtc_state *cstate,
+			    unsigned int ddb_size,
+			    struct skl_ddb_entry *alloc)
+{
+	struct drm_atomic_state *state = cstate->base.state;
+	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+	struct drm_crtc *for_crtc = cstate->base.crtc;
+	enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe;
+	const struct drm_display_mode *adjusted_mode;
+	const struct drm_crtc_state *crtc_state;
+	const struct drm_crtc *crtc;
+	u32 pipe_width[I915_MAX_PIPES] = {0};
+	u32 total_width = 0, width_before_pipe = 0;
+	unsigned int pipe_size;
+	u16 ddb_size_before_pipe;
+	u32 i;
+
+	if (WARN_ON(!intel_state->modeset))
+		return;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		int hdisplay, vdisplay;
+		enum pipe pipe;
+
+		if (!crtc_state->enable)
+			continue;
+
+		pipe = to_intel_crtc(crtc)->pipe;
+		adjusted_mode = &crtc_state->adjusted_mode;
+		drm_mode_get_hv_timing(adjusted_mode, &hdisplay, &vdisplay);
+		pipe_width[pipe] = hdisplay;
+		total_width += pipe_width[pipe];
+
+		if (pipe < for_pipe)
+			width_before_pipe += pipe_width[pipe];
+	}
+
+	ddb_size_before_pipe = div_u64(ddb_size * width_before_pipe,
+				       total_width);
+	pipe_size = div_u64(ddb_size * pipe_width[for_pipe], total_width);
+	alloc->start = ddb_size_before_pipe;
+	alloc->end = alloc->start + pipe_size;
+}
+
 static void
 skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
 				   const struct intel_crtc_state *cstate,
@@ -3814,8 +3860,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_crtc *for_crtc = cstate->base.crtc;
-	unsigned int pipe_size, ddb_size;
-	int nth_active_pipe;
+	unsigned int ddb_size;
 
 	if (WARN_ON(!state) || !cstate->base.active) {
 		alloc->start = 0;
@@ -3849,11 +3894,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
 		return;
 	}
 
-	nth_active_pipe = hweight32(intel_state->active_crtcs &
-				    (drm_crtc_mask(for_crtc) - 1));
-	pipe_size = ddb_size / hweight32(intel_state->active_crtcs);
-	alloc->start = nth_active_pipe * ddb_size / *num_active;
-	alloc->end = alloc->start + pipe_size;
+	return skl_ddb_get_pipe_allocation(dev_priv, cstate, ddb_size, alloc);
 }
 
 static unsigned int skl_cursor_allocation(int num_active)
@@ -5259,7 +5300,7 @@ skl_ddb_add_affected_pipes(struct drm_atomic_state *state, bool *changed)
 	 * any other display updates race with this transaction, so we need
 	 * to grab the lock on *all* CRTC's.
 	 */
-	if (intel_state->active_pipe_changes) {
+	if (intel_state->active_pipe_changes || intel_state->modeset) {
 		realloc_pipes = ~0;
 		intel_state->wm_results.dirty_pipes = ~0;
 	}
-- 
2.16.2



More information about the Intel-gfx-trybot mailing list