55efec4
From 0206aec944641c69815562407b73b6f9df22f041 Mon Sep 17 00:00:00 2001
55efec4
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
55efec4
Date: Mon, 20 Jun 2016 11:13:09 +0200
55efec4
Subject: [PATCH 03/17] drm/i915/gen9: Cache plane data rates in CRTC state
55efec4
55efec4
Upstream: since drm-intel-next-2016-05-22
55efec4
commit a1de91e5f3039dfc32ac2b77ffb280a68646cbc7
55efec4
55efec4
Author:     Matt Roper <matthew.d.roper@intel.com>
55efec4
AuthorDate: Thu May 12 07:05:57 2016 -0700
55efec4
Commit:     Matt Roper <matthew.d.roper@intel.com>
55efec4
CommitDate: Fri May 13 07:32:35 2016 -0700
55efec4
55efec4
    drm/i915/gen9: Cache plane data rates in CRTC state
55efec4
55efec4
    This will be important when we start calculating CRTC data rates for
55efec4
    in-flight CRTC states since it will allow us to calculate the total data
55efec4
    rate without needing to grab the plane state for any planes that aren't
55efec4
    updated by the transaction.
55efec4
55efec4
    Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
55efec4
    Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
55efec4
    Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-4-git-send-email-matthew.d.roper@intel.com
55efec4
---
55efec4
 drivers/gpu/drm/i915/intel_drv.h |  4 ++
55efec4
 drivers/gpu/drm/i915/intel_pm.c  | 92 ++++++++++++++++++++++++++--------------
55efec4
 2 files changed, 63 insertions(+), 33 deletions(-)
55efec4
55efec4
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
55efec4
index 7d19baf..7c00ab6 100644
55efec4
--- a/drivers/gpu/drm/i915/intel_drv.h
55efec4
+++ b/drivers/gpu/drm/i915/intel_drv.h
55efec4
@@ -385,6 +385,10 @@ struct intel_crtc_wm_state {
55efec4
 		struct {
55efec4
 			/* gen9+ only needs 1-step wm programming */
55efec4
 			struct skl_pipe_wm optimal;
55efec4
+
55efec4
+			/* cached plane data rate */
55efec4
+			unsigned plane_data_rate[I915_MAX_PLANES];
55efec4
+			unsigned plane_y_data_rate[I915_MAX_PLANES];
55efec4
 		} skl;
55efec4
 	};
55efec4
 
55efec4
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
55efec4
index 8f081b2..854f0a4 100644
55efec4
--- a/drivers/gpu/drm/i915/intel_pm.c
55efec4
+++ b/drivers/gpu/drm/i915/intel_pm.c
55efec4
@@ -2879,6 +2879,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
55efec4
 	struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
55efec4
 	struct drm_framebuffer *fb = pstate->fb;
55efec4
 	uint32_t width = 0, height = 0;
55efec4
+	unsigned format = fb ? fb->pixel_format : DRM_FORMAT_XRGB8888;
55efec4
+
55efec4
+	if (!intel_pstate->visible)
55efec4
+		return 0;
55efec4
+	if (pstate->plane->type == DRM_PLANE_TYPE_CURSOR)
55efec4
+		return 0;
55efec4
+	if (y && format != DRM_FORMAT_NV12)
55efec4
+		return 0;
55efec4
 
55efec4
 	width = drm_rect_width(&intel_pstate->src) >> 16;
55efec4
 	height = drm_rect_height(&intel_pstate->src) >> 16;
55efec4
@@ -2887,17 +2895,17 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
55efec4
 		swap(width, height);
55efec4
 
55efec4
 	/* for planar format */
55efec4
-	if (fb->pixel_format == DRM_FORMAT_NV12) {
55efec4
+	if (format == DRM_FORMAT_NV12) {
55efec4
 		if (y)  /* y-plane data rate */
55efec4
 			return width * height *
55efec4
-				drm_format_plane_cpp(fb->pixel_format, 0);
55efec4
+				drm_format_plane_cpp(format, 0);
55efec4
 		else    /* uv-plane data rate */
55efec4
 			return (width / 2) * (height / 2) *
55efec4
-				drm_format_plane_cpp(fb->pixel_format, 1);
55efec4
+				drm_format_plane_cpp(format, 1);
55efec4
 	}
55efec4
 
55efec4
 	/* for packed formats */
55efec4
-	return width * height * drm_format_plane_cpp(fb->pixel_format, 0);
55efec4
+	return width * height * drm_format_plane_cpp(format, 0);
55efec4
 }
55efec4
 
55efec4
 /*
55efec4
@@ -2906,32 +2914,34 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
55efec4
  *   3 * 4096 * 8192  * 4 < 2^32
55efec4
  */
55efec4
 static unsigned int
55efec4
-skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate)
55efec4
+skl_get_total_relative_data_rate(struct intel_crtc_state *cstate)
55efec4
 {
55efec4
 	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
55efec4
 	struct drm_device *dev = intel_crtc->base.dev;
55efec4
 	const struct intel_plane *intel_plane;
55efec4
-	unsigned int total_data_rate = 0;
55efec4
+	unsigned int rate, total_data_rate = 0;
55efec4
 
55efec4
+	/* Calculate and cache data rate for each plane */
55efec4
 	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
55efec4
 		const struct drm_plane_state *pstate = intel_plane->base.state;
55efec4
+		int id = skl_wm_plane_id(intel_plane);
55efec4
 
55efec4
-		if (pstate->fb == NULL)
55efec4
-			continue;
55efec4
+		/* packed/uv */
55efec4
+		rate = skl_plane_relative_data_rate(cstate, pstate, 0);
55efec4
+		cstate->wm.skl.plane_data_rate[id] = rate;
55efec4
 
55efec4
-		if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
55efec4
-			continue;
55efec4
+		/* y-plane */
55efec4
+		rate = skl_plane_relative_data_rate(cstate, pstate, 1);
55efec4
+		cstate->wm.skl.plane_y_data_rate[id] = rate;
55efec4
+	}
55efec4
 
55efec4
-		/* packed/uv */
55efec4
-		total_data_rate += skl_plane_relative_data_rate(cstate,
55efec4
-								pstate,
55efec4
-								0);
55efec4
+	/* Calculate CRTC's total data rate from cached values */
55efec4
+	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
55efec4
+		int id = skl_wm_plane_id(intel_plane);
55efec4
 
55efec4
-		if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
55efec4
-			/* y-plane */
55efec4
-			total_data_rate += skl_plane_relative_data_rate(cstate,
55efec4
-									pstate,
55efec4
-									1);
55efec4
+		/* packed/uv */
55efec4
+		total_data_rate += cstate->wm.skl.plane_data_rate[id];
55efec4
+		total_data_rate += cstate->wm.skl.plane_y_data_rate[id];
55efec4
 	}
55efec4
 
55efec4
 	return total_data_rate;
55efec4
@@ -2995,6 +3005,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
55efec4
 	 * FIXME: we may not allocate every single block here.
55efec4
 	 */
55efec4
 	total_data_rate = skl_get_total_relative_data_rate(cstate);
55efec4
+	if (total_data_rate == 0)
55efec4
+		return;
55efec4
 
55efec4
 	start = alloc->start;
55efec4
 	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
55efec4
@@ -3009,7 +3021,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
55efec4
 		if (plane->type == DRM_PLANE_TYPE_CURSOR)
55efec4
 			continue;
55efec4
 
55efec4
-		data_rate = skl_plane_relative_data_rate(cstate, pstate, 0);
55efec4
+		data_rate = cstate->wm.skl.plane_data_rate[id];
55efec4
 
55efec4
 		/*
55efec4
 		 * allocation for (packed formats) or (uv-plane part of planar format):
55efec4
@@ -3028,20 +3040,16 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
55efec4
 		/*
55efec4
 		 * allocation for y_plane part of planar format:
55efec4
 		 */
55efec4
-		if (pstate->fb->pixel_format == DRM_FORMAT_NV12) {
55efec4
-			y_data_rate = skl_plane_relative_data_rate(cstate,
55efec4
-								   pstate,
55efec4
-								   1);
55efec4
-			y_plane_blocks = y_minimum[id];
55efec4
-			y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
55efec4
-						total_data_rate);
55efec4
-
55efec4
-			ddb->y_plane[pipe][id].start = start;
55efec4
-			ddb->y_plane[pipe][id].end = start + y_plane_blocks;
55efec4
-
55efec4
-			start += y_plane_blocks;
55efec4
-		}
55efec4
+		y_data_rate = cstate->wm.skl.plane_y_data_rate[id];
55efec4
+
55efec4
+		y_plane_blocks = y_minimum[id];
55efec4
+		y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
55efec4
+					total_data_rate);
55efec4
 
55efec4
+		ddb->y_plane[pipe][id].start = start;
55efec4
+		ddb->y_plane[pipe][id].end = start + y_plane_blocks;
55efec4
+
55efec4
+		start += y_plane_blocks;
55efec4
 	}
55efec4
 
55efec4
 }
55efec4
@@ -3820,10 +3828,28 @@ void skl_wm_get_hw_state(struct drm_device *dev)
55efec4
 	struct drm_i915_private *dev_priv = dev->dev_private;
55efec4
 	struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
55efec4
 	struct drm_crtc *crtc;
55efec4
+	struct intel_crtc *intel_crtc;
55efec4
 
55efec4
 	skl_ddb_get_hw_state(dev_priv, ddb);
55efec4
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
55efec4
 		skl_pipe_wm_get_hw_state(crtc);
55efec4
+
55efec4
+	/* Calculate plane data rates */
55efec4
+	for_each_intel_crtc(dev, intel_crtc) {
55efec4
+		struct intel_crtc_state *cstate = intel_crtc->config;
55efec4
+		struct intel_plane *intel_plane;
55efec4
+
55efec4
+		for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
55efec4
+			const struct drm_plane_state *pstate =
55efec4
+				intel_plane->base.state;
55efec4
+			int id = skl_wm_plane_id(intel_plane);
55efec4
+
55efec4
+			cstate->wm.skl.plane_data_rate[id] =
55efec4
+				skl_plane_relative_data_rate(cstate, pstate, 0);
55efec4
+			cstate->wm.skl.plane_y_data_rate[id] =
55efec4
+				skl_plane_relative_data_rate(cstate, pstate, 1);
55efec4
+		}
55efec4
+	}
55efec4
 }
55efec4
 
55efec4
 static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
55efec4
-- 
55efec4
2.7.4
55efec4