[01/12] drm/i915: Store all wm memory latency values in .1 usec units
diff mbox series

Message ID 20181010130454.28557-2-ville.syrjala@linux.intel.com
State New
Headers show
Series
  • drm/i915: Clean up the wm mem latency stuff
Related show

Commit Message

Ville Syrjälä Oct. 10, 2018, 1:04 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

In order to simplify the code let's store all memory latency values in
0.1 usec units. This limits the platform specific units to the initial
setup code for the most part.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  12 ---
 drivers/gpu/drm/i915/i915_drv.h     |  14 +--
 drivers/gpu/drm/i915/intel_pm.c     | 149 ++++++++++++++++------------
 3 files changed, 87 insertions(+), 88 deletions(-)

Comments

Chris Wilson Oct. 10, 2018, 1:12 p.m. UTC | #1
Quoting Ville Syrjala (2018-10-10 14:04:43)
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> In order to simplify the code let's store all memory latency values in
> 0.1 usec units. This limits the platform specific units to the initial
> setup code for the most part.

Asking for a friend: is it 0.1us or 128ns?
-Chris
Ville Syrjälä Oct. 10, 2018, 3:35 p.m. UTC | #2
On Wed, Oct 10, 2018 at 02:12:30PM +0100, Chris Wilson wrote:
> Quoting Ville Syrjala (2018-10-10 14:04:43)
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > In order to simplify the code let's store all memory latency values in
> > 0.1 usec units. This limits the platform specific units to the initial
> > setup code for the most part.
> 
> Asking for a friend: is it 0.1us or 128ns?

100ns

Patch
diff mbox series

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 00c551d3e409..9e0cb995801f 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3807,18 +3807,6 @@  static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
 	for (level = 0; level < num_levels; level++) {
 		unsigned int latency = wm[level];
 
-		/*
-		 * - WM1+ latency values in 0.5us units
-		 * - latencies are in us on gen9/vlv/chv
-		 */
-		if (INTEL_GEN(dev_priv) >= 9 ||
-		    IS_VALLEYVIEW(dev_priv) ||
-		    IS_CHERRYVIEW(dev_priv) ||
-		    IS_G4X(dev_priv))
-			latency *= 10;
-		else if (level > 0)
-			latency *= 5;
-
 		seq_printf(m, "WM%d %u (%u.%u usec)\n",
 			   level, wm[level], latency / 10, latency % 10);
 	}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 794a8a03c7e6..e57b8cb8fa4d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1906,22 +1906,10 @@  struct drm_i915_private {
 	} sagv_status;
 
 	struct {
-		/*
-		 * Raw watermark latency values:
-		 * in 0.1us units for WM0,
-		 * in 0.5us units for WM1+.
-		 */
-		/* primary */
+		/* Watermark memory latency values in 0.1 us units */
 		uint16_t pri_latency[5];
-		/* sprite */
 		uint16_t spr_latency[5];
-		/* cursor */
 		uint16_t cur_latency[5];
-		/*
-		 * Raw watermark memory latency values
-		 * for SKL for all 8 levels
-		 * in 1us units.
-		 */
 		uint16_t skl_latency[8];
 
 		/* current hardware state */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 1392aa56a55a..f871a6f152c3 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -801,6 +801,27 @@  static int intel_wm_num_levels(struct drm_i915_private *dev_priv)
 	return dev_priv->wm.max_level + 1;
 }
 
+static int intel_plane_wm_latency(struct intel_plane *plane,
+				  int level)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		return dev_priv->wm.skl_latency[level];
+
+	if (HAS_GMCH_DISPLAY(dev_priv))
+		return dev_priv->wm.pri_latency[level];
+
+	switch (plane->id) {
+	case PLANE_PRIMARY:
+		return dev_priv->wm.pri_latency[level];
+	case PLANE_CURSOR:
+		return dev_priv->wm.cur_latency[level];
+	default:
+		return dev_priv->wm.spr_latency[level];
+	}
+}
+
 static bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state,
 				   const struct intel_plane_state *plane_state)
 {
@@ -1039,10 +1060,10 @@  static void vlv_write_wm_values(struct drm_i915_private *dev_priv,
 
 static void g4x_setup_wm_latency(struct drm_i915_private *dev_priv)
 {
-	/* all latencies in usec */
-	dev_priv->wm.pri_latency[G4X_WM_LEVEL_NORMAL] = 5;
-	dev_priv->wm.pri_latency[G4X_WM_LEVEL_SR] = 12;
-	dev_priv->wm.pri_latency[G4X_WM_LEVEL_HPLL] = 35;
+	/* all latencies in .1 usec */
+	dev_priv->wm.pri_latency[G4X_WM_LEVEL_NORMAL] = 50;
+	dev_priv->wm.pri_latency[G4X_WM_LEVEL_SR] = 120;
+	dev_priv->wm.pri_latency[G4X_WM_LEVEL_HPLL] = 350;
 
 	dev_priv->wm.max_level = G4X_WM_LEVEL_HPLL;
 }
@@ -1097,7 +1118,7 @@  static uint16_t g4x_compute_wm(const struct intel_crtc_state *crtc_state,
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	const struct drm_display_mode *adjusted_mode =
 		&crtc_state->base.adjusted_mode;
-	unsigned int latency = dev_priv->wm.pri_latency[level] * 10;
+	int latency = intel_plane_wm_latency(plane, level);
 	unsigned int clock, htotal, cpp, width, wm;
 
 	if (latency == 0)
@@ -1586,14 +1607,14 @@  static unsigned int vlv_wm_method2(unsigned int pixel_rate,
 
 static void vlv_setup_wm_latency(struct drm_i915_private *dev_priv)
 {
-	/* all latencies in usec */
-	dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM2] = 3;
+	/* all latencies in .1 usec */
+	dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM2] = 30;
 
 	dev_priv->wm.max_level = VLV_WM_LEVEL_PM2;
 
 	if (IS_CHERRYVIEW(dev_priv)) {
-		dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM5] = 12;
-		dev_priv->wm.pri_latency[VLV_WM_LEVEL_DDR_DVFS] = 33;
+		dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM5] = 120;
+		dev_priv->wm.pri_latency[VLV_WM_LEVEL_DDR_DVFS] = 330;
 
 		dev_priv->wm.max_level = VLV_WM_LEVEL_DDR_DVFS;
 	}
@@ -1604,12 +1625,12 @@  static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
 				     int level)
 {
 	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	const struct drm_display_mode *adjusted_mode =
 		&crtc_state->base.adjusted_mode;
+	int latency = intel_plane_wm_latency(plane, level);
 	unsigned int clock, htotal, cpp, width, wm;
 
-	if (dev_priv->wm.pri_latency[level] == 0)
+	if (latency == 0)
 		return USHRT_MAX;
 
 	if (!intel_wm_plane_visible(crtc_state, plane_state))
@@ -1629,8 +1650,7 @@  static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
 		 */
 		wm = 63;
 	} else {
-		wm = vlv_wm_method2(clock, htotal, width, cpp,
-				    dev_priv->wm.pri_latency[level] * 10);
+		wm = vlv_wm_method2(clock, htotal, width, cpp, latency);
 	}
 
 	return min_t(unsigned int, wm, USHRT_MAX);
@@ -2481,15 +2501,12 @@  struct ilk_wm_maximums {
 	uint16_t fbc;
 };
 
-/*
- * For both WM_PIPE and WM_LP.
- * mem_value must be in 0.1us units.
- */
 static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
 				   const struct intel_plane_state *pstate,
-				   uint32_t mem_value,
-				   bool is_lp)
+				   int level)
 {
+	struct intel_plane *plane = to_intel_plane(pstate->base.plane);
+	int latency = intel_plane_wm_latency(plane, level);
 	uint32_t method1, method2;
 	int cpp;
 
@@ -2498,27 +2515,25 @@  static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
 
 	cpp = pstate->base.fb->format->cpp[0];
 
-	method1 = ilk_wm_method1(cstate->pixel_rate, cpp, mem_value);
+	method1 = ilk_wm_method1(cstate->pixel_rate, cpp, latency);
 
-	if (!is_lp)
+	if (level == 0)
 		return method1;
 
 	method2 = ilk_wm_method2(cstate->pixel_rate,
 				 cstate->base.adjusted_mode.crtc_htotal,
 				 drm_rect_width(&pstate->base.dst),
-				 cpp, mem_value);
+				 cpp, latency);
 
 	return min(method1, method2);
 }
 
-/*
- * For both WM_PIPE and WM_LP.
- * mem_value must be in 0.1us units.
- */
 static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
 				   const struct intel_plane_state *pstate,
-				   uint32_t mem_value)
+				   int level)
 {
+	struct intel_plane *plane = to_intel_plane(pstate->base.plane);
+	int latency = intel_plane_wm_latency(plane, level);
 	uint32_t method1, method2;
 	int cpp;
 
@@ -2527,22 +2542,20 @@  static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
 
 	cpp = pstate->base.fb->format->cpp[0];
 
-	method1 = ilk_wm_method1(cstate->pixel_rate, cpp, mem_value);
+	method1 = ilk_wm_method1(cstate->pixel_rate, cpp, latency);
 	method2 = ilk_wm_method2(cstate->pixel_rate,
 				 cstate->base.adjusted_mode.crtc_htotal,
 				 drm_rect_width(&pstate->base.dst),
-				 cpp, mem_value);
+				 cpp, latency);
 	return min(method1, method2);
 }
 
-/*
- * For both WM_PIPE and WM_LP.
- * mem_value must be in 0.1us units.
- */
 static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
 				   const struct intel_plane_state *pstate,
-				   uint32_t mem_value)
+				   int level)
 {
+	struct intel_plane *plane = to_intel_plane(pstate->base.plane);
+	int latency = intel_plane_wm_latency(plane, level);
 	int cpp;
 
 	if (!intel_wm_plane_visible(cstate, pstate))
@@ -2552,7 +2565,7 @@  static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
 
 	return ilk_wm_method2(cstate->pixel_rate,
 			      cstate->base.adjusted_mode.crtc_htotal,
-			      pstate->base.crtc_w, cpp, mem_value);
+			      pstate->base.crtc_w, cpp, latency);
 }
 
 /* Only for WM_LP. */
@@ -2743,28 +2756,16 @@  static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
 				 const struct intel_plane_state *curstate,
 				 struct intel_wm_level *result)
 {
-	uint16_t pri_latency = dev_priv->wm.pri_latency[level];
-	uint16_t spr_latency = dev_priv->wm.spr_latency[level];
-	uint16_t cur_latency = dev_priv->wm.cur_latency[level];
-
-	/* WM1+ latency values stored in 0.5us units */
-	if (level > 0) {
-		pri_latency *= 5;
-		spr_latency *= 5;
-		cur_latency *= 5;
-	}
-
 	if (pristate) {
-		result->pri_val = ilk_compute_pri_wm(cstate, pristate,
-						     pri_latency, level);
+		result->pri_val = ilk_compute_pri_wm(cstate, pristate, level);
 		result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
 	}
 
 	if (sprstate)
-		result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
+		result->spr_val = ilk_compute_spr_wm(cstate, sprstate, level);
 
 	if (curstate)
-		result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
+		result->cur_val = ilk_compute_cur_wm(cstate, curstate, level);
 
 	result->enable = true;
 }
@@ -2930,6 +2931,16 @@  static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv,
 		wm[0] = 13;
 }
 
+static void ilk_fixup_wm_latency_units(struct drm_i915_private *dev_priv,
+				       u16 wm[5])
+{
+	int level, num_levels = ilk_wm_max_level(dev_priv) + 1;
+
+	/* convert .5 usec to .1 usec units */
+	for (level = 1; level < num_levels; level++)
+		wm[level] *= 5;
+}
+
 int ilk_wm_max_level(const struct drm_i915_private *dev_priv)
 {
 	/* how many WM levels are we expecting */
@@ -2958,15 +2969,6 @@  static void intel_print_wm_latency(struct drm_i915_private *dev_priv,
 			continue;
 		}
 
-		/*
-		 * - latencies are in us on gen9.
-		 * - before then, WM1+ latency values are in 0.5us units
-		 */
-		if (INTEL_GEN(dev_priv) >= 9)
-			latency *= 10;
-		else if (level > 0)
-			latency *= 5;
-
 		DRM_DEBUG_KMS("%s WM%d latency %u (%u.%u usec)\n",
 			      name, level, wm[level],
 			      latency / 10, latency % 10);
@@ -2982,8 +2984,12 @@  static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
 		return false;
 
 	wm[0] = max(wm[0], min);
+
+	/* WM1+ latencies must be multiples of .5 usec */
+	min = roundup(min, 5);
+
 	for (level = 1; level <= max_level; level++)
-		wm[level] = max_t(uint16_t, wm[level], DIV_ROUND_UP(min, 5));
+		wm[level] = max(wm[level], min);
 
 	return true;
 }
@@ -3013,6 +3019,8 @@  static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
 {
 	intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency);
 
+	ilk_fixup_wm_latency_units(dev_priv, dev_priv->wm.pri_latency);
+
 	memcpy(dev_priv->wm.spr_latency, dev_priv->wm.pri_latency,
 	       sizeof(dev_priv->wm.pri_latency));
 	memcpy(dev_priv->wm.cur_latency, dev_priv->wm.pri_latency,
@@ -3029,9 +3037,22 @@  static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
 		snb_wm_latency_quirk(dev_priv);
 }
 
+static void skl_fixup_wm_latency_units(struct drm_i915_private *dev_priv,
+				       u16 wm[8])
+{
+	int level, num_levels = ilk_wm_max_level(dev_priv) + 1;
+
+	/* convert usec to .1 usec units */
+	for (level = 0; level < num_levels; level++)
+		wm[level] *= 10;
+}
+
 static void skl_setup_wm_latency(struct drm_i915_private *dev_priv)
 {
 	intel_read_wm_latency(dev_priv, dev_priv->wm.skl_latency);
+
+	skl_fixup_wm_latency_units(dev_priv, dev_priv->wm.skl_latency);
+
 	intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency);
 }
 
@@ -3303,7 +3324,8 @@  static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level)
 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		return 2 * level;
 	else
-		return dev_priv->wm.pri_latency[level];
+		/* specified in .5 usec units */
+		return dev_priv->wm.pri_latency[level] / 5;
 }
 
 static void ilk_compute_wm_results(struct drm_device *dev,
@@ -3763,7 +3785,7 @@  bool intel_can_enable_sagv(struct drm_atomic_state *state)
 		     !wm->wm[level].plane_en; --level)
 		     { }
 
-		latency = dev_priv->wm.skl_latency[level];
+		latency = intel_plane_wm_latency(plane, level);
 
 		if (skl_needs_memory_bw_wa(intel_state) &&
 		    plane->base.state->fb->modifier ==
@@ -4636,7 +4658,8 @@  static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
 				struct skl_wm_level *result /* out */)
 {
 	const struct drm_plane_state *pstate = &intel_pstate->base;
-	uint32_t latency = dev_priv->wm.skl_latency[level];
+	uint32_t latency = intel_plane_wm_latency(to_intel_plane(pstate->plane),
+						  level);
 	uint_fixed_16_16_t method1, method2;
 	uint_fixed_16_16_t selected_result;
 	uint32_t res_blocks, res_lines;