7d2c2f2
From 0830cf3698b5966d3409745f751fb6d3a555c254 Mon Sep 17 00:00:00 2001
7d2c2f2
From: Matt Roper <matthew.d.roper@intel.com>
7d2c2f2
Date: Thu, 12 May 2016 07:06:08 -0700
7d2c2f2
Subject: [PATCH 14/17] drm/i915/gen9: Propagate watermark calculation failures
7d2c2f2
 up the call chain
7d2c2f2
7d2c2f2
Once we move watermark calculation to the atomic check phase, we'll want
7d2c2f2
to start rejecting display configurations that exceed out watermark
7d2c2f2
limits.  At the moment we just assume that there's always a valid set of
7d2c2f2
watermarks, even though this may not actually be true.  Let's prepare by
7d2c2f2
passing return codes up through the call stack in preparation.
7d2c2f2
7d2c2f2
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
7d2c2f2
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
7d2c2f2
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-15-git-send-email-matthew.d.roper@intel.com
7d2c2f2
---
7d2c2f2
 drivers/gpu/drm/i915/intel_display.c | 10 ++--
7d2c2f2
 drivers/gpu/drm/i915/intel_pm.c      | 90 ++++++++++++++++++++++--------------
7d2c2f2
 2 files changed, 61 insertions(+), 39 deletions(-)
7d2c2f2
7d2c2f2
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
7d2c2f2
index 4db10d7..2190bac 100644
7d2c2f2
--- a/drivers/gpu/drm/i915/intel_display.c
7d2c2f2
+++ b/drivers/gpu/drm/i915/intel_display.c
7d2c2f2
@@ -13339,7 +13339,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
7d2c2f2
  * phase.  The code here should be run after the per-crtc and per-plane 'check'
7d2c2f2
  * handlers to ensure that all derived state has been updated.
7d2c2f2
  */
7d2c2f2
-static void calc_watermark_data(struct drm_atomic_state *state)
7d2c2f2
+static int calc_watermark_data(struct drm_atomic_state *state)
7d2c2f2
 {
7d2c2f2
 	struct drm_device *dev = state->dev;
7d2c2f2
 	struct drm_i915_private *dev_priv = to_i915(dev);
7d2c2f2
@@ -13375,7 +13375,9 @@ static void calc_watermark_data(struct drm_atomic_state *state)
7d2c2f2
 
7d2c2f2
 	/* Is there platform-specific watermark information to calculate? */
7d2c2f2
 	if (dev_priv->display.compute_global_watermarks)
7d2c2f2
-		dev_priv->display.compute_global_watermarks(state);
7d2c2f2
+		return dev_priv->display.compute_global_watermarks(state);
7d2c2f2
+
7d2c2f2
+	return 0;
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
 /**
7d2c2f2
@@ -13459,9 +13461,7 @@ static int intel_atomic_check(struct drm_device *dev,
7d2c2f2
 		return ret;
7d2c2f2
 
7d2c2f2
 	intel_fbc_choose_crtc(dev_priv, state);
7d2c2f2
-	calc_watermark_data(state);
7d2c2f2
-
7d2c2f2
-	return 0;
7d2c2f2
+	return calc_watermark_data(state);
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
 static int intel_atomic_prepare_commit(struct drm_device *dev,
7d2c2f2
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
index cb6b6f4..342aa66 100644
7d2c2f2
--- a/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
+++ b/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
@@ -3238,13 +3238,14 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
7d2c2f2
 	return false;
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
-static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
7d2c2f2
-				 struct intel_crtc_state *cstate,
7d2c2f2
-				 struct intel_plane_state *intel_pstate,
7d2c2f2
-				 uint16_t ddb_allocation,
7d2c2f2
-				 int level,
7d2c2f2
-				 uint16_t *out_blocks, /* out */
7d2c2f2
-				 uint8_t *out_lines /* out */)
7d2c2f2
+static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
7d2c2f2
+				struct intel_crtc_state *cstate,
7d2c2f2
+				struct intel_plane_state *intel_pstate,
7d2c2f2
+				uint16_t ddb_allocation,
7d2c2f2
+				int level,
7d2c2f2
+				uint16_t *out_blocks, /* out */
7d2c2f2
+				uint8_t *out_lines, /* out */
7d2c2f2
+				bool *enabled /* out */)
7d2c2f2
 {
7d2c2f2
 	struct drm_plane_state *pstate = &intel_pstate->base;
7d2c2f2
 	struct drm_framebuffer *fb = pstate->fb;
7d2c2f2
@@ -3256,8 +3257,10 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
7d2c2f2
 	uint8_t cpp;
7d2c2f2
 	uint32_t width = 0, height = 0;
7d2c2f2
 
7d2c2f2
-	if (latency == 0 || !cstate->base.active || !intel_pstate->visible)
7d2c2f2
-		return false;
7d2c2f2
+	if (latency == 0 || !cstate->base.active || !intel_pstate->visible) {
7d2c2f2
+		*enabled = false;
7d2c2f2
+		return 0;
7d2c2f2
+	}
7d2c2f2
 
7d2c2f2
 	width = drm_rect_width(&intel_pstate->src) >> 16;
7d2c2f2
 	height = drm_rect_height(&intel_pstate->src) >> 16;
7d2c2f2
@@ -3318,13 +3321,16 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
7d2c2f2
 			res_blocks++;
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
-	if (res_blocks >= ddb_allocation || res_lines > 31)
7d2c2f2
-		return false;
7d2c2f2
+	if (res_blocks >= ddb_allocation || res_lines > 31) {
7d2c2f2
+		*enabled = false;
7d2c2f2
+		return 0;
7d2c2f2
+	}
7d2c2f2
 
7d2c2f2
 	*out_blocks = res_blocks;
7d2c2f2
 	*out_lines = res_lines;
7d2c2f2
+	*enabled = true;
7d2c2f2
 
7d2c2f2
-	return true;
7d2c2f2
+	return 0;
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
 static int
7d2c2f2
@@ -3342,6 +3348,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv,
7d2c2f2
 	struct intel_plane_state *intel_pstate;
7d2c2f2
 	uint16_t ddb_blocks;
7d2c2f2
 	enum pipe pipe = intel_crtc->pipe;
7d2c2f2
+	int ret;
7d2c2f2
 
7d2c2f2
 	/*
7d2c2f2
 	 * We'll only calculate watermarks for planes that are actually
7d2c2f2
@@ -3379,13 +3386,16 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv,
7d2c2f2
 
7d2c2f2
 		ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
7d2c2f2
 
7d2c2f2
-		result->plane_en[i] = skl_compute_plane_wm(dev_priv,
7d2c2f2
-						cstate,
7d2c2f2
-						intel_pstate,
7d2c2f2
-						ddb_blocks,
7d2c2f2
-						level,
7d2c2f2
-						&result->plane_res_b[i],
7d2c2f2
-						&result->plane_res_l[i]);
7d2c2f2
+		ret = skl_compute_plane_wm(dev_priv,
7d2c2f2
+					   cstate,
7d2c2f2
+					   intel_pstate,
7d2c2f2
+					   ddb_blocks,
7d2c2f2
+					   level,
7d2c2f2
+					   &result->plane_res_b[i],
7d2c2f2
+					   &result->plane_res_l[i],
7d2c2f2
+					   &result->plane_en[i]);
7d2c2f2
+		if (ret)
7d2c2f2
+			return ret;
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
 	return 0;
7d2c2f2
@@ -3422,21 +3432,26 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
7d2c2f2
 	}
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
-static void skl_build_pipe_wm(struct intel_crtc_state *cstate,
7d2c2f2
-			      struct skl_ddb_allocation *ddb,
7d2c2f2
-			      struct skl_pipe_wm *pipe_wm)
7d2c2f2
+static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
7d2c2f2
+			     struct skl_ddb_allocation *ddb,
7d2c2f2
+			     struct skl_pipe_wm *pipe_wm)
7d2c2f2
 {
7d2c2f2
 	struct drm_device *dev = cstate->base.crtc->dev;
7d2c2f2
 	const struct drm_i915_private *dev_priv = dev->dev_private;
7d2c2f2
 	int level, max_level = ilk_wm_max_level(dev);
7d2c2f2
+	int ret;
7d2c2f2
 
7d2c2f2
 	for (level = 0; level <= max_level; level++) {
7d2c2f2
-		skl_compute_wm_level(dev_priv, ddb, cstate,
7d2c2f2
-				     level, &pipe_wm->wm[level]);
7d2c2f2
+		ret = skl_compute_wm_level(dev_priv, ddb, cstate,
7d2c2f2
+					   level, &pipe_wm->wm[level]);
7d2c2f2
+		if (ret)
7d2c2f2
+			return ret;
7d2c2f2
 	}
7d2c2f2
 	pipe_wm->linetime = skl_compute_linetime_wm(cstate);
7d2c2f2
 
7d2c2f2
 	skl_compute_transition_wm(cstate, &pipe_wm->trans_wm);
7d2c2f2
+
7d2c2f2
+	return 0;
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
 static void skl_compute_wm_results(struct drm_device *dev,
7d2c2f2
@@ -3683,21 +3698,27 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
7d2c2f2
 	}
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
-static bool skl_update_pipe_wm(struct drm_crtc_state *cstate,
7d2c2f2
-			       struct skl_ddb_allocation *ddb, /* out */
7d2c2f2
-			       struct skl_pipe_wm *pipe_wm /* out */)
7d2c2f2
+static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
7d2c2f2
+			      struct skl_ddb_allocation *ddb, /* out */
7d2c2f2
+			      struct skl_pipe_wm *pipe_wm, /* out */
7d2c2f2
+			      bool *changed /* out */)
7d2c2f2
 {
7d2c2f2
 	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc);
7d2c2f2
 	struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
7d2c2f2
+	int ret;
7d2c2f2
 
7d2c2f2
-	skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
7d2c2f2
+	ret = skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
7d2c2f2
+	if (ret)
7d2c2f2
+		return ret;
7d2c2f2
 
7d2c2f2
 	if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
7d2c2f2
-		return false;
7d2c2f2
+		*changed = false;
7d2c2f2
+	else
7d2c2f2
+		*changed = true;
7d2c2f2
 
7d2c2f2
 	intel_crtc->wm.active.skl = *pipe_wm;
7d2c2f2
 
7d2c2f2
-	return true;
7d2c2f2
+	return 0;
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
 static void skl_update_other_pipe_wm(struct drm_device *dev,
7d2c2f2
@@ -3730,8 +3751,8 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
7d2c2f2
 		if (!intel_crtc->active)
7d2c2f2
 			continue;
7d2c2f2
 
7d2c2f2
-		wm_changed = skl_update_pipe_wm(intel_crtc->base.state,
7d2c2f2
-						&r->ddb, &pipe_wm);
7d2c2f2
+		skl_update_pipe_wm(intel_crtc->base.state,
7d2c2f2
+				   &r->ddb, &pipe_wm, &wm_changed);
7d2c2f2
 
7d2c2f2
 		/*
7d2c2f2
 		 * If we end up re-computing the other pipe WM values, it's
7d2c2f2
@@ -3841,14 +3862,15 @@ static void skl_update_wm(struct drm_crtc *crtc)
7d2c2f2
 	struct skl_wm_values *results = &dev_priv->wm.skl_results;
7d2c2f2
 	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
7d2c2f2
 	struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal;
7d2c2f2
-
7d2c2f2
+	bool wm_changed;
7d2c2f2
 
7d2c2f2
 	/* Clear all dirty flags */
7d2c2f2
 	results->dirty_pipes = 0;
7d2c2f2
 
7d2c2f2
 	skl_clear_wm(results, intel_crtc->pipe);
7d2c2f2
 
7d2c2f2
-	if (!skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm))
7d2c2f2
+	skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm, &wm_changed);
7d2c2f2
+	if (!wm_changed)
7d2c2f2
 		return;
7d2c2f2
 
7d2c2f2
 	skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
7d2c2f2
-- 
7d2c2f2
2.7.4
7d2c2f2