7d2c2f2
From be60f2176911a4ac8e0450ab51f11c235a4984de Mon Sep 17 00:00:00 2001
7d2c2f2
From: Matt Roper <matthew.d.roper@intel.com>
7d2c2f2
Date: Thu, 12 May 2016 07:05:57 -0700
7d2c2f2
Subject: [PATCH 03/17] drm/i915/gen9: Cache plane data rates in CRTC state
7d2c2f2
7d2c2f2
This will be important when we start calculating CRTC data rates for
7d2c2f2
in-flight CRTC states since it will allow us to calculate the total data
7d2c2f2
rate without needing to grab the plane state for any planes that aren't
7d2c2f2
updated by the transaction.
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-4-git-send-email-matthew.d.roper@intel.com
7d2c2f2
---
7d2c2f2
 drivers/gpu/drm/i915/intel_drv.h |  4 ++
7d2c2f2
 drivers/gpu/drm/i915/intel_pm.c  | 92 ++++++++++++++++++++++++++--------------
7d2c2f2
 2 files changed, 63 insertions(+), 33 deletions(-)
7d2c2f2
7d2c2f2
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
7d2c2f2
index 5a186bf..6a95696 100644
7d2c2f2
--- a/drivers/gpu/drm/i915/intel_drv.h
7d2c2f2
+++ b/drivers/gpu/drm/i915/intel_drv.h
7d2c2f2
@@ -427,6 +427,10 @@ struct intel_crtc_wm_state {
7d2c2f2
 		struct {
7d2c2f2
 			/* gen9+ only needs 1-step wm programming */
7d2c2f2
 			struct skl_pipe_wm optimal;
7d2c2f2
+
7d2c2f2
+			/* cached plane data rate */
7d2c2f2
+			unsigned plane_data_rate[I915_MAX_PLANES];
7d2c2f2
+			unsigned plane_y_data_rate[I915_MAX_PLANES];
7d2c2f2
 		} skl;
7d2c2f2
 	};
7d2c2f2
 
7d2c2f2
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
index e15cb2a..6835614 100644
7d2c2f2
--- a/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
+++ b/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
@@ -2940,6 +2940,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
7d2c2f2
 	struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
7d2c2f2
 	struct drm_framebuffer *fb = pstate->fb;
7d2c2f2
 	uint32_t width = 0, height = 0;
7d2c2f2
+	unsigned format = fb ? fb->pixel_format : DRM_FORMAT_XRGB8888;
7d2c2f2
+
7d2c2f2
+	if (!intel_pstate->visible)
7d2c2f2
+		return 0;
7d2c2f2
+	if (pstate->plane->type == DRM_PLANE_TYPE_CURSOR)
7d2c2f2
+		return 0;
7d2c2f2
+	if (y && format != DRM_FORMAT_NV12)
7d2c2f2
+		return 0;
7d2c2f2
 
7d2c2f2
 	width = drm_rect_width(&intel_pstate->src) >> 16;
7d2c2f2
 	height = drm_rect_height(&intel_pstate->src) >> 16;
7d2c2f2
@@ -2948,17 +2956,17 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
7d2c2f2
 		swap(width, height);
7d2c2f2
 
7d2c2f2
 	/* for planar format */
7d2c2f2
-	if (fb->pixel_format == DRM_FORMAT_NV12) {
7d2c2f2
+	if (format == DRM_FORMAT_NV12) {
7d2c2f2
 		if (y)  /* y-plane data rate */
7d2c2f2
 			return width * height *
7d2c2f2
-				drm_format_plane_cpp(fb->pixel_format, 0);
7d2c2f2
+				drm_format_plane_cpp(format, 0);
7d2c2f2
 		else    /* uv-plane data rate */
7d2c2f2
 			return (width / 2) * (height / 2) *
7d2c2f2
-				drm_format_plane_cpp(fb->pixel_format, 1);
7d2c2f2
+				drm_format_plane_cpp(format, 1);
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
 	/* for packed formats */
7d2c2f2
-	return width * height * drm_format_plane_cpp(fb->pixel_format, 0);
7d2c2f2
+	return width * height * drm_format_plane_cpp(format, 0);
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
 /*
7d2c2f2
@@ -2967,32 +2975,34 @@ 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(const struct intel_crtc_state *cstate)
7d2c2f2
+skl_get_total_relative_data_rate(struct intel_crtc_state *cstate)
7d2c2f2
 {
7d2c2f2
 	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
7d2c2f2
 	struct drm_device *dev = intel_crtc->base.dev;
7d2c2f2
 	const struct intel_plane *intel_plane;
7d2c2f2
-	unsigned int total_data_rate = 0;
7d2c2f2
+	unsigned int rate, total_data_rate = 0;
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
-		if (pstate->fb == NULL)
7d2c2f2
-			continue;
7d2c2f2
+		/* packed/uv */
7d2c2f2
+		rate = skl_plane_relative_data_rate(cstate, pstate, 0);
7d2c2f2
+		cstate->wm.skl.plane_data_rate[id] = rate;
7d2c2f2
 
7d2c2f2
-		if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
7d2c2f2
-			continue;
7d2c2f2
+		/* y-plane */
7d2c2f2
+		rate = skl_plane_relative_data_rate(cstate, pstate, 1);
7d2c2f2
+		cstate->wm.skl.plane_y_data_rate[id] = rate;
7d2c2f2
+	}
7d2c2f2
 
7d2c2f2
-		/* packed/uv */
7d2c2f2
-		total_data_rate += skl_plane_relative_data_rate(cstate,
7d2c2f2
-								pstate,
7d2c2f2
-								0);
7d2c2f2
+	/* Calculate CRTC's total data rate from cached values */
7d2c2f2
+	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
7d2c2f2
+		int id = skl_wm_plane_id(intel_plane);
7d2c2f2
 
7d2c2f2
-		if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
7d2c2f2
-			/* y-plane */
7d2c2f2
-			total_data_rate += skl_plane_relative_data_rate(cstate,
7d2c2f2
-									pstate,
7d2c2f2
-									1);
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
 	}
7d2c2f2
 
7d2c2f2
 	return total_data_rate;
7d2c2f2
@@ -3056,6 +3066,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
7d2c2f2
 	 * FIXME: we may not allocate every single block here.
7d2c2f2
 	 */
7d2c2f2
 	total_data_rate = skl_get_total_relative_data_rate(cstate);
7d2c2f2
+	if (total_data_rate == 0)
7d2c2f2
+		return;
7d2c2f2
 
7d2c2f2
 	start = alloc->start;
7d2c2f2
 	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
7d2c2f2
@@ -3070,7 +3082,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
7d2c2f2
 		if (plane->type == DRM_PLANE_TYPE_CURSOR)
7d2c2f2
 			continue;
7d2c2f2
 
7d2c2f2
-		data_rate = skl_plane_relative_data_rate(cstate, pstate, 0);
7d2c2f2
+		data_rate = cstate->wm.skl.plane_data_rate[id];
7d2c2f2
 
7d2c2f2
 		/*
7d2c2f2
 		 * allocation for (packed formats) or (uv-plane part of planar format):
7d2c2f2
@@ -3089,20 +3101,16 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
7d2c2f2
 		/*
7d2c2f2
 		 * allocation for y_plane part of planar format:
7d2c2f2
 		 */
7d2c2f2
-		if (pstate->fb->pixel_format == DRM_FORMAT_NV12) {
7d2c2f2
-			y_data_rate = skl_plane_relative_data_rate(cstate,
7d2c2f2
-								   pstate,
7d2c2f2
-								   1);
7d2c2f2
-			y_plane_blocks = y_minimum[id];
7d2c2f2
-			y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
7d2c2f2
-						total_data_rate);
7d2c2f2
-
7d2c2f2
-			ddb->y_plane[pipe][id].start = start;
7d2c2f2
-			ddb->y_plane[pipe][id].end = start + y_plane_blocks;
7d2c2f2
-
7d2c2f2
-			start += y_plane_blocks;
7d2c2f2
-		}
7d2c2f2
+		y_data_rate = cstate->wm.skl.plane_y_data_rate[id];
7d2c2f2
+
7d2c2f2
+		y_plane_blocks = y_minimum[id];
7d2c2f2
+		y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
7d2c2f2
+					total_data_rate);
7d2c2f2
 
7d2c2f2
+		ddb->y_plane[pipe][id].start = start;
7d2c2f2
+		ddb->y_plane[pipe][id].end = start + y_plane_blocks;
7d2c2f2
+
7d2c2f2
+		start += y_plane_blocks;
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
 }
7d2c2f2
@@ -3879,10 +3887,28 @@ void skl_wm_get_hw_state(struct drm_device *dev)
7d2c2f2
 	struct drm_i915_private *dev_priv = dev->dev_private;
7d2c2f2
 	struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
7d2c2f2
 	struct drm_crtc *crtc;
7d2c2f2
+	struct intel_crtc *intel_crtc;
7d2c2f2
 
7d2c2f2
 	skl_ddb_get_hw_state(dev_priv, ddb);
7d2c2f2
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
7d2c2f2
 		skl_pipe_wm_get_hw_state(crtc);
7d2c2f2
+
7d2c2f2
+	/* Calculate plane data rates */
7d2c2f2
+	for_each_intel_crtc(dev, intel_crtc) {
7d2c2f2
+		struct intel_crtc_state *cstate = intel_crtc->config;
7d2c2f2
+		struct intel_plane *intel_plane;
7d2c2f2
+
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
+			cstate->wm.skl.plane_data_rate[id] =
7d2c2f2
+				skl_plane_relative_data_rate(cstate, pstate, 0);
7d2c2f2
+			cstate->wm.skl.plane_y_data_rate[id] =
7d2c2f2
+				skl_plane_relative_data_rate(cstate, pstate, 1);
7d2c2f2
+		}
7d2c2f2
+	}
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
 static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
7d2c2f2
-- 
7d2c2f2
2.7.4
7d2c2f2