[Intel-gfx] [RFC 1/7] drm/i915: Calculate gen3- watermarks semi-atomically.

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Thu May 4 11:41:27 UTC 2017


The gen3 watermark calculations are converted to atomic,
but the wm update calls are still done through the legacy
functions.

This will make it easier to bisect things if they go wrong.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   3 +-
 drivers/gpu/drm/i915/intel_drv.h     |  14 +++
 drivers/gpu/drm/i915/intel_pm.c      | 231 +++++++++++++++++++++--------------
 3 files changed, 152 insertions(+), 96 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4991ef2ac77d..c7d295a0895d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15518,7 +15518,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
 		skl_wm_get_hw_state(dev);
 	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		ilk_wm_get_hw_state(dev);
-	}
+	} else if (INTEL_GEN(dev_priv) <= 3 && !IS_PINEVIEW(dev_priv))
+		i9xx_wm_get_hw_state(dev);
 
 	for_each_intel_crtc(dev, crtc) {
 		u64 put_domains;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ae9173707959..d9e49f2b3c22 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -546,6 +546,15 @@ struct g4x_wm_state {
 	bool fbc_en;
 };
 
+struct i9xx_wm_state {
+	uint16_t plane_wm;
+	bool cxsr;
+
+	struct {
+		uint16_t plane;
+	} sr;
+};
+
 struct intel_crtc_wm_state {
 	union {
 		struct {
@@ -590,6 +599,9 @@ struct intel_crtc_wm_state {
 			/* optimal watermarks */
 			struct g4x_wm_state optimal;
 		} g4x;
+		struct {
+			struct i9xx_wm_state optimal;
+		} i9xx;
 	};
 
 	/*
@@ -828,6 +840,7 @@ struct intel_crtc {
 			struct intel_pipe_wm ilk;
 			struct vlv_wm_state vlv;
 			struct g4x_wm_state g4x;
+			struct i9xx_wm_state i9xx;
 		} active;
 	} wm;
 
@@ -1868,6 +1881,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv,
 		    unsigned long submitted);
 void intel_queue_rps_boost_for_request(struct drm_i915_gem_request *req);
 void g4x_wm_get_hw_state(struct drm_device *dev);
+void i9xx_wm_get_hw_state(struct drm_device *dev);
 void vlv_wm_get_hw_state(struct drm_device *dev);
 void ilk_wm_get_hw_state(struct drm_device *dev);
 void skl_wm_get_hw_state(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d2cec3249e87..0c933cfad02c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2226,89 +2226,154 @@ static void i965_update_wm(struct intel_crtc *unused_crtc)
 
 #undef FW_WM
 
-static void i9xx_update_wm(struct intel_crtc *unused_crtc)
+static const struct intel_watermark_params *i9xx_get_wm_info(struct drm_i915_private *dev_priv,
+							     struct intel_crtc *crtc)
 {
-	struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
-	const struct intel_watermark_params *wm_info;
-	uint32_t fwater_lo;
-	uint32_t fwater_hi;
-	int cwm, srwm = 1;
-	int fifo_size;
-	int planea_wm, planeb_wm;
-	struct intel_crtc *crtc, *enabled = NULL;
+	struct intel_plane *plane = to_intel_plane(crtc->base.primary);
 
 	if (IS_I945GM(dev_priv))
-		wm_info = &i945_wm_info;
+		return &i945_wm_info;
 	else if (!IS_GEN2(dev_priv))
-		wm_info = &i915_wm_info;
+		return &i915_wm_info;
+	else if (plane->plane == PLANE_A)
+		return &i830_a_wm_info;
 	else
-		wm_info = &i830_a_wm_info;
+		return &i830_bc_wm_info;
+}
 
-	fifo_size = dev_priv->display.get_fifo_size(dev_priv, 0);
-	crtc = intel_get_crtc_for_plane(dev_priv, 0);
-	if (intel_crtc_active(crtc)) {
+static int i9xx_compute_pipe_wm(struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct intel_atomic_state *state =
+		to_intel_atomic_state(crtc_state->base.state);
+	struct i9xx_wm_state *wm_state = &crtc_state->wm.i9xx.optimal;
+	struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+	const struct drm_plane_state *plane_state = NULL;
+	int fifo_size;
+	const struct intel_watermark_params *wm_info;
+
+	fifo_size = dev_priv->display.get_fifo_size(dev_priv, plane->plane);
+
+	wm_info = i9xx_get_wm_info(dev_priv, crtc);
+
+	wm_state->cxsr = false;
+	memset(&wm_state->sr, 0, sizeof(wm_state->sr));
+
+	if (crtc_state->base.plane_mask & BIT(drm_plane_index(&plane->base)))
+		plane_state = __drm_atomic_get_current_plane_state(&state->base, &plane->base);
+
+	if (!plane_state || !intel_wm_plane_visible(crtc_state, to_intel_plane_state(plane_state))) {
+		wm_state->plane_wm = fifo_size - wm_info->guard_size;
+		if (wm_state->plane_wm > (long)wm_info->max_wm)
+			wm_state->plane_wm = wm_info->max_wm;
+	} else if (HAS_FW_BLC(dev_priv)) {
+		struct drm_framebuffer *fb = plane_state->fb;
+		unsigned cpp = IS_GEN2(dev_priv) ? 4 : fb->format->cpp[0];
 		const struct drm_display_mode *adjusted_mode =
-			&crtc->config->base.adjusted_mode;
-		const struct drm_framebuffer *fb =
-			crtc->base.primary->state->fb;
-		int cpp;
+			&crtc_state->base.adjusted_mode;
+		unsigned active_crtcs;
+		bool may_cxsr;
 
-		if (IS_GEN2(dev_priv))
-			cpp = 4;
+		if (state->modeset)
+			active_crtcs = state->active_crtcs;
 		else
-			cpp = fb->format->cpp[0];
+			active_crtcs = dev_priv->active_crtcs;
 
-		planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
-					       wm_info, fifo_size, cpp,
-					       pessimal_latency_ns);
-		enabled = crtc;
-	} else {
-		planea_wm = fifo_size - wm_info->guard_size;
-		if (planea_wm > (long)wm_info->max_wm)
-			planea_wm = wm_info->max_wm;
+		may_cxsr = active_crtcs == drm_crtc_mask(&crtc->base);
+
+		wm_state->plane_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
+							wm_info, fifo_size, cpp,
+							pessimal_latency_ns);
+
+		DRM_DEBUG_KMS("FIFO watermarks - plane watermarks: %d\n", wm_state->plane_wm);
+
+		if (IS_I915GM(dev_priv) && i915_gem_object_is_tiled(intel_fb_obj(fb)))
+			may_cxsr = false;
+
+		if (may_cxsr) {
+			static const int sr_latency_ns = 6000;
+			unsigned long entries;
+
+			entries = intel_wm_method2(adjusted_mode->crtc_clock,
+						   adjusted_mode->crtc_htotal,
+						   crtc_state->pipe_src_w, cpp,
+						   sr_latency_ns / 100);
+			entries = DIV_ROUND_UP(entries, wm_info->cacheline_size);
+
+			DRM_DEBUG_KMS("self-refresh entries: %ld\n", entries);
+
+			if (wm_info->fifo_size >= entries) {
+				wm_state->cxsr = true;
+				wm_state->sr.plane = wm_info->fifo_size - entries;
+			} else
+				may_cxsr = false;
+		}
+
+		DRM_DEBUG_KMS("FIFO watermarks - plane watermarks: %d, can cxsr: %s, SR size: %d\n",
+			      wm_state->plane_wm, yesno(wm_state->cxsr), wm_state->sr.plane);
 	}
 
-	if (IS_GEN2(dev_priv))
-		wm_info = &i830_bc_wm_info;
+	return 0;
+}
 
-	fifo_size = dev_priv->display.get_fifo_size(dev_priv, 1);
-	crtc = intel_get_crtc_for_plane(dev_priv, 1);
-	if (intel_crtc_active(crtc)) {
-		const struct drm_display_mode *adjusted_mode =
-			&crtc->config->base.adjusted_mode;
-		const struct drm_framebuffer *fb =
-			crtc->base.primary->state->fb;
-		int cpp;
+void i9xx_wm_get_hw_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_crtc *crtc;
+	uint32_t fwater_lo, planea_wm, planeb_wm;
+
+	fwater_lo = I915_READ(FW_BLC);
+
+	planea_wm = fwater_lo & 0x3f;
+	planeb_wm = (fwater_lo >> 16) & 0x3f;
+
+	for_each_intel_crtc(dev, crtc) {
+		struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->base.state);
+		struct i9xx_wm_state *wm_state = &cstate->wm.i9xx.optimal;
+		struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+
+		memset(&wm_state->sr, 0, sizeof(wm_state->sr));
+		wm_state->cxsr = false;
 
-		if (IS_GEN2(dev_priv))
-			cpp = 4;
+		if (plane == PLANE_A)
+			wm_state->plane_wm = planea_wm;
 		else
-			cpp = fb->format->cpp[0];
+			wm_state->plane_wm = planeb_wm;
+
+		crtc->wm.active.i9xx = *wm_state;
+	}
+}
 
-		planeb_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
-					       wm_info, fifo_size, cpp,
-					       pessimal_latency_ns);
+static void i9xx_update_wm(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	uint32_t fwater_lo;
+	uint32_t fwater_hi;
+	int cwm, srwm = -1;
+	int planea_wm, planeb_wm;
+	struct intel_crtc *enabled = NULL;
+
+	crtc->wm.active.i9xx = crtc->config->wm.i9xx.optimal;
+
+	crtc = intel_get_crtc_for_plane(dev_priv, 0);
+	planea_wm = crtc->wm.active.i9xx.plane_wm;
+	if (intel_crtc_active(crtc))
+		enabled = crtc;
+
+	crtc = intel_get_crtc_for_plane(dev_priv, 1);
+	if (intel_crtc_active(crtc)) {
 		if (enabled == NULL)
 			enabled = crtc;
 		else
 			enabled = NULL;
-	} else {
-		planeb_wm = fifo_size - wm_info->guard_size;
-		if (planeb_wm > (long)wm_info->max_wm)
-			planeb_wm = wm_info->max_wm;
 	}
+	planeb_wm = crtc->wm.active.i9xx.plane_wm;
 
 	DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
 
-	if (IS_I915GM(dev_priv) && enabled) {
-		struct drm_i915_gem_object *obj;
-
-		obj = intel_fb_obj(enabled->base.primary->state->fb);
-
-		/* self-refresh seems busted with untiled */
-		if (!i915_gem_object_is_tiled(obj))
-			enabled = NULL;
-	}
+	if (!enabled->wm.active.i9xx.cxsr)
+		enabled = NULL;
 
 	/*
 	 * Overlay gets an aggressive default since video jitter is bad.
@@ -2319,31 +2384,8 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
 	intel_set_memory_cxsr(dev_priv, false);
 
 	/* Calc sr entries for one plane configs */
-	if (HAS_FW_BLC(dev_priv) && enabled) {
-		/* self-refresh has much higher latency */
-		static const int sr_latency_ns = 6000;
-		const struct drm_display_mode *adjusted_mode =
-			&enabled->config->base.adjusted_mode;
-		const struct drm_framebuffer *fb =
-			enabled->base.primary->state->fb;
-		int clock = adjusted_mode->crtc_clock;
-		int htotal = adjusted_mode->crtc_htotal;
-		int hdisplay = enabled->config->pipe_src_w;
-		int cpp;
-		int entries;
-
-		if (IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
-			cpp = 4;
-		else
-			cpp = fb->format->cpp[0];
-
-		entries = intel_wm_method2(clock, htotal, hdisplay, cpp,
-					   sr_latency_ns / 100);
-		entries = DIV_ROUND_UP(entries, wm_info->cacheline_size);
-		DRM_DEBUG_KMS("self-refresh entries: %d\n", entries);
-		srwm = wm_info->fifo_size - entries;
-		if (srwm < 0)
-			srwm = 1;
+	if (enabled) {
+		srwm = enabled->wm.active.i9xx.sr.plane;
 
 		if (IS_I945G(dev_priv) || IS_I945GM(dev_priv))
 			I915_WRITE(FW_BLC_SELF,
@@ -2369,23 +2411,18 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
 		intel_set_memory_cxsr(dev_priv, true);
 }
 
-static void i845_update_wm(struct intel_crtc *unused_crtc)
+static void i845_update_wm(struct intel_crtc *crtc)
 {
-	struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
-	struct intel_crtc *crtc;
-	const struct drm_display_mode *adjusted_mode;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	uint32_t fwater_lo;
 	int planea_wm;
 
-	crtc = single_enabled_crtc(dev_priv);
-	if (crtc == NULL)
+	if (!intel_crtc_active(crtc))
 		return;
 
-	adjusted_mode = &crtc->config->base.adjusted_mode;
-	planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
-				       &i845_wm_info,
-				       dev_priv->display.get_fifo_size(dev_priv, 0),
-				       4, pessimal_latency_ns);
+	crtc->wm.active.i9xx = crtc->config->wm.i9xx.optimal;
+	planea_wm = crtc->wm.active.i9xx.plane_wm;
+
 	fwater_lo = I915_READ(FW_BLC) & ~0xfff;
 	fwater_lo |= (3<<8) | planea_wm;
 
@@ -8705,9 +8742,13 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
 	} else if (IS_GEN4(dev_priv)) {
 		dev_priv->display.update_wm = i965_update_wm;
 	} else if (IS_GEN3(dev_priv)) {
+		dev_priv->display.compute_pipe_wm = i9xx_compute_pipe_wm;
 		dev_priv->display.update_wm = i9xx_update_wm;
+
 		dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
 	} else if (IS_GEN2(dev_priv)) {
+		dev_priv->display.compute_pipe_wm = i9xx_compute_pipe_wm;
+
 		if (INTEL_INFO(dev_priv)->num_pipes == 1) {
 			dev_priv->display.update_wm = i845_update_wm;
 			dev_priv->display.get_fifo_size = i845_get_fifo_size;
-- 
2.9.3



More information about the Intel-gfx mailing list