0903551
From c3d2591095045a8230361d55fadf15ce5dc9127d Mon Sep 17 00:00:00 2001
0903551
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
0903551
Date: Mon, 20 Jun 2016 12:41:12 +0200
0903551
Subject: [PATCH 12/17] drm/i915/gen9: Allow watermark calculation on in-flight
0903551
 atomic state (v3)
0903551
0903551
Upstream: since drm-intel-next-2016-05-22
0903551
commit f4a967523ec7215a3ec867b7ed2e916bd34840e1
0903551
0903551
Author:     Matt Roper <matthew.d.roper@intel.com>
0903551
AuthorDate: Thu May 12 07:06:06 2016 -0700
0903551
Commit:     Matt Roper <matthew.d.roper@intel.com>
0903551
CommitDate: Fri May 13 07:34:23 2016 -0700
0903551
0903551
    drm/i915/gen9: Allow watermark calculation on in-flight atomic state (v3)
0903551
0903551
    In an upcoming patch we'll move this calculation to the atomic 'check'
0903551
    phase so that the display update can be rejected early if no valid
0903551
    watermark programming is possible.
0903551
0903551
    v2:
0903551
     - Drop intel_pstate_for_cstate_plane() helper and add note about how
0903551
       the code needs to evolve in the future if we start allowing more than
0903551
       one pending commit against a CRTC.  (Maarten)
0903551
0903551
    v3:
0903551
     - Only have skl_compute_wm_level calculate watermarks for enabled
0903551
       planes; we can just set the other planes on a CRTC to disabled
0903551
       without having to look at the plane state.  This is important because
0903551
       despite our CRTC lock we can still have racing commits that modify
0903551
       a disabled plane's property without turning it on.  (Maarten)
0903551
0903551
    Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
0903551
    Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
0903551
    Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-13-git-send-email-matthew.d.roper@intel.com
0903551
---
0903551
 drivers/gpu/drm/i915/intel_pm.c | 61 ++++++++++++++++++++++++++++++++---------
0903551
 1 file changed, 48 insertions(+), 13 deletions(-)
0903551
0903551
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
0903551
index 3164f30..cd29ab6 100644
0903551
--- a/drivers/gpu/drm/i915/intel_pm.c
0903551
+++ b/drivers/gpu/drm/i915/intel_pm.c
0903551
@@ -3266,23 +3266,56 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
0903551
 	return true;
0903551
 }
0903551
 
0903551
-static void skl_compute_wm_level(const struct drm_i915_private *dev_priv,
0903551
-				 struct skl_ddb_allocation *ddb,
0903551
-				 struct intel_crtc_state *cstate,
0903551
-				 int level,
0903551
-				 struct skl_wm_level *result)
0903551
+static int
0903551
+skl_compute_wm_level(const struct drm_i915_private *dev_priv,
0903551
+		     struct skl_ddb_allocation *ddb,
0903551
+		     struct intel_crtc_state *cstate,
0903551
+		     int level,
0903551
+		     struct skl_wm_level *result)
0903551
 {
0903551
 	struct drm_device *dev = dev_priv->dev;
0903551
+	struct drm_atomic_state *state = cstate->base.state;
0903551
 	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
0903551
+	struct drm_plane *plane;
0903551
 	struct intel_plane *intel_plane;
0903551
 	struct intel_plane_state *intel_pstate;
0903551
 	uint16_t ddb_blocks;
0903551
 	enum pipe pipe = intel_crtc->pipe;
0903551
 
0903551
-	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
0903551
+	/*
0903551
+	 * We'll only calculate watermarks for planes that are actually
0903551
+	 * enabled, so make sure all other planes are set as disabled.
0903551
+	 */
0903551
+	memset(result, 0, sizeof(*result));
0903551
+
0903551
+	for_each_intel_plane_mask(dev, intel_plane, cstate->base.plane_mask) {
0903551
 		int i = skl_wm_plane_id(intel_plane);
0903551
 
0903551
-		intel_pstate = to_intel_plane_state(intel_plane->base.state);
0903551
+		plane = &intel_plane->base;
0903551
+		intel_pstate = NULL;
0903551
+		if (state)
0903551
+			intel_pstate =
0903551
+				intel_atomic_get_existing_plane_state(state,
0903551
+								      intel_plane);
0903551
+
0903551
+		/*
0903551
+		 * Note: If we start supporting multiple pending atomic commits
0903551
+		 * against the same planes/CRTC's in the future, plane->state
0903551
+		 * will no longer be the correct pre-state to use for the
0903551
+		 * calculations here and we'll need to change where we get the
0903551
+		 * 'unchanged' plane data from.
0903551
+		 *
0903551
+		 * For now this is fine because we only allow one queued commit
0903551
+		 * against a CRTC.  Even if the plane isn't modified by this
0903551
+		 * transaction and we don't have a plane lock, we still have
0903551
+		 * the CRTC's lock, so we know that no other transactions are
0903551
+		 * racing with us to update it.
0903551
+		 */
0903551
+		if (!intel_pstate)
0903551
+			intel_pstate = to_intel_plane_state(plane->state);
0903551
+
0903551
+		WARN_ON(!intel_pstate->base.fb);
0903551
+
0903551
 		ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
0903551
 
0903551
 		result->plane_en[i] = skl_compute_plane_wm(dev_priv,
0903551
@@ -3293,6 +3326,8 @@ static void skl_compute_wm_level(const struct drm_i915_private *dev_priv,
0903551
 						&result->plane_res_b[i],
0903551
 						&result->plane_res_l[i]);
0903551
 	}
0903551
+
0903551
+	return 0;
0903551
 }
0903551
 
0903551
 static uint32_t
0903551
@@ -3587,14 +3622,14 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
0903551
 	}
0903551
 }
0903551
 
0903551
-static bool skl_update_pipe_wm(struct drm_crtc *crtc,
0903551
+static bool skl_update_pipe_wm(struct drm_crtc_state *cstate,
0903551
 			       struct skl_ddb_allocation *ddb, /* out */
0903551
 			       struct skl_pipe_wm *pipe_wm /* out */)
0903551
 {
0903551
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
0903551
-	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
0903551
+	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc);
0903551
+	struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
0903551
 
0903551
-	skl_build_pipe_wm(cstate, ddb, pipe_wm);
0903551
+	skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
0903551
 
0903551
 	if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
0903551
 		return false;
0903551
@@ -3634,7 +3669,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
0903551
 		if (!intel_crtc->active)
0903551
 			continue;
0903551
 
0903551
-		wm_changed = skl_update_pipe_wm(&intel_crtc->base,
0903551
+		wm_changed = skl_update_pipe_wm(intel_crtc->base.state,
0903551
 						&r->ddb, &pipe_wm);
0903551
 
0903551
 		/*
0903551
@@ -3752,7 +3787,7 @@ static void skl_update_wm(struct drm_crtc *crtc)
0903551
 
0903551
 	skl_clear_wm(results, intel_crtc->pipe);
0903551
 
0903551
-	if (!skl_update_pipe_wm(crtc, &results->ddb, pipe_wm))
0903551
+	if (!skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm))
0903551
 		return;
0903551
 
0903551
 	skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
0903551
-- 
0903551
2.7.4
0903551