[PATCH v5 1/2] drm/i915: Refactor intel_can_enable_sagv

Stanislav Lisovskiy stanislav.lisovskiy at intel.com
Mon Oct 21 14:50:31 UTC 2019


Currently intel_can_enable_sagv function contains
a mix of workarounds for different platforms
some of them are not valid for gens >= 11 already,
so lets split it into separate functions.

v2:
    - Rework watermark calculation algorithm to
      attempt to calculate Level 0 watermark
      with added sagv block time latency and
      check if it fits in DBuf in order to
      determine if SAGV can be enabled already
      at this stage, just as BSpec 49325 states.
      if that fails rollback to usual Level 0
      latency and disable SAGV.
    - Remove unneeded tabs(James Ausmus)

Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy at intel.com>
Cc: Ville Syrjälä <ville.syrjala at intel.com>
Cc: James Ausmus <james.ausmus at intel.com>
---
 .../drm/i915/display/intel_display_types.h    |   7 +
 drivers/gpu/drm/i915/intel_pm.c               | 150 +++++++++++++++++-
 2 files changed, 155 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 40390d855815..d6047c37d942 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -490,6 +490,13 @@ struct intel_atomic_state {
 	 */
 	u8 active_pipe_changes;
 
+	/*
+	 * For Gen12 only after calculating watermarks with
+	 * additional latency, we can determine if SAGV can be enabled
+	 * or not for that particular configuration.
+	 */
+	bool gen12_can_sagv;
+
 	u8 active_pipes;
 	/* minimum acceptable cdclk for each pipe */
 	int min_cdclk[I915_MAX_PIPES];
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 67d171456f59..a8a77d744d44 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3750,7 +3750,7 @@ intel_disable_sagv(struct drm_i915_private *dev_priv)
 	return 0;
 }
 
-bool intel_can_enable_sagv(struct intel_atomic_state *state)
+bool skl_can_enable_sagv(struct intel_atomic_state *state)
 {
 	struct drm_device *dev = state->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
@@ -3816,6 +3816,75 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state)
 	return true;
 }
 
+bool icl_can_enable_sagv(struct intel_atomic_state *state)
+{
+	struct drm_device *dev = state->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_crtc *crtc;
+	struct intel_crtc_state *new_crtc_state;
+	int level, latency;
+	int i;
+	int plane_id;
+
+	if (!intel_has_sagv(dev_priv))
+		return false;
+
+	/*
+	 * If there are no active CRTCs, no additional checks need be performed
+	 */
+	if (hweight8(state->active_pipes) == 0)
+		return true;
+
+	for_each_new_intel_crtc_in_state(state, crtc,
+					     new_crtc_state, i) {
+
+		if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+			return false;
+
+		if (!new_crtc_state->base.enable)
+			continue;
+
+		for_each_plane_id_on_crtc(crtc, plane_id) {
+			struct skl_plane_wm *wm =
+				&new_crtc_state->wm.skl.optimal.planes[plane_id];
+
+			/* Skip this plane if it's not enabled */
+			if (!wm->wm[0].plane_en)
+				continue;
+
+			/* Find the highest enabled wm level for this plane */
+			for (level = ilk_wm_max_level(dev_priv);
+			     !wm->wm[level].plane_en; --level)
+			     { }
+
+			latency = dev_priv->wm.skl_latency[level];
+
+			/*
+			 * If any of the planes on this pipe don't enable wm levels that
+			 * incur memory latencies higher than sagv_block_time_us we
+			 * can't enable SAGV.
+			 */
+			if (latency < dev_priv->sagv_block_time_us)
+				return false;
+		}
+	}
+
+	return true;
+}
+
+bool intel_can_enable_sagv(struct intel_atomic_state *state)
+{
+	struct drm_device *dev = state->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+
+	if (INTEL_GEN(dev_priv) >= 12)
+		return state->gen12_can_sagv;
+	else if (INTEL_GEN(dev_priv) == 11)
+		return icl_can_enable_sagv(state);
+
+	return skl_can_enable_sagv(state);
+}
+
 static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
 			      const struct intel_crtc_state *crtc_state,
 			      const u64 total_data_rate,
@@ -4950,6 +5019,13 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
 		return;
 	}
 
+	if ((INTEL_GEN(dev_priv) >= 12) && level == 0) {
+		struct intel_atomic_state *state = \
+			    to_intel_atomic_state(crtc_state->base.state);
+		if (state->gen12_can_sagv)
+			latency += dev_priv->sagv_block_time_us;
+	}
+
 	/*
 	 * WaIncreaseLatencyIPCEnabled: kbl,cfl
 	 * Display WA #1141: kbl,cfl
@@ -5813,6 +5889,70 @@ skl_compute_wm(struct intel_atomic_state *state)
 	return 0;
 }
 
+static int
+tgl_compute_wm(struct intel_atomic_state *state)
+{
+	struct intel_crtc *crtc;
+	struct intel_crtc_state *new_crtc_state;
+	struct intel_crtc_state *old_crtc_state;
+	struct skl_ddb_values *results = &state->wm_results;
+	bool changed = false;
+	int ret, i;
+
+	/* Clear all dirty flags */
+	results->dirty_pipes = 0;
+
+	ret = skl_ddb_add_affected_pipes(state, &changed);
+	if (ret || !changed)
+		return ret;
+
+	/*
+	 * Lets assume we can tolerate SAGV for now,
+	 * until watermark calculations prove the opposite
+	 */
+	state->gen12_can_sagv = true;
+
+start:
+	/*
+	 * 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 (and set bits in dirty_pipes) 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);
+		if (ret)
+			return ret;
+
+		ret = skl_wm_add_affected_planes(state, crtc);
+		if (ret)
+			return ret;
+
+		if (!skl_pipe_wm_equals(crtc,
+					&old_crtc_state->wm.skl.optimal,
+					&new_crtc_state->wm.skl.optimal))
+			results->dirty_pipes |= drm_crtc_mask(&crtc->base);
+	}
+
+	ret = skl_compute_ddb(state);
+	if (ret) {
+		/*
+		 * If we don't have enough space for SAGV enabled,
+		 * try next time without it.
+		 */
+		if (state->gen12_can_sagv) {
+			state->gen12_can_sagv = false;
+			goto start;
+		}
+		return ret;
+	}
+
+	skl_print_wm_changes(state);
+
+	return 0;
+}
+
 static void skl_atomic_update_crtc_wm(struct intel_atomic_state *state,
 				      struct intel_crtc_state *crtc_state)
 {
@@ -9210,7 +9350,13 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
 		skl_setup_sagv_block_time(dev_priv);
 
 	/* For FIFO watermark updates */
-	if (INTEL_GEN(dev_priv) >= 9) {
+	if (INTEL_GEN(dev_priv) >= 12) {
+		skl_setup_wm_latency(dev_priv);
+		dev_priv->display.initial_watermarks = skl_initial_wm;
+		dev_priv->display.atomic_update_watermarks = skl_atomic_update_crtc_wm;
+		dev_priv->display.compute_global_watermarks = tgl_compute_wm;
+	}
+	else if (INTEL_GEN(dev_priv) >= 9) {
 		skl_setup_wm_latency(dev_priv);
 		dev_priv->display.initial_watermarks = skl_initial_wm;
 		dev_priv->display.atomic_update_watermarks = skl_atomic_update_crtc_wm;
-- 
2.17.1



More information about the Intel-gfx-trybot mailing list