diff mbox

[01/28] drm/i915/skl: Read the Memory Latency Values for WM computation

Message ID 1415120825-4375-2-git-send-email-damien.lespiau@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lespiau, Damien Nov. 4, 2014, 5:06 p.m. UTC
From: Pradeep Bhat <pradeep.bhat@intel.com>

This patch reads the memory latency values for all the 8 levels for
SKL. These values are needed for the Watermark computation.

v2: Incorporated the review comments from Damien on register
    indentation.

v3: Updated the code to use the sandybridge_pcode_read for reading
    memory latencies for GEN9.

v4: Don't put gen 9 in the middle of an ordered list of ifs
    (Damien)

v5: take the rps.hw_lock around sandybridge_pcode_read() (Damien)

v6: Use gen >= 9 in the pcode_read() function for data1.
    Move the defines near the gen6 ones and prefix them with PCODE.
    Remove unused timeout define (the pcode_read() code has a larger
    timeout already).

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h |  6 ++++
 drivers/gpu/drm/i915/i915_reg.h |  7 ++++
 drivers/gpu/drm/i915/intel_pm.c | 76 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 83 insertions(+), 6 deletions(-)

Comments

Daniel Vetter Nov. 5, 2014, 10:25 a.m. UTC | #1
On Tue, Nov 04, 2014 at 05:06:38PM +0000, Damien Lespiau wrote:
> From: Pradeep Bhat <pradeep.bhat@intel.com>
> 
> This patch reads the memory latency values for all the 8 levels for
> SKL. These values are needed for the Watermark computation.
> 
> v2: Incorporated the review comments from Damien on register
>     indentation.
> 
> v3: Updated the code to use the sandybridge_pcode_read for reading
>     memory latencies for GEN9.
> 
> v4: Don't put gen 9 in the middle of an ordered list of ifs
>     (Damien)
> 
> v5: take the rps.hw_lock around sandybridge_pcode_read() (Damien)
> 
> v6: Use gen >= 9 in the pcode_read() function for data1.
>     Move the defines near the gen6 ones and prefix them with PCODE.
>     Remove unused timeout define (the pcode_read() code has a larger
>     timeout already).
> 
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h |  6 ++++
>  drivers/gpu/drm/i915/i915_reg.h |  7 ++++
>  drivers/gpu/drm/i915/intel_pm.c | 76 +++++++++++++++++++++++++++++++++++++----
>  3 files changed, 83 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 54691bc..05fcbe5 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1678,6 +1678,12 @@ struct drm_i915_private {
>  		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 */
>  		struct ilk_wm_values hw;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index f32c624..3f469c8 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -5957,6 +5957,13 @@ enum punit_power_well {
>  #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8
>  #define   GEN6_PCODE_FREQ_RING_RATIO_SHIFT	16
>  
> +#define GEN9_PCODE_DATA1			0x13812C
> +#define   GEN9_PCODE_READ_MEM_LATENCY		0x6
> +#define   GEN9_MEM_LATENCY_LEVEL_MASK		0xFF
> +#define   GEN9_MEM_LATENCY_LEVEL_1_5_SHIFT	8
> +#define   GEN9_MEM_LATENCY_LEVEL_2_6_SHIFT	16
> +#define   GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT	24
> +
>  #define GEN6_GT_CORE_STATUS		0x138060
>  #define   GEN6_CORE_CPD_STATE_MASK	(7<<4)
>  #define   GEN6_RCn_MASK			7
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 7a69eba..761c884 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2271,11 +2271,56 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
>  	       PIPE_WM_LINETIME_TIME(linetime);
>  }
>  
> -static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
> +static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8])

Imo we should split this into an ilk_read_wm_latency and a
skl_read_wm_latency function. It's big and all the callers seem to only
care about one or the other. Care for a follow-up patch?
-Daniel
Daniel Vetter Nov. 5, 2014, 10:29 a.m. UTC | #2
On Wed, Nov 05, 2014 at 11:25:51AM +0100, Daniel Vetter wrote:
> On Tue, Nov 04, 2014 at 05:06:38PM +0000, Damien Lespiau wrote:
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 7a69eba..761c884 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2271,11 +2271,56 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
> >  	       PIPE_WM_LINETIME_TIME(linetime);
> >  }
> >  
> > -static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
> > +static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8])
> 
> Imo we should split this into an ilk_read_wm_latency and a
> skl_read_wm_latency function. It's big and all the callers seem to only
> care about one or the other. Care for a follow-up patch?

Actually there seem to be a few more functions which are platform
specific. E.g. the intel_fixup* functions - tbh we might as well just
inline them.
-Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 54691bc..05fcbe5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1678,6 +1678,12 @@  struct drm_i915_private {
 		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 */
 		struct ilk_wm_values hw;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f32c624..3f469c8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5957,6 +5957,13 @@  enum punit_power_well {
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8
 #define   GEN6_PCODE_FREQ_RING_RATIO_SHIFT	16
 
+#define GEN9_PCODE_DATA1			0x13812C
+#define   GEN9_PCODE_READ_MEM_LATENCY		0x6
+#define   GEN9_MEM_LATENCY_LEVEL_MASK		0xFF
+#define   GEN9_MEM_LATENCY_LEVEL_1_5_SHIFT	8
+#define   GEN9_MEM_LATENCY_LEVEL_2_6_SHIFT	16
+#define   GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT	24
+
 #define GEN6_GT_CORE_STATUS		0x138060
 #define   GEN6_CORE_CPD_STATE_MASK	(7<<4)
 #define   GEN6_RCn_MASK			7
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7a69eba..761c884 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2271,11 +2271,56 @@  hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
 	       PIPE_WM_LINETIME_TIME(linetime);
 }
 
-static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
+static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8])
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+	if (IS_GEN9(dev)) {
+		uint32_t val;
+		int ret;
+
+		/* read the first set of memory latencies[0:3] */
+		val = 0; /* data0 to be programmed to 0 for first set */
+		mutex_lock(&dev_priv->rps.hw_lock);
+		ret = sandybridge_pcode_read(dev_priv,
+					     GEN9_PCODE_READ_MEM_LATENCY,
+					     &val);
+		mutex_unlock(&dev_priv->rps.hw_lock);
+
+		if (ret) {
+			DRM_ERROR("SKL Mailbox read error = %d\n", ret);
+			return;
+		}
+
+		wm[0] = val & GEN9_MEM_LATENCY_LEVEL_MASK;
+		wm[1] = (val >> GEN9_MEM_LATENCY_LEVEL_1_5_SHIFT) &
+				GEN9_MEM_LATENCY_LEVEL_MASK;
+		wm[2] = (val >> GEN9_MEM_LATENCY_LEVEL_2_6_SHIFT) &
+				GEN9_MEM_LATENCY_LEVEL_MASK;
+		wm[3] = (val >> GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT) &
+				GEN9_MEM_LATENCY_LEVEL_MASK;
+
+		/* read the second set of memory latencies[4:7] */
+		val = 1; /* data0 to be programmed to 1 for second set */
+		mutex_lock(&dev_priv->rps.hw_lock);
+		ret = sandybridge_pcode_read(dev_priv,
+					     GEN9_PCODE_READ_MEM_LATENCY,
+					     &val);
+		mutex_unlock(&dev_priv->rps.hw_lock);
+		if (ret) {
+			DRM_ERROR("SKL Mailbox read error = %d\n", ret);
+			return;
+		}
+
+		wm[4] = val & GEN9_MEM_LATENCY_LEVEL_MASK;
+		wm[5] = (val >> GEN9_MEM_LATENCY_LEVEL_1_5_SHIFT) &
+				GEN9_MEM_LATENCY_LEVEL_MASK;
+		wm[6] = (val >> GEN9_MEM_LATENCY_LEVEL_2_6_SHIFT) &
+				GEN9_MEM_LATENCY_LEVEL_MASK;
+		wm[7] = (val >> GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT) &
+				GEN9_MEM_LATENCY_LEVEL_MASK;
+
+	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		uint64_t sskpd = I915_READ64(MCH_SSKPD);
 
 		wm[0] = (sskpd >> 56) & 0xFF;
@@ -2323,7 +2368,9 @@  static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
 int ilk_wm_max_level(const struct drm_device *dev)
 {
 	/* how many WM levels are we expecting */
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (IS_GEN9(dev))
+		return 7;
+	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		return 4;
 	else if (INTEL_INFO(dev)->gen >= 6)
 		return 3;
@@ -2333,7 +2380,7 @@  int ilk_wm_max_level(const struct drm_device *dev)
 
 static void intel_print_wm_latency(struct drm_device *dev,
 				   const char *name,
-				   const uint16_t wm[5])
+				   const uint16_t wm[8])
 {
 	int level, max_level = ilk_wm_max_level(dev);
 
@@ -2346,8 +2393,13 @@  static void intel_print_wm_latency(struct drm_device *dev,
 			continue;
 		}
 
-		/* WM1+ latency values in 0.5us units */
-		if (level > 0)
+		/*
+		 * - latencies are in us on gen9.
+		 * - before then, WM1+ latency values are in 0.5us units
+		 */
+		if (IS_GEN9(dev))
+			latency *= 10;
+		else if (level > 0)
 			latency *= 5;
 
 		DRM_DEBUG_KMS("%s WM%d latency %u (%u.%u usec)\n",
@@ -2415,6 +2467,14 @@  static void ilk_setup_wm_latency(struct drm_device *dev)
 		snb_wm_latency_quirk(dev);
 }
 
+static void skl_setup_wm_latency(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	intel_read_wm_latency(dev, dev_priv->wm.skl_latency);
+	intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
+}
+
 static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
 				      struct ilk_pipe_wm_parameters *p)
 {
@@ -6127,6 +6187,8 @@  void intel_init_pm(struct drm_device *dev)
 
 	/* For FIFO watermark updates */
 	if (IS_GEN9(dev)) {
+		skl_setup_wm_latency(dev);
+
 		dev_priv->display.init_clock_gating = gen9_init_clock_gating;
 	} else if (HAS_PCH_SPLIT(dev)) {
 		ilk_setup_wm_latency(dev);
@@ -6219,6 +6281,8 @@  int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val)
 	}
 
 	I915_WRITE(GEN6_PCODE_DATA, *val);
+	if (INTEL_INFO(dev_priv)->gen >= 9)
+		I915_WRITE(GEN9_PCODE_DATA1, 0);
 	I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
 
 	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,