7d2c2f2
From 2bf927b92091d11f778a2a972b996f24a63281be Mon Sep 17 00:00:00 2001
7d2c2f2
From: Matt Roper <matthew.d.roper@intel.com>
7d2c2f2
Date: Thu, 12 May 2016 07:05:58 -0700
7d2c2f2
Subject: [PATCH 04/17] drm/i915/gen9: Allow calculation of data rate for
7d2c2f2
 in-flight state (v2)
7d2c2f2
7d2c2f2
Our skl_get_total_relative_data_rate() function gets passed a crtc state
7d2c2f2
object to calculate the data rate for, but it currently always looks
7d2c2f2
up the committed plane states that correspond to that CRTC.  Let's
7d2c2f2
check whether the CRTC state is an in-flight state (meaning
7d2c2f2
cstate->state is non-NULL) and if so, use the corresponding in-flight
7d2c2f2
plane states.
7d2c2f2
7d2c2f2
We'll soon be using this function exclusively for in-flight states; at
7d2c2f2
that time we'll be able to simplify the function a bit, but for now we
7d2c2f2
allow it to be used in either mode.
7d2c2f2
7d2c2f2
v2:
7d2c2f2
 - Rebase on top of changes to cache plane data rates.
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-5-git-send-email-matthew.d.roper@intel.com
7d2c2f2
---
7d2c2f2
 drivers/gpu/drm/i915/intel_pm.c | 74 +++++++++++++++++++++++++++++++++--------
7d2c2f2
 1 file changed, 60 insertions(+), 14 deletions(-)
7d2c2f2
7d2c2f2
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
index 6835614..5104ba7 100644
7d2c2f2
--- a/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
+++ b/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
@@ -2975,25 +2975,69 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
7d2c2f2
  *   3 * 4096 * 8192  * 4 < 2^32
7d2c2f2
  */
7d2c2f2
 static unsigned int
7d2c2f2
-skl_get_total_relative_data_rate(struct intel_crtc_state *cstate)
7d2c2f2
+skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate)
7d2c2f2
 {
7d2c2f2
-	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
7d2c2f2
-	struct drm_device *dev = intel_crtc->base.dev;
7d2c2f2
+	struct drm_crtc_state *cstate = &intel_cstate->base;
7d2c2f2
+	struct drm_atomic_state *state = cstate->state;
7d2c2f2
+	struct drm_crtc *crtc = cstate->crtc;
7d2c2f2
+	struct drm_device *dev = crtc->dev;
7d2c2f2
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
7d2c2f2
 	const struct intel_plane *intel_plane;
7d2c2f2
 	unsigned int rate, total_data_rate = 0;
7d2c2f2
+	int id;
7d2c2f2
 
7d2c2f2
 	/* Calculate and cache data rate for each plane */
7d2c2f2
-	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
7d2c2f2
-		const struct drm_plane_state *pstate = intel_plane->base.state;
7d2c2f2
-		int id = skl_wm_plane_id(intel_plane);
7d2c2f2
+	/*
7d2c2f2
+	 * FIXME: At the moment this function can be called on either an
7d2c2f2
+	 * in-flight or a committed state object.  If it's in-flight then we
7d2c2f2
+	 * only want to re-calculate the plane data rate for planes that are
7d2c2f2
+	 * part of the transaction (i.e., we don't want to grab any additional
7d2c2f2
+	 * plane states if we don't have to).  If we're operating on committed
7d2c2f2
+	 * state, we'll just go ahead and recalculate the plane data rate for
7d2c2f2
+	 * all planes.
7d2c2f2
+	 *
7d2c2f2
+	 * Once we finish moving our DDB allocation to the atomic check phase,
7d2c2f2
+	 * we'll only be calling this function on in-flight state objects, so
7d2c2f2
+	 * the 'else' branch here will go away.
7d2c2f2
+	 */
7d2c2f2
+	if (state) {
7d2c2f2
+		struct drm_plane *plane;
7d2c2f2
+		struct drm_plane_state *pstate;
7d2c2f2
+		int i;
7d2c2f2
+
7d2c2f2
+		for_each_plane_in_state(state, plane, pstate, i) {
7d2c2f2
+			intel_plane = to_intel_plane(plane);
7d2c2f2
+			id = skl_wm_plane_id(intel_plane);
7d2c2f2
+
7d2c2f2
+			if (intel_plane->pipe != intel_crtc->pipe)
7d2c2f2
+				continue;
7d2c2f2
+
7d2c2f2
+			/* packed/uv */
7d2c2f2
+			rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
+							    pstate, 0);
7d2c2f2
+			intel_cstate->wm.skl.plane_data_rate[id] = rate;
7d2c2f2
+
7d2c2f2
+			/* y-plane */
7d2c2f2
+			rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
+							    pstate, 1);
7d2c2f2
+			intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
7d2c2f2
+		}
7d2c2f2
+	} else {
7d2c2f2
+		for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
7d2c2f2
+			const struct drm_plane_state *pstate =
7d2c2f2
+				intel_plane->base.state;
7d2c2f2
+			int id = skl_wm_plane_id(intel_plane);
7d2c2f2
 
7d2c2f2
-		/* packed/uv */
7d2c2f2
-		rate = skl_plane_relative_data_rate(cstate, pstate, 0);
7d2c2f2
-		cstate->wm.skl.plane_data_rate[id] = rate;
7d2c2f2
+			/* packed/uv */
7d2c2f2
+			rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
+							    pstate, 0);
7d2c2f2
+			intel_cstate->wm.skl.plane_data_rate[id] = rate;
7d2c2f2
 
7d2c2f2
-		/* y-plane */
7d2c2f2
-		rate = skl_plane_relative_data_rate(cstate, pstate, 1);
7d2c2f2
-		cstate->wm.skl.plane_y_data_rate[id] = rate;
7d2c2f2
+			/* y-plane */
7d2c2f2
+			rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
+							    pstate, 1);
7d2c2f2
+			intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
7d2c2f2
+		}
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
 	/* Calculate CRTC's total data rate from cached values */
7d2c2f2
@@ -3001,10 +3045,12 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *cstate)
7d2c2f2
 		int id = skl_wm_plane_id(intel_plane);
7d2c2f2
 
7d2c2f2
 		/* packed/uv */
7d2c2f2
-		total_data_rate += cstate->wm.skl.plane_data_rate[id];
7d2c2f2
-		total_data_rate += cstate->wm.skl.plane_y_data_rate[id];
7d2c2f2
+		total_data_rate += intel_cstate->wm.skl.plane_data_rate[id];
7d2c2f2
+		total_data_rate += intel_cstate->wm.skl.plane_y_data_rate[id];
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
+	WARN_ON(cstate->plane_mask && total_data_rate == 0);
7d2c2f2
+
7d2c2f2
 	return total_data_rate;
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
-- 
7d2c2f2
2.7.4
7d2c2f2