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