All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/35] drm/i915: ILK+ watermark rewrite
@ 2013-07-05  8:57 ville.syrjala
  2013-07-05  8:57 ` [PATCH 01/35] drm/i915: Add scaled paramater to update_sprite_watermarks() ville.syrjala
                   ` (35 more replies)
  0 siblings, 36 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

Here's my big ILK+ watermark rewrite. The main idea of the series is to
write the watermark registers at vblank to make the changes (almost) in
sync with the plane changes that caused the change in watermarks.

I sent a massive RFC patch a while back, and this is now the somewhat
split up version.

It's still not quite where we need to get wrt. pre-computing and
properly checking the LP0 watermarks, but at least it gets us a bit
closer to that goal.

There's quite a bit of refactoring, small fixes, renaming, and what have you
at the beginning of the series, so a lot of it should be mergeable w/o too much
risk. Many of the patches only touch codepaths that are used by HSW currently,
but by the end of the series, ILK,SNB,IVB,HSW are all using the exact same
code.

So far I've run this somewhat succesfully on ILK and IVB.

----------------------------------------------------------------
Ville Syrjälä (35):
      drm/i915: Add scaled paramater to update_sprite_watermarks()
      drm/i915: Pass the actual sprite width to watermarks functions
      drm/i915: Calculate the sprite WM based on the source width instead of the destination width
      drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate
      drm/i915: Rename most wm compute functions to ilk_ prefix
      drm/i915: Pass the watermark level to primary WM compute functions
      drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm
      drm/i915: Change the watermark latency type to uint16_t
      drm/i915: Split out reading of HSW watermark latency values
      drm/i915: Don't multiply the watermark latency values too early
      drm/i915: Add SNB/IVB support to intel_read_wm_latency
      drm/i915: Add ILK support to intel_read_wm_latency
      drm/i915: Store the watermark latency values in dev_priv
      drm/i915: Use the stored cursor and plane latencies properly
      drm/i915: Print the watermark latencies during init
      drm/i915: Disable specific watermark levels when latency is zero
      drm/i915: Pull watermark level validity check out
      drm/i915: Split watermark level computation from the code
      drm/i915: Kill fbc_enable from hsw_lp_wm_results
      drm/i915: Rename hsw_data_buf_partitioning to intel_ddb_partitioning
      drm/i915: Rename hsw_lp_wm_result to intel_wm_level
      drm/i915: Calculate max watermark levels for ILK+
      drm/i915; Pull some watermarks state into a separate structure
      drm/i915: Split plane watermark parameters into a separate struct
      drm/i915: Pass crtc to our update/disable_plane hooks
      drm/i915: Don't try to disable plane if it's already disabled
      drm/i915: Pass plane and crtc to intel_update_sprite_watermarks
      drm/i915: Always call intel_update_sprite_watermarks() when disabling a plane
      drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset
      drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
      drm/i915: Move HSW linetime watermark handling to modeset code
      hack: Add debug prints to watermark compute funcs
      hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB
      hack: Make fifo underruns DRM_ERROR
      hack: Print watermark programming duration

 drivers/gpu/drm/i915/i915_drv.h      |   41 +-
 drivers/gpu/drm/i915/i915_irq.c      |   32 +-
 drivers/gpu/drm/i915/i915_reg.h      |    2 +
 drivers/gpu/drm/i915/intel_display.c |   45 +-
 drivers/gpu/drm/i915/intel_drv.h     |   47 +-
 drivers/gpu/drm/i915/intel_pm.c      | 1796 +++++++++++++++++-----------------
 drivers/gpu/drm/i915/intel_sprite.c  |   54 +-
 7 files changed, 1039 insertions(+), 978 deletions(-)
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 74+ messages in thread

* [PATCH 01/35] drm/i915: Add scaled paramater to update_sprite_watermarks()
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 18:26   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 02/35] drm/i915: Pass the actual sprite width to watermarks functions ville.syrjala
                   ` (34 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Fro calculating watermarks we want to know whether sprites are
scaled. Pass that information to update_sprite_watermarks() so that
eventually we may do some watermark pre-computing.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h     |  2 +-
 drivers/gpu/drm/i915/intel_drv.h    |  7 ++++---
 drivers/gpu/drm/i915/intel_pm.c     | 13 +++++++------
 drivers/gpu/drm/i915/intel_sprite.c | 11 +++++++----
 4 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fd0f589..99eb980 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -361,7 +361,7 @@ struct drm_i915_display_funcs {
 	void (*update_wm)(struct drm_device *dev);
 	void (*update_sprite_wm)(struct drm_device *dev, int pipe,
 				 uint32_t sprite_width, int pixel_size,
-				 bool enable);
+				 bool enable, bool scaled);
 	void (*modeset_global_resources)(struct drm_device *dev);
 	/* Returns the active state of the crtc, and if the crtc is active,
 	 * fills out the pipe-config with the hw state. */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5dfc1a0..3371ecc 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -353,7 +353,8 @@ struct intel_plane {
 	 * for the watermark calculations. Currently only Haswell uses this.
 	 */
 	struct {
-		bool enable;
+		bool enabled;
+		bool scaled;
 		uint8_t bytes_per_pixel;
 		uint32_t horiz_pixels;
 	} wm;
@@ -772,8 +773,8 @@ extern void intel_ddi_init(struct drm_device *dev, enum port port);
 /* For use by IVB LP watermark workaround in intel_sprite.c */
 extern void intel_update_watermarks(struct drm_device *dev);
 extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
-					   uint32_t sprite_width,
-					   int pixel_size, bool enable);
+					   uint32_t sprite_width, int pixel_size,
+					   bool enabled, bool scaled);
 
 extern unsigned long intel_gen4_compute_page_offset(int *x, int *y,
 						    unsigned int tiling_mode,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7cfd3b7..beca186 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2388,7 +2388,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 		pipe = intel_plane->pipe;
 		p = &params[pipe];
 
-		p->sprite_enabled = intel_plane->wm.enable;
+		p->sprite_enabled = intel_plane->wm.enabled;
 		p->spr_bytes_per_pixel = intel_plane->wm.bytes_per_pixel;
 		p->spr_horiz_pixels = intel_plane->wm.horiz_pixels;
 
@@ -2616,7 +2616,7 @@ static void haswell_update_wm(struct drm_device *dev)
 
 static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
 				     uint32_t sprite_width, int pixel_size,
-				     bool enable)
+				     bool enabled, bool scaled)
 {
 	struct drm_plane *plane;
 
@@ -2624,7 +2624,8 @@ static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
 		struct intel_plane *intel_plane = to_intel_plane(plane);
 
 		if (intel_plane->pipe == pipe) {
-			intel_plane->wm.enable = enable;
+			intel_plane->wm.enabled = enabled;
+			intel_plane->wm.scaled = scaled;
 			intel_plane->wm.horiz_pixels = sprite_width + 1;
 			intel_plane->wm.bytes_per_pixel = pixel_size;
 			break;
@@ -2712,7 +2713,7 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
 
 static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
 					 uint32_t sprite_width, int pixel_size,
-					 bool enable)
+					 bool enable, bool scaled)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
@@ -2835,13 +2836,13 @@ void intel_update_watermarks(struct drm_device *dev)
 
 void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
 				    uint32_t sprite_width, int pixel_size,
-				    bool enable)
+				    bool enable, bool scaled)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (dev_priv->display.update_sprite_wm)
 		dev_priv->display.update_sprite_wm(dev, pipe, sprite_width,
-						   pixel_size, enable);
+						   pixel_size, enable, scaled);
 }
 
 static struct drm_i915_gem_object *
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 1fa5612..5a1f3fd 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -114,7 +114,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
+	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
+				       src_w != crtc_w || src_h != crtc_h);
 
 	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
 	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
@@ -268,7 +269,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
+	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
+				       src_w != crtc_w || src_h != crtc_h);
 
 	/*
 	 * IVB workaround: must disable low power watermarks for at least
@@ -335,7 +337,7 @@ ivb_disable_plane(struct drm_plane *plane)
 
 	dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
 
-	intel_update_sprite_watermarks(dev, pipe, 0, 0, false);
+	intel_update_sprite_watermarks(dev, pipe, 0, 0, false, false);
 
 	/* potentially re-enable LP watermarks */
 	if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
@@ -455,7 +457,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
+	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
+				       src_w != crtc_w || src_h != crtc_h);
 
 	dvsscale = 0;
 	if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 02/35] drm/i915: Pass the actual sprite width to watermarks functions
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
  2013-07-05  8:57 ` [PATCH 01/35] drm/i915: Add scaled paramater to update_sprite_watermarks() ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 18:32   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 03/35] drm/i915: Calculate the sprite WM based on the source width instead of the destination width ville.syrjala
                   ` (33 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Don't subtract one from the sprite width before watermark calculations.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c     |  2 +-
 drivers/gpu/drm/i915/intel_sprite.c | 18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index beca186..db548a1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2626,7 +2626,7 @@ static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
 		if (intel_plane->pipe == pipe) {
 			intel_plane->wm.enabled = enabled;
 			intel_plane->wm.scaled = scaled;
-			intel_plane->wm.horiz_pixels = sprite_width + 1;
+			intel_plane->wm.horiz_pixels = sprite_width;
 			intel_plane->wm.bytes_per_pixel = pixel_size;
 			break;
 		}
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 5a1f3fd..d7fca56 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -108,15 +108,15 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
 
 	sprctl |= SP_ENABLE;
 
+	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
+				       src_w != crtc_w || src_h != crtc_h);
+
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
-				       src_w != crtc_w || src_h != crtc_h);
-
 	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
 	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
 
@@ -263,15 +263,15 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	if (IS_HASWELL(dev))
 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
 
+	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
+				       src_w != crtc_w || src_h != crtc_h);
+
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
-				       src_w != crtc_w || src_h != crtc_h);
-
 	/*
 	 * IVB workaround: must disable low power watermarks for at least
 	 * one frame before enabling scaling.  LP watermarks can be re-enabled
@@ -451,15 +451,15 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
 	dvscntr |= DVS_ENABLE;
 
+	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
+				       src_w != crtc_w || src_h != crtc_h);
+
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
-				       src_w != crtc_w || src_h != crtc_h);
-
 	dvsscale = 0;
 	if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 03/35] drm/i915: Calculate the sprite WM based on the source width instead of the destination width
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
  2013-07-05  8:57 ` [PATCH 01/35] drm/i915: Add scaled paramater to update_sprite_watermarks() ville.syrjala
  2013-07-05  8:57 ` [PATCH 02/35] drm/i915: Pass the actual sprite width to watermarks functions ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 19:01   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 04/35] drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate ville.syrjala
                   ` (32 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Using the destination width in the sprite WM calculations isn't correct.
We should be using the source width.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_sprite.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index d7fca56..7c6cce7 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -108,7 +108,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
 
 	sprctl |= SP_ENABLE;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
+	intel_update_sprite_watermarks(dev, pipe, src_w, pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
 	/* Sizes are 0 based */
@@ -263,7 +263,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	if (IS_HASWELL(dev))
 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
+	intel_update_sprite_watermarks(dev, pipe, src_w, pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
 	/* Sizes are 0 based */
@@ -451,7 +451,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
 	dvscntr |= DVS_ENABLE;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
+	intel_update_sprite_watermarks(dev, pipe, src_w, pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
 	/* Sizes are 0 based */
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 04/35] drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (2 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 03/35] drm/i915: Calculate the sprite WM based on the source width instead of the destination width ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 19:20   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 05/35] drm/i915: Rename most wm compute functions to ilk_ prefix ville.syrjala
                   ` (31 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

hsw_wm_get_pixel_rate() isn't specific to HSW. In fact it should be made
to handle all gens, but for now it depends on the PCH panel fitter
state, so give it an ilk_ prefix.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index db548a1..b8fde13 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2080,8 +2080,8 @@ static void ivybridge_update_wm(struct drm_device *dev)
 		   cursor_wm);
 }
 
-static uint32_t hsw_wm_get_pixel_rate(struct drm_device *dev,
-				      struct drm_crtc *crtc)
+static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
+				    struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	uint32_t pixel_rate, pfit_size;
@@ -2373,7 +2373,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 		pipes_active++;
 
 		p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
-		p->pixel_rate = hsw_wm_get_pixel_rate(dev, crtc);
+		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
 		p->pri_bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
 		p->cur_bytes_per_pixel = 4;
 		p->pri_horiz_pixels =
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 05/35] drm/i915: Rename most wm compute functions to ilk_ prefix
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (3 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 04/35] drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 19:37   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 06/35] drm/i915: Pass the watermark level to primary WM compute functions ville.syrjala
                   ` (30 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

These functions are appropriate for everything since ILK.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index b8fde13..6b820c4 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2111,7 +2111,7 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
 	return pixel_rate;
 }
 
-static uint32_t hsw_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
+static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
 			       uint32_t latency)
 {
 	uint64_t ret;
@@ -2122,7 +2122,7 @@ static uint32_t hsw_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
 	return ret;
 }
 
-static uint32_t hsw_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
+static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
 			       uint32_t horiz_pixels, uint8_t bytes_per_pixel,
 			       uint32_t latency)
 {
@@ -2134,7 +2134,7 @@ static uint32_t hsw_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
 	return ret;
 }
 
-static uint32_t hsw_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
+static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
 			   uint8_t bytes_per_pixel)
 {
 	return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
@@ -2183,7 +2183,7 @@ enum hsw_data_buf_partitioning {
 };
 
 /* For both WM_PIPE and WM_LP. */
-static uint32_t hsw_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value,
 				   bool is_lp)
 {
@@ -2193,14 +2193,14 @@ static uint32_t hsw_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 	if (!params->active)
 		return 0;
 
-	method1 = hsw_wm_method1(params->pixel_rate,
+	method1 = ilk_wm_method1(params->pixel_rate,
 				 params->pri_bytes_per_pixel,
 				 mem_value);
 
 	if (!is_lp)
 		return method1;
 
-	method2 = hsw_wm_method2(params->pixel_rate,
+	method2 = ilk_wm_method2(params->pixel_rate,
 				 params->pipe_htotal,
 				 params->pri_horiz_pixels,
 				 params->pri_bytes_per_pixel,
@@ -2210,7 +2210,7 @@ static uint32_t hsw_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 }
 
 /* For both WM_PIPE and WM_LP. */
-static uint32_t hsw_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value)
 {
 	uint32_t method1, method2;
@@ -2218,10 +2218,10 @@ static uint32_t hsw_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
 	if (!params->active || !params->sprite_enabled)
 		return 0;
 
-	method1 = hsw_wm_method1(params->pixel_rate,
+	method1 = ilk_wm_method1(params->pixel_rate,
 				 params->spr_bytes_per_pixel,
 				 mem_value);
-	method2 = hsw_wm_method2(params->pixel_rate,
+	method2 = ilk_wm_method2(params->pixel_rate,
 				 params->pipe_htotal,
 				 params->spr_horiz_pixels,
 				 params->spr_bytes_per_pixel,
@@ -2230,13 +2230,13 @@ static uint32_t hsw_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
 }
 
 /* For both WM_PIPE and WM_LP. */
-static uint32_t hsw_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value)
 {
 	if (!params->active)
 		return 0;
 
-	return hsw_wm_method2(params->pixel_rate,
+	return ilk_wm_method2(params->pixel_rate,
 			      params->pipe_htotal,
 			      params->cur_horiz_pixels,
 			      params->cur_bytes_per_pixel,
@@ -2244,14 +2244,14 @@ static uint32_t hsw_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
 }
 
 /* Only for WM_LP. */
-static uint32_t hsw_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t pri_val,
 				   uint32_t mem_value)
 {
 	if (!params->active)
 		return 0;
 
-	return hsw_wm_fbc(pri_val,
+	return ilk_wm_fbc(pri_val,
 			  params->pri_horiz_pixels,
 			  params->pri_bytes_per_pixel);
 }
@@ -2266,10 +2266,10 @@ static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
 	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) {
 		struct hsw_pipe_wm_parameters *p = &params[pipe];
 
-		pri_val[pipe] = hsw_compute_pri_wm(p, mem_value, true);
-		spr_val[pipe] = hsw_compute_spr_wm(p, mem_value);
-		cur_val[pipe] = hsw_compute_cur_wm(p, mem_value);
-		fbc_val[pipe] = hsw_compute_fbc_wm(p, pri_val[pipe], mem_value);
+		pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, true);
+		spr_val[pipe] = ilk_compute_spr_wm(p, mem_value);
+		cur_val[pipe] = ilk_compute_cur_wm(p, mem_value);
+		fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe], mem_value);
 	}
 
 	result->pri_val = max3(pri_val[0], pri_val[1], pri_val[2]);
@@ -2296,9 +2296,9 @@ static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
 {
 	uint32_t pri_val, cur_val, spr_val;
 
-	pri_val = hsw_compute_pri_wm(params, mem_value, false);
-	spr_val = hsw_compute_spr_wm(params, mem_value);
-	cur_val = hsw_compute_cur_wm(params, mem_value);
+	pri_val = ilk_compute_pri_wm(params, mem_value, false);
+	spr_val = ilk_compute_spr_wm(params, mem_value);
+	cur_val = ilk_compute_cur_wm(params, mem_value);
 
 	WARN(pri_val > 127,
 	     "Primary WM error, mode not supported for pipe %c\n",
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 06/35] drm/i915: Pass the watermark level to primary WM compute functions
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (4 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 05/35] drm/i915: Rename most wm compute functions to ilk_ prefix ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 19:49   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 07/35] drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm ville.syrjala
                   ` (29 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Passing the level insted of "is_lp" seems easier. The end result is the
same though.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6b820c4..f178e26 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2185,7 +2185,7 @@ enum hsw_data_buf_partitioning {
 /* For both WM_PIPE and WM_LP. */
 static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value,
-				   bool is_lp)
+				   int level)
 {
 	uint32_t method1, method2;
 
@@ -2197,7 +2197,7 @@ static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 				 params->pri_bytes_per_pixel,
 				 mem_value);
 
-	if (!is_lp)
+	if (level == 0)
 		return method1;
 
 	method2 = ilk_wm_method2(params->pixel_rate,
@@ -2266,7 +2266,7 @@ static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
 	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) {
 		struct hsw_pipe_wm_parameters *p = &params[pipe];
 
-		pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, true);
+		pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, 1);
 		spr_val[pipe] = ilk_compute_spr_wm(p, mem_value);
 		cur_val[pipe] = ilk_compute_cur_wm(p, mem_value);
 		fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe], mem_value);
@@ -2296,7 +2296,7 @@ static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
 {
 	uint32_t pri_val, cur_val, spr_val;
 
-	pri_val = ilk_compute_pri_wm(params, mem_value, false);
+	pri_val = ilk_compute_pri_wm(params, mem_value, 0);
 	spr_val = ilk_compute_spr_wm(params, mem_value);
 	cur_val = ilk_compute_cur_wm(params, mem_value);
 
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 07/35] drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (5 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 06/35] drm/i915: Pass the watermark level to primary WM compute functions ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 19:54   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 08/35] drm/i915: Change the watermark latency type to uint16_t ville.syrjala
                   ` (28 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The FBC watermark doesn't depend on the latency value, so no point in
passing it in.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f178e26..981416c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2245,8 +2245,7 @@ static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
 
 /* Only for WM_LP. */
 static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
-				   uint32_t pri_val,
-				   uint32_t mem_value)
+				   uint32_t pri_val)
 {
 	if (!params->active)
 		return 0;
@@ -2269,7 +2268,7 @@ static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
 		pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, 1);
 		spr_val[pipe] = ilk_compute_spr_wm(p, mem_value);
 		cur_val[pipe] = ilk_compute_cur_wm(p, mem_value);
-		fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe], mem_value);
+		fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe]);
 	}
 
 	result->pri_val = max3(pri_val[0], pri_val[1], pri_val[2]);
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 08/35] drm/i915: Change the watermark latency type to uint16_t
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (6 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 07/35] drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 20:01   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 09/35] drm/i915: Split out reading of HSW watermark latency values ville.syrjala
                   ` (27 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The latency values fit in uint16_t, so let's save a few bytes.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 981416c..2239cdb 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2338,7 +2338,7 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
 
 static void hsw_compute_wm_parameters(struct drm_device *dev,
 				      struct hsw_pipe_wm_parameters *params,
-				      uint32_t *wm,
+				      uint16_t *wm,
 				      struct hsw_wm_maximums *lp_max_1_2,
 				      struct hsw_wm_maximums *lp_max_5_6)
 {
@@ -2411,7 +2411,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 
 static void hsw_compute_wm_results(struct drm_device *dev,
 				   struct hsw_pipe_wm_parameters *params,
-				   uint32_t *wm,
+				   uint16_t *wm,
 				   struct hsw_wm_maximums *lp_maximums,
 				   struct hsw_wm_values *results)
 {
@@ -2593,7 +2593,7 @@ static void haswell_update_wm(struct drm_device *dev)
 	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
 	struct hsw_pipe_wm_parameters params[3];
 	struct hsw_wm_values results_1_2, results_5_6, *best_results;
-	uint32_t wm[5];
+	uint16_t wm[5];
 	enum hsw_data_buf_partitioning partitioning;
 
 	hsw_compute_wm_parameters(dev, params, wm, &lp_max_1_2, &lp_max_5_6);
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 09/35] drm/i915: Split out reading of HSW watermark latency values
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (7 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 08/35] drm/i915: Change the watermark latency type to uint16_t ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  9:19   ` Chris Wilson
  2013-07-30 20:09   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 10/35] drm/i915: Don't multiply the watermark latency values too early ville.syrjala
                   ` (26 subsequent siblings)
  35 siblings, 2 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move parsing of MCH_SSKPD to a separate function, we'll add other
platforms there later.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 2239cdb..c266e47 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2336,28 +2336,33 @@ 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])
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_HASWELL(dev)) {
+		uint64_t sskpd = I915_READ64(MCH_SSKPD);
+
+		wm[0] = (sskpd >> 56) & 0xFF;
+		if (wm[0] == 0)
+			wm[0] = sskpd & 0xF;
+		wm[1] = ((sskpd >> 4) & 0xFF) * 5;
+		wm[2] = ((sskpd >> 12) & 0xFF) * 5;
+		wm[3] = ((sskpd >> 20) & 0x1FF) * 5;
+		wm[4] = ((sskpd >> 32) & 0x1FF) * 5;
+	}
+}
+
 static void hsw_compute_wm_parameters(struct drm_device *dev,
 				      struct hsw_pipe_wm_parameters *params,
-				      uint16_t *wm,
 				      struct hsw_wm_maximums *lp_max_1_2,
 				      struct hsw_wm_maximums *lp_max_5_6)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
 	struct drm_plane *plane;
-	uint64_t sskpd = I915_READ64(MCH_SSKPD);
 	enum pipe pipe;
 	int pipes_active = 0, sprites_enabled = 0;
 
-	if ((sskpd >> 56) & 0xFF)
-		wm[0] = (sskpd >> 56) & 0xFF;
-	else
-		wm[0] = sskpd & 0xF;
-	wm[1] = ((sskpd >> 4) & 0xFF) * 5;
-	wm[2] = ((sskpd >> 12) & 0xFF) * 5;
-	wm[3] = ((sskpd >> 20) & 0x1FF) * 5;
-	wm[4] = ((sskpd >> 32) & 0x1FF) * 5;
-
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 		struct hsw_pipe_wm_parameters *p;
@@ -2593,10 +2598,11 @@ static void haswell_update_wm(struct drm_device *dev)
 	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
 	struct hsw_pipe_wm_parameters params[3];
 	struct hsw_wm_values results_1_2, results_5_6, *best_results;
-	uint16_t wm[5];
+	uint16_t wm[5] = {};
 	enum hsw_data_buf_partitioning partitioning;
 
-	hsw_compute_wm_parameters(dev, params, wm, &lp_max_1_2, &lp_max_5_6);
+	intel_read_wm_latency(dev, wm);
+	hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
 
 	hsw_compute_wm_results(dev, params, wm, &lp_max_1_2, &results_1_2);
 	if (lp_max_1_2.pri != lp_max_5_6.pri) {
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 10/35] drm/i915: Don't multiply the watermark latency values too early
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (8 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 09/35] drm/i915: Split out reading of HSW watermark latency values ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 20:21   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 11/35] drm/i915: Add SNB/IVB support to intel_read_wm_latency ville.syrjala
                   ` (25 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The LP1+ watermark latency values need to be multiplied by 5 to
make the suitable for watermark calculations. However on pre-HSW
platforms we're going to need the raw value later when we have to
write it to the WM_LPn registers' latency field. So delay the
multiplication until it's needed.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c266e47..a2ca018 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2346,10 +2346,10 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
 		wm[0] = (sskpd >> 56) & 0xFF;
 		if (wm[0] == 0)
 			wm[0] = sskpd & 0xF;
-		wm[1] = ((sskpd >> 4) & 0xFF) * 5;
-		wm[2] = ((sskpd >> 12) & 0xFF) * 5;
-		wm[3] = ((sskpd >> 20) & 0x1FF) * 5;
-		wm[4] = ((sskpd >> 32) & 0x1FF) * 5;
+		wm[1] = (sskpd >> 4) & 0xFF;
+		wm[2] = (sskpd >> 12) & 0xFF;
+		wm[3] = (sskpd >> 20) & 0x1FF;
+		wm[4] = (sskpd >> 32) & 0x1FF;
 	}
 }
 
@@ -2427,7 +2427,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 	int level, max_level, wm_lp;
 
 	for (level = 1; level <= 4; level++)
-		if (!hsw_compute_lp_wm(wm[level], lp_maximums, params,
+		if (!hsw_compute_lp_wm(wm[level] * 5, lp_maximums, params,
 				       &lp_results[level - 1]))
 			break;
 	max_level = level - 1;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 11/35] drm/i915: Add SNB/IVB support to intel_read_wm_latency
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (9 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 10/35] drm/i915: Don't multiply the watermark latency values too early ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 21:01   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 12/35] drm/i915: Add ILK " ville.syrjala
                   ` (24 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

SNB and IVB have slightly a different way to read out the
watermark latency values.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index a2ca018..6ff89c6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2350,6 +2350,13 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
 		wm[2] = (sskpd >> 12) & 0xFF;
 		wm[3] = (sskpd >> 20) & 0x1FF;
 		wm[4] = (sskpd >> 32) & 0x1FF;
+	} else if (INTEL_INFO(dev)->gen >= 6) {
+		uint32_t sskpd = I915_READ(MCH_SSKPD);
+
+		wm[0] = (sskpd >> SSKPD_WM0_SHIFT) & SSKPD_WM_MASK;
+		wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK;
+		wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK;
+		wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK;
 	}
 }
 
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 12/35] drm/i915: Add ILK support to intel_read_wm_latency
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (10 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 11/35] drm/i915: Add SNB/IVB support to intel_read_wm_latency ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 13/35] drm/i915: Store the watermark latency values in dev_priv ville.syrjala
                   ` (23 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

ILK has a slightly different way to read out the watermark
latency values. On ILK the LP0 latenciy values are in fact
not stored in any register, and instead we must use fixed
values.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6ff89c6..e4d2477 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2357,6 +2357,13 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
 		wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK;
 		wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK;
 		wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK;
+	} else if (INTEL_INFO(dev)->gen >= 5) {
+		uint32_t mltr = I915_READ(MLTR_ILK);
+
+		/* ILK primary LP0 latency is 700 ns */
+		wm[0] = 7;
+		wm[1] = (mltr >> MLTR_WM1_SHIFT) & ILK_SRLT_MASK;
+		wm[2] = (mltr >> MLTR_WM2_SHIFT) & ILK_SRLT_MASK;
 	}
 }
 
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 13/35] drm/i915: Store the watermark latency values in dev_priv
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (11 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 12/35] drm/i915: Add ILK " ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
       [not found]   ` <CA+gsUGQ0JqEZiEUsONJh7nr6rPYRfTxJM79oc5tGcexEudB2Og@mail.gmail.com>
  2013-07-05  8:57 ` [PATCH 14/35] drm/i915: Use the stored cursor and plane latencies properly ville.syrjala
                   ` (22 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Rather than having to read the latency values out every time, just
store them in dev_priv.

On ILK and IVB there is a difference between some of the latency
values for different planes, so store the latency values for each
plane type separately, and apply the necesary fixups during init.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h |  9 ++++++
 drivers/gpu/drm/i915/intel_pm.c | 62 +++++++++++++++++++++++++++++++++++------
 2 files changed, 62 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 99eb980..60f9437 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1184,6 +1184,15 @@ typedef struct drm_i915_private {
 
 	struct i915_suspend_saved_registers regfile;
 
+	struct {
+		/* watermark latency values for primary */
+		uint16_t pri_latency[5];
+		/* watermark latency values for sprite */
+		uint16_t spr_latency[5];
+		/* watermark latency values for cursor */
+		uint16_t cur_latency[5];
+	} wm;
+
 	/* Old dri1 support infrastructure, beware the dragons ya fools entering
 	 * here! */
 	struct i915_dri1_state dri1;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e4d2477..68a1de4 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2367,6 +2367,39 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
 	}
 }
 
+static void intel_fixup_spr_wm_latency(struct drm_device *dev, uint16_t wm[5])
+{
+	/* ILK sprite LP0 latency is 1300 ns */
+	if (INTEL_INFO(dev)->gen == 5)
+		wm[0] = 13;
+}
+
+static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
+{
+	/* ILK cursor LP0 latency is 1300 ns */
+	if (INTEL_INFO(dev)->gen == 5)
+		wm[0] = 13;
+
+	/* WaDoubleCursorLP3Latency:ivb */
+	if (IS_IVYBRIDGE(dev))
+		wm[3] *= 2;
+}
+
+static void intel_setup_wm_latency(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	intel_read_wm_latency(dev, 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,
+	       sizeof dev_priv->wm.pri_latency);
+
+	intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency);
+	intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency);
+}
+
 static void hsw_compute_wm_parameters(struct drm_device *dev,
 				      struct hsw_pipe_wm_parameters *params,
 				      struct hsw_wm_maximums *lp_max_1_2,
@@ -2612,16 +2645,17 @@ static void haswell_update_wm(struct drm_device *dev)
 	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
 	struct hsw_pipe_wm_parameters params[3];
 	struct hsw_wm_values results_1_2, results_5_6, *best_results;
-	uint16_t wm[5] = {};
 	enum hsw_data_buf_partitioning partitioning;
 
-	intel_read_wm_latency(dev, wm);
 	hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
 
-	hsw_compute_wm_results(dev, params, wm, &lp_max_1_2, &results_1_2);
+	hsw_compute_wm_results(dev, params,
+			       dev_priv->wm.pri_latency,
+			       &lp_max_1_2, &results_1_2);
 	if (lp_max_1_2.pri != lp_max_5_6.pri) {
-		hsw_compute_wm_results(dev, params, wm, &lp_max_5_6,
-				       &results_5_6);
+		hsw_compute_wm_results(dev, params,
+				       dev_priv->wm.pri_latency,
+				       &lp_max_5_6, &results_5_6);
 		best_results = hsw_find_best_result(&results_1_2, &results_5_6);
 	} else {
 		best_results = &results_1_2;
@@ -5211,8 +5245,12 @@ void intel_init_pm(struct drm_device *dev)
 
 	/* For FIFO watermark updates */
 	if (HAS_PCH_SPLIT(dev)) {
+		intel_setup_wm_latency(dev);
+
 		if (IS_GEN5(dev)) {
-			if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
+			if (dev_priv->wm.pri_latency[1] &&
+			    dev_priv->wm.spr_latency[1] &&
+			    dev_priv->wm.cur_latency[1])
 				dev_priv->display.update_wm = ironlake_update_wm;
 			else {
 				DRM_DEBUG_KMS("Failed to get proper latency. "
@@ -5221,7 +5259,9 @@ void intel_init_pm(struct drm_device *dev)
 			}
 			dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
 		} else if (IS_GEN6(dev)) {
-			if (SNB_READ_WM0_LATENCY()) {
+			if (dev_priv->wm.pri_latency[0] &&
+			    dev_priv->wm.spr_latency[0] &&
+			    dev_priv->wm.cur_latency[0]) {
 				dev_priv->display.update_wm = sandybridge_update_wm;
 				dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
 			} else {
@@ -5231,7 +5271,9 @@ void intel_init_pm(struct drm_device *dev)
 			}
 			dev_priv->display.init_clock_gating = gen6_init_clock_gating;
 		} else if (IS_IVYBRIDGE(dev)) {
-			if (SNB_READ_WM0_LATENCY()) {
+			if (dev_priv->wm.pri_latency[0] &&
+			    dev_priv->wm.spr_latency[0] &&
+			    dev_priv->wm.cur_latency[0]) {
 				dev_priv->display.update_wm = ivybridge_update_wm;
 				dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
 			} else {
@@ -5241,7 +5283,9 @@ void intel_init_pm(struct drm_device *dev)
 			}
 			dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
 		} else if (IS_HASWELL(dev)) {
-			if (I915_READ64(MCH_SSKPD)) {
+			if (dev_priv->wm.pri_latency[0] &&
+			    dev_priv->wm.spr_latency[0] &&
+			    dev_priv->wm.cur_latency[0]) {
 				dev_priv->display.update_wm = haswell_update_wm;
 				dev_priv->display.update_sprite_wm =
 					haswell_update_sprite_wm;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 14/35] drm/i915: Use the stored cursor and plane latencies properly
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (12 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 13/35] drm/i915: Store the watermark latency values in dev_priv ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 15/35] drm/i915: Print the watermark latencies during init ville.syrjala
                   ` (21 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Rather than pass around the plane latencies, just grab them from
dev_priv nearer to where they're needed. Do the same for cursor
latencies.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 68a1de4..37919df 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2255,7 +2255,8 @@ static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
 			  params->pri_bytes_per_pixel);
 }
 
-static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
+static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
+			      int level, struct hsw_wm_maximums *max,
 			      struct hsw_pipe_wm_parameters *params,
 			      struct hsw_lp_wm_result *result)
 {
@@ -2264,10 +2265,13 @@ static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
 
 	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) {
 		struct hsw_pipe_wm_parameters *p = &params[pipe];
+		uint16_t pri_latency = dev_priv->wm.pri_latency[level] * 5;
+		uint16_t spr_latency = dev_priv->wm.spr_latency[level] * 5;
+		uint16_t cur_latency = dev_priv->wm.cur_latency[level] * 5;
 
-		pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, 1);
-		spr_val[pipe] = ilk_compute_spr_wm(p, mem_value);
-		cur_val[pipe] = ilk_compute_cur_wm(p, mem_value);
+		pri_val[pipe] = ilk_compute_pri_wm(p, pri_latency, 1);
+		spr_val[pipe] = ilk_compute_spr_wm(p, spr_latency);
+		cur_val[pipe] = ilk_compute_cur_wm(p, cur_latency);
 		fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe]);
 	}
 
@@ -2290,14 +2294,17 @@ static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
 }
 
 static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
-				    uint32_t mem_value, enum pipe pipe,
+				    enum pipe pipe,
 				    struct hsw_pipe_wm_parameters *params)
 {
 	uint32_t pri_val, cur_val, spr_val;
+	uint16_t pri_latency = dev_priv->wm.pri_latency[0];
+	uint16_t spr_latency = dev_priv->wm.spr_latency[0];
+	uint16_t cur_latency = dev_priv->wm.cur_latency[0];
 
-	pri_val = ilk_compute_pri_wm(params, mem_value, 0);
-	spr_val = ilk_compute_spr_wm(params, mem_value);
-	cur_val = ilk_compute_cur_wm(params, mem_value);
+	pri_val = ilk_compute_pri_wm(params, pri_latency, 0);
+	spr_val = ilk_compute_spr_wm(params, spr_latency);
+	cur_val = ilk_compute_cur_wm(params, cur_latency);
 
 	WARN(pri_val > 127,
 	     "Primary WM error, mode not supported for pipe %c\n",
@@ -2463,7 +2470,6 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 
 static void hsw_compute_wm_results(struct drm_device *dev,
 				   struct hsw_pipe_wm_parameters *params,
-				   uint16_t *wm,
 				   struct hsw_wm_maximums *lp_maximums,
 				   struct hsw_wm_values *results)
 {
@@ -2474,7 +2480,8 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 	int level, max_level, wm_lp;
 
 	for (level = 1; level <= 4; level++)
-		if (!hsw_compute_lp_wm(wm[level] * 5, lp_maximums, params,
+		if (!hsw_compute_lp_wm(dev_priv, level,
+				       lp_maximums, params,
 				       &lp_results[level - 1]))
 			break;
 	max_level = level - 1;
@@ -2506,8 +2513,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 	}
 
 	for_each_pipe(pipe)
-		results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev_priv, wm[0],
-							     pipe,
+		results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev_priv, pipe,
 							     &params[pipe]);
 
 	for_each_pipe(pipe) {
@@ -2650,11 +2656,9 @@ static void haswell_update_wm(struct drm_device *dev)
 	hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
 
 	hsw_compute_wm_results(dev, params,
-			       dev_priv->wm.pri_latency,
 			       &lp_max_1_2, &results_1_2);
 	if (lp_max_1_2.pri != lp_max_5_6.pri) {
 		hsw_compute_wm_results(dev, params,
-				       dev_priv->wm.pri_latency,
 				       &lp_max_5_6, &results_5_6);
 		best_results = hsw_find_best_result(&results_1_2, &results_5_6);
 	} else {
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 15/35] drm/i915: Print the watermark latencies during init
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (13 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 14/35] drm/i915: Use the stored cursor and plane latencies properly ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 21:49   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 16/35] drm/i915: Disable specific watermark levels when latency is zero ville.syrjala
                   ` (20 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Seeing the watermark latency values in dmesg might help sometimes.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 37919df..5687957 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2392,6 +2392,24 @@ static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
 		wm[3] *= 2;
 }
 
+static void intel_print_wm_latency(struct drm_device *dev, const uint16_t wm[5])
+{
+	int level;
+
+	for (level = 0; level <= 4; level++) {
+		unsigned int latency = wm[level];
+
+		if (latency == 0)
+			continue;
+
+		if (level > 0)
+			latency *= 5;
+
+		DRM_DEBUG_KMS(" WM%d latency %u (%u.%u usec)\n",
+			      level, wm[level], latency / 10, latency % 10);
+	}
+}
+
 static void intel_setup_wm_latency(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2405,6 +2423,13 @@ static void intel_setup_wm_latency(struct drm_device *dev)
 
 	intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency);
 	intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency);
+
+	DRM_DEBUG_KMS("Primary watermark latencies:\n");
+	intel_print_wm_latency(dev, dev_priv->wm.pri_latency);
+	DRM_DEBUG_KMS("Sprite watermark latencies:\n");
+	intel_print_wm_latency(dev, dev_priv->wm.spr_latency);
+	DRM_DEBUG_KMS("Cursor watermark latencies:\n");
+	intel_print_wm_latency(dev, dev_priv->wm.cur_latency);
 }
 
 static void hsw_compute_wm_parameters(struct drm_device *dev,
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 16/35] drm/i915: Disable specific watermark levels when latency is zero
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (14 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 15/35] drm/i915: Print the watermark latencies during init ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-30 21:51   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 17/35] drm/i915: Pull watermark level validity check out ville.syrjala
                   ` (19 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Return UINT_MAX for the calculated WM level if the latency is zero.
This will lead to marking the WM level as disabled.

I'm not sure if latency==0 should mean that we want to disable the
level. But that's the implication I got from the fact that we don't
even enable the watermark code of the SSKDP register is 0.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 5687957..a919445 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2116,6 +2116,9 @@ static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
 {
 	uint64_t ret;
 
+	if (latency == 0)
+		return UINT_MAX;
+
 	ret = (uint64_t) pixel_rate * bytes_per_pixel * latency;
 	ret = DIV_ROUND_UP_ULL(ret, 64 * 10000) + 2;
 
@@ -2128,6 +2131,9 @@ static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
 {
 	uint32_t ret;
 
+	if (latency == 0)
+		return UINT_MAX;
+
 	ret = (latency * pixel_rate) / (pipe_htotal * 10000);
 	ret = (ret + 1) * horiz_pixels * bytes_per_pixel;
 	ret = DIV_ROUND_UP(ret, 64) + 2;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 17/35] drm/i915: Pull watermark level validity check out
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (15 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 16/35] drm/i915: Disable specific watermark levels when latency is zero ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 18/35] drm/i915: Split watermark level computation from the code ville.syrjala
                   ` (18 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Refactor the code a bit to split the watermark level validity check into
a separate function.

Also add hack there that allows us to use it even for LP0 watermarks.
ATM we don't pre-compute/check the LP0 watermarks, so we just have to
clamp them to the maximum and hope things work out.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index a919445..1d63d47 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2261,6 +2261,36 @@ static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
 			  params->pri_bytes_per_pixel);
 }
 
+static bool ilk_check_wm(int level,
+			 const struct hsw_wm_maximums *max,
+			 struct hsw_lp_wm_result *result)
+{
+	bool ret;
+
+	result->enable = result->pri_val <= max->pri &&
+			 result->spr_val <= max->spr &&
+			 result->cur_val <= max->cur;
+
+	ret = result->enable;
+
+	/*
+	 * HACK until we can pre-compute everything,
+	 * and thus fail gracefully if LP0 watermarks
+	 * are exceeded...
+	 */
+	if (level == 0 && !result->enable) {
+		result->pri_val = min_t(uint32_t, result->pri_val, max->pri);
+		result->spr_val = min_t(uint32_t, result->spr_val, max->spr);
+		result->cur_val = min_t(uint32_t, result->cur_val, max->cur);
+		result->enable = true;
+		ret = false;
+	}
+
+	DRM_DEBUG_KMS("WM%d: %sabled\n", level, result->enable ? "en" : "dis");
+
+	return ret;
+}
+
 static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
 			      int level, struct hsw_wm_maximums *max,
 			      struct hsw_pipe_wm_parameters *params,
@@ -2293,10 +2323,7 @@ static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
 		result->fbc_enable = true;
 	}
 
-	result->enable = result->pri_val <= max->pri &&
-			 result->spr_val <= max->spr &&
-			 result->cur_val <= max->cur;
-	return result->enable;
+	return ilk_check_wm(level, max, result);
 }
 
 static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 18/35] drm/i915: Split watermark level computation from the code
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (16 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 17/35] drm/i915: Pull watermark level validity check out ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 19/35] drm/i915: Kill fbc_enable from hsw_lp_wm_results ville.syrjala
                   ` (17 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Refactor the watermarks computation for one level to a separate
function. This function will now set the ->enable flat to true,
even if the watermark level wasn't actually checked yet. In the
future we will delay the checking so we must consider all unchecked
watermarks as possibly valid.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 49 +++++++++++++++++++++++++++--------------
 1 file changed, 33 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 1d63d47..3f6cffd 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2267,6 +2267,9 @@ static bool ilk_check_wm(int level,
 {
 	bool ret;
 
+	if (!result->enable)
+		return false;
+
 	result->enable = result->pri_val <= max->pri &&
 			 result->spr_val <= max->spr &&
 			 result->cur_val <= max->cur;
@@ -2291,30 +2294,44 @@ static bool ilk_check_wm(int level,
 	return ret;
 }
 
+static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
+				 int level,
+				 struct hsw_pipe_wm_parameters *p,
+				 struct hsw_lp_wm_result *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];
+
+	if (level > 0) {
+		pri_latency *= 5;
+		spr_latency *= 5;
+		cur_latency *= 5;
+	}
+
+	result->pri_val = ilk_compute_pri_wm(p, pri_latency, level);
+	result->spr_val = ilk_compute_spr_wm(p, spr_latency);
+	result->cur_val = ilk_compute_cur_wm(p, cur_latency);
+	result->fbc_val = ilk_compute_fbc_wm(p, result->pri_val);
+	result->enable = true;
+}
+
 static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
 			      int level, struct hsw_wm_maximums *max,
 			      struct hsw_pipe_wm_parameters *params,
 			      struct hsw_lp_wm_result *result)
 {
 	enum pipe pipe;
-	uint32_t pri_val[3], spr_val[3], cur_val[3], fbc_val[3];
+	struct hsw_lp_wm_result res[3];
 
-	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) {
-		struct hsw_pipe_wm_parameters *p = &params[pipe];
-		uint16_t pri_latency = dev_priv->wm.pri_latency[level] * 5;
-		uint16_t spr_latency = dev_priv->wm.spr_latency[level] * 5;
-		uint16_t cur_latency = dev_priv->wm.cur_latency[level] * 5;
+	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++)
+		ilk_compute_wm_level(dev_priv, level, &params[pipe], &res[pipe]);
 
-		pri_val[pipe] = ilk_compute_pri_wm(p, pri_latency, 1);
-		spr_val[pipe] = ilk_compute_spr_wm(p, spr_latency);
-		cur_val[pipe] = ilk_compute_cur_wm(p, cur_latency);
-		fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe]);
-	}
-
-	result->pri_val = max3(pri_val[0], pri_val[1], pri_val[2]);
-	result->spr_val = max3(spr_val[0], spr_val[1], spr_val[2]);
-	result->cur_val = max3(cur_val[0], cur_val[1], cur_val[2]);
-	result->fbc_val = max3(fbc_val[0], fbc_val[1], fbc_val[2]);
+	result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val);
+	result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val);
+	result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val);
+	result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val);
+	result->enable = true;
 
 	if (result->fbc_val > max->fbc) {
 		result->fbc_enable = false;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 19/35] drm/i915: Kill fbc_enable from hsw_lp_wm_results
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (17 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 18/35] drm/i915: Split watermark level computation from the code ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 20/35] drm/i915: Rename hsw_data_buf_partitioning to intel_ddb_partitioning ville.syrjala
                   ` (16 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We don't need to store the FBC WM enabled status in each watermark
level. We anyway have to reduce it down to a single boolean, so just
delay checking the FBC WM limit until we're computing the final
value.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 3f6cffd..974e171 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2168,7 +2168,6 @@ struct hsw_wm_maximums {
 
 struct hsw_lp_wm_result {
 	bool enable;
-	bool fbc_enable;
 	uint32_t pri_val;
 	uint32_t spr_val;
 	uint32_t cur_val;
@@ -2333,13 +2332,6 @@ static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
 	result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val);
 	result->enable = true;
 
-	if (result->fbc_val > max->fbc) {
-		result->fbc_enable = false;
-		result->fbc_val = 0;
-	} else {
-		result->fbc_enable = true;
-	}
-
 	return ilk_check_wm(level, max, result);
 }
 
@@ -2565,9 +2557,9 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 	 * a WM level. */
 	results->enable_fbc_wm = true;
 	for (level = 1; level <= max_level; level++) {
-		if (!lp_results[level - 1].fbc_enable) {
+		if (!lp_results[level - 1].fbc_val > lp_maximums->fbc) {
 			results->enable_fbc_wm = false;
-			break;
+			lp_results[level - 1].fbc_val = 0;
 		}
 	}
 
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 20/35] drm/i915: Rename hsw_data_buf_partitioning to intel_ddb_partitioning
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (18 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 19/35] drm/i915: Kill fbc_enable from hsw_lp_wm_results ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 21/35] drm/i915: Rename hsw_lp_wm_result to intel_wm_level ville.syrjala
                   ` (15 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We're going to use the 1/2 vs. 5/6 split option already on IVB so the
HSW name is not proper. Just give it an intel_ prefix and move it to
i915_drv.h so that we can use it there later.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h |  5 +++++
 drivers/gpu/drm/i915/intel_pm.c | 17 ++++++-----------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 60f9437..e0b8354 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1012,6 +1012,11 @@ struct intel_vbt_data {
 	struct child_device_config *child_dev;
 };
 
+enum intel_ddb_partitioning {
+	INTEL_DDB_PART_1_2,
+	INTEL_DDB_PART_5_6, /* IVB+ */
+};
+
 typedef struct drm_i915_private {
 	struct drm_device *dev;
 	struct kmem_cache *slab;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 974e171..cf9ec3c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2182,11 +2182,6 @@ struct hsw_wm_values {
 	bool enable_fbc_wm;
 };
 
-enum hsw_data_buf_partitioning {
-	HSW_DATA_BUF_PART_1_2,
-	HSW_DATA_BUF_PART_5_6,
-};
-
 /* For both WM_PIPE and WM_LP. */
 static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value,
@@ -2621,11 +2616,11 @@ static struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1,
  */
 static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 				struct hsw_wm_values *results,
-				enum hsw_data_buf_partitioning partitioning)
+				enum intel_ddb_partitioning partitioning)
 {
 	struct hsw_wm_values previous;
 	uint32_t val;
-	enum hsw_data_buf_partitioning prev_partitioning;
+	enum intel_ddb_partitioning prev_partitioning;
 	bool prev_enable_fbc_wm;
 
 	previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
@@ -2642,7 +2637,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 	previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
 
 	prev_partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
-			    HSW_DATA_BUF_PART_5_6 : HSW_DATA_BUF_PART_1_2;
+				INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
 
 	prev_enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
 
@@ -2681,7 +2676,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 
 	if (prev_partitioning != partitioning) {
 		val = I915_READ(WM_MISC);
-		if (partitioning == HSW_DATA_BUF_PART_1_2)
+		if (partitioning == INTEL_DDB_PART_1_2)
 			val &= ~WM_MISC_DATA_PARTITION_5_6;
 		else
 			val |= WM_MISC_DATA_PARTITION_5_6;
@@ -2718,7 +2713,7 @@ static void haswell_update_wm(struct drm_device *dev)
 	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
 	struct hsw_pipe_wm_parameters params[3];
 	struct hsw_wm_values results_1_2, results_5_6, *best_results;
-	enum hsw_data_buf_partitioning partitioning;
+	enum intel_ddb_partitioning partitioning;
 
 	hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
 
@@ -2733,7 +2728,7 @@ static void haswell_update_wm(struct drm_device *dev)
 	}
 
 	partitioning = (best_results == &results_1_2) ?
-		       HSW_DATA_BUF_PART_1_2 : HSW_DATA_BUF_PART_5_6;
+		       INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
 
 	hsw_write_wm_values(dev_priv, best_results, partitioning);
 }
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 21/35] drm/i915: Rename hsw_lp_wm_result to intel_wm_level
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (19 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 20/35] drm/i915: Rename hsw_data_buf_partitioning to intel_ddb_partitioning ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 22/35] drm/i915: Calculate max watermark levels for ILK+ ville.syrjala
                   ` (14 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Let's call hsw_lp_wm_result intel_wm_level from now on and move it to
i915_drv.h for later use.

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

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e0b8354..5c139fe 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1017,6 +1017,14 @@ enum intel_ddb_partitioning {
 	INTEL_DDB_PART_5_6, /* IVB+ */
 };
 
+struct intel_wm_level {
+	bool enable;
+	uint32_t pri_val;
+	uint32_t spr_val;
+	uint32_t cur_val;
+	uint32_t fbc_val;
+};
+
 typedef struct drm_i915_private {
 	struct drm_device *dev;
 	struct kmem_cache *slab;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index cf9ec3c..2415bfa 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2166,14 +2166,6 @@ struct hsw_wm_maximums {
 	uint16_t fbc;
 };
 
-struct hsw_lp_wm_result {
-	bool enable;
-	uint32_t pri_val;
-	uint32_t spr_val;
-	uint32_t cur_val;
-	uint32_t fbc_val;
-};
-
 struct hsw_wm_values {
 	uint32_t wm_pipe[3];
 	uint32_t wm_lp[3];
@@ -2257,7 +2249,7 @@ static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
 
 static bool ilk_check_wm(int level,
 			 const struct hsw_wm_maximums *max,
-			 struct hsw_lp_wm_result *result)
+			 struct intel_wm_level *result)
 {
 	bool ret;
 
@@ -2291,7 +2283,7 @@ static bool ilk_check_wm(int level,
 static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
 				 int level,
 				 struct hsw_pipe_wm_parameters *p,
-				 struct hsw_lp_wm_result *result)
+				 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];
@@ -2313,10 +2305,10 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
 static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
 			      int level, struct hsw_wm_maximums *max,
 			      struct hsw_pipe_wm_parameters *params,
-			      struct hsw_lp_wm_result *result)
+			      struct intel_wm_level *result)
 {
 	enum pipe pipe;
-	struct hsw_lp_wm_result res[3];
+	struct intel_wm_level res[3];
 
 	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++)
 		ilk_compute_wm_level(dev_priv, level, &params[pipe], &res[pipe]);
@@ -2537,7 +2529,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
-	struct hsw_lp_wm_result lp_results[4] = {};
+	struct intel_wm_level lp_results[4] = {};
 	enum pipe pipe;
 	int level, max_level, wm_lp;
 
@@ -2560,7 +2552,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 
 	memset(results, 0, sizeof(*results));
 	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
-		const struct hsw_lp_wm_result *r;
+		const struct intel_wm_level *r;
 
 		level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp;
 		if (level > max_level)
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 22/35] drm/i915: Calculate max watermark levels for ILK+
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (20 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 21/35] drm/i915: Rename hsw_lp_wm_result to intel_wm_level ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 23/35] drm/i915; Pull some watermarks state into a separate structure ville.syrjala
                   ` (13 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

There are quite a few variables we need to take into account to
determine the maximum watermark levels, so it feels a bit cleaner
to calculate those rather than just have a bunch of what look like
magic numbers.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 119 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 107 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 2415bfa..2bdb0ae 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2247,6 +2247,104 @@ static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
 			  params->pri_bytes_per_pixel);
 }
 
+static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
+{
+	if (INTEL_INFO(dev)->gen >= 7)
+		return 768;
+	else
+		return 512;
+}
+
+/* Calculate the maximum primary/sprite plane watermark */
+static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
+				     int level,
+				     unsigned int pipes_active,
+				     bool sprite_enabled,
+				     enum intel_ddb_partitioning ddb_partitioning,
+				     bool is_sprite)
+{
+	unsigned int fifo_size = ilk_display_fifo_size(dev);
+	unsigned int max;
+
+	/* if sprites aren't enabled, sprites get nothing */
+	if (is_sprite && !sprite_enabled)
+		return 0;
+
+	/* HSW allows LP1+ watermarks even with multiple pipes */
+	if (level == 0 || pipes_active > 1) {
+		fifo_size /= INTEL_INFO(dev)->num_pipes;
+
+		/*
+		 * For some reason the non self refresh
+		 * FIFO size is only half of the self
+		 * refresh FIFO size on ILK/SNB.
+		 */
+		if (INTEL_INFO(dev)->gen <= 6)
+			fifo_size /= 2;
+	}
+
+	if (sprite_enabled) {
+		/* level 0 is always calculated with 1:1 split */
+		if (level > 0 && ddb_partitioning == INTEL_DDB_PART_5_6) {
+			if (is_sprite)
+				fifo_size *= 5;
+			fifo_size /= 6;
+		} else {
+			fifo_size /= 2;
+		}
+	}
+
+	/* clamp to max that the registers can hold */
+	if (INTEL_INFO(dev)->gen >= 7)
+		/* IVB/HSW primary/sprite plane watermarks */
+		max = level == 0 ? 127 : 1023;
+	else if (!is_sprite)
+		/* ILK/SNB primary plane watermarks */
+		max = level == 0 ? 127 : 511;
+	else
+		/* ILK/SNB sprite plane watermarks */
+		max = level == 0 ? 63 : 255;
+
+	return min(fifo_size, max);
+}
+
+/* Calculate the maximum cursor plane watermark */
+static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
+				      int level, unsigned int pipes_active)
+{
+	/* HSW LP1+ watermarks w/ multiple pipes */
+	if (level > 0 && pipes_active > 1)
+		return 64;
+
+	/* othwewise just report max that registers can hold */
+	if (INTEL_INFO(dev)->gen >= 7)
+		return level == 0 ? 63 : 255;
+	else
+		return level == 0 ? 31 : 63;
+}
+
+/* Calculate the maximum FBC watermark */
+static unsigned int ilk_fbc_wm_max(void)
+{
+	/* max that registers can hold */
+	return 15;
+}
+
+static void ilk_wm_max(struct drm_device *dev,
+		       int level,
+		       unsigned int pipes_active,
+		       bool sprite_enabled,
+		       enum intel_ddb_partitioning ddb_partitioning,
+		       struct hsw_wm_maximums *max)
+{
+	max->pri = ilk_plane_wm_max(dev, level, pipes_active,
+				    sprite_enabled, ddb_partitioning, false);
+	max->spr = ilk_plane_wm_max(dev, level, pipes_active,
+				    sprite_enabled, ddb_partitioning, true);
+	max->cur = ilk_cursor_wm_max(dev, level, pipes_active);
+	max->fbc = ilk_fbc_wm_max();
+}
+
 static bool ilk_check_wm(int level,
 			 const struct hsw_wm_maximums *max,
 			 struct intel_wm_level *result)
@@ -2508,18 +2606,15 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 			sprites_enabled++;
 	}
 
-	if (pipes_active > 1) {
-		lp_max_1_2->pri = lp_max_5_6->pri = sprites_enabled ? 128 : 256;
-		lp_max_1_2->spr = lp_max_5_6->spr = 128;
-		lp_max_1_2->cur = lp_max_5_6->cur = 64;
-	} else {
-		lp_max_1_2->pri = sprites_enabled ? 384 : 768;
-		lp_max_5_6->pri = sprites_enabled ? 128 : 768;
-		lp_max_1_2->spr = 384;
-		lp_max_5_6->spr = 640;
-		lp_max_1_2->cur = lp_max_5_6->cur = 255;
-	}
-	lp_max_1_2->fbc = lp_max_5_6->fbc = 15;
+	ilk_wm_max(dev, 1, pipes_active, sprites_enabled,
+		   INTEL_DDB_PART_1_2, lp_max_1_2);
+
+	/* 5/6 split only in single pipe config on IVB+ */
+	if (INTEL_INFO(dev)->gen >= 7 && pipes_active <= 1)
+		ilk_wm_max(dev, 1, pipes_active, sprites_enabled,
+			   INTEL_DDB_PART_5_6, lp_max_5_6);
+	else
+		*lp_max_5_6 = *lp_max_1_2;
 }
 
 static void hsw_compute_wm_results(struct drm_device *dev,
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 23/35] drm/i915; Pull some watermarks state into a separate structure
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (21 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 22/35] drm/i915: Calculate max watermark levels for ILK+ ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 24/35] drm/i915: Split plane watermark parameters into a separate struct ville.syrjala
                   ` (12 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

There is a bunch of global state that needs to be considered when
checking watermarks for validity. Move most of that to a new
structure intel_wm_config, to avoid having to pass around so
many variables.

One notable thing left out is the DDB partitioning information,
since we often anyway need to check the same watermarks against
both 1/2 and 5/6 DDB partitioning layouts.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 48 +++++++++++++++++++++--------------------
 1 file changed, 25 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 2bdb0ae..43d05db 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2174,6 +2174,14 @@ struct hsw_wm_values {
 	bool enable_fbc_wm;
 };
 
+/* used in computing the new watermarks state */
+struct intel_wm_config {
+	unsigned int pipes_active;
+	bool sprites_enabled;
+	bool sprites_scaled;
+	bool fbc_wm_enabled;
+};
+
 /* For both WM_PIPE and WM_LP. */
 static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value,
@@ -2258,8 +2266,7 @@ static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
 /* Calculate the maximum primary/sprite plane watermark */
 static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 				     int level,
-				     unsigned int pipes_active,
-				     bool sprite_enabled,
+				     const struct intel_wm_config *config,
 				     enum intel_ddb_partitioning ddb_partitioning,
 				     bool is_sprite)
 {
@@ -2267,11 +2274,11 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 	unsigned int max;
 
 	/* if sprites aren't enabled, sprites get nothing */
-	if (is_sprite && !sprite_enabled)
+	if (is_sprite && !config->sprites_enabled)
 		return 0;
 
 	/* HSW allows LP1+ watermarks even with multiple pipes */
-	if (level == 0 || pipes_active > 1) {
+	if (level == 0 || config->pipes_active > 1) {
 		fifo_size /= INTEL_INFO(dev)->num_pipes;
 
 		/*
@@ -2283,7 +2290,7 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 			fifo_size /= 2;
 	}
 
-	if (sprite_enabled) {
+	if (config->sprites_enabled) {
 		/* level 0 is always calculated with 1:1 split */
 		if (level > 0 && ddb_partitioning == INTEL_DDB_PART_5_6) {
 			if (is_sprite)
@@ -2310,10 +2317,11 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 
 /* Calculate the maximum cursor plane watermark */
 static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
-				      int level, unsigned int pipes_active)
+				      int level,
+				      const struct intel_wm_config *config)
 {
 	/* HSW LP1+ watermarks w/ multiple pipes */
-	if (level > 0 && pipes_active > 1)
+	if (level > 0 && config->pipes_active > 1)
 		return 64;
 
 	/* othwewise just report max that registers can hold */
@@ -2332,16 +2340,13 @@ static unsigned int ilk_fbc_wm_max(void)
 
 static void ilk_wm_max(struct drm_device *dev,
 		       int level,
-		       unsigned int pipes_active,
-		       bool sprite_enabled,
+		       const struct intel_wm_config *config,
 		       enum intel_ddb_partitioning ddb_partitioning,
 		       struct hsw_wm_maximums *max)
 {
-	max->pri = ilk_plane_wm_max(dev, level, pipes_active,
-				    sprite_enabled, ddb_partitioning, false);
-	max->spr = ilk_plane_wm_max(dev, level, pipes_active,
-				    sprite_enabled, ddb_partitioning, true);
-	max->cur = ilk_cursor_wm_max(dev, level, pipes_active);
+	max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
+	max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
+	max->cur = ilk_cursor_wm_max(dev, level, config);
 	max->fbc = ilk_fbc_wm_max();
 }
 
@@ -2567,7 +2572,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 	struct drm_crtc *crtc;
 	struct drm_plane *plane;
 	enum pipe pipe;
-	int pipes_active = 0, sprites_enabled = 0;
+	struct intel_wm_config config = {};
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -2580,7 +2585,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 		if (!p->active)
 			continue;
 
-		pipes_active++;
+		config.pipes_active++;
 
 		p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
 		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
@@ -2602,17 +2607,14 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 		p->spr_bytes_per_pixel = intel_plane->wm.bytes_per_pixel;
 		p->spr_horiz_pixels = intel_plane->wm.horiz_pixels;
 
-		if (p->sprite_enabled)
-			sprites_enabled++;
+		config.sprites_enabled |= p->sprite_enabled;
 	}
 
-	ilk_wm_max(dev, 1, pipes_active, sprites_enabled,
-		   INTEL_DDB_PART_1_2, lp_max_1_2);
+	ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
 
 	/* 5/6 split only in single pipe config on IVB+ */
-	if (INTEL_INFO(dev)->gen >= 7 && pipes_active <= 1)
-		ilk_wm_max(dev, 1, pipes_active, sprites_enabled,
-			   INTEL_DDB_PART_5_6, lp_max_5_6);
+	if (INTEL_INFO(dev)->gen >= 7 && config.pipes_active <= 1)
+		ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6);
 	else
 		*lp_max_5_6 = *lp_max_1_2;
 }
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 24/35] drm/i915: Split plane watermark parameters into a separate struct
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (22 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 23/35] drm/i915; Pull some watermarks state into a separate structure ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 25/35] drm/i915: Pass crtc to our update/disable_plane hooks ville.syrjala
                   ` (11 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Give a name to the plane watermark related data we have currently
stored under intel_plane->wm.

We also observe that this data is more or less the same that we have
in the hsw_pipe_wm_parameters structure, so use it there as well.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h | 14 +++++-----
 drivers/gpu/drm/i915/intel_pm.c  | 57 +++++++++++++++++++---------------------
 2 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3371ecc..390d754 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -334,6 +334,13 @@ struct intel_crtc {
 	bool pch_fifo_underrun_disabled;
 };
 
+struct intel_plane_wm_parameters {
+	bool enabled;
+	bool scaled;
+	uint8_t bytes_per_pixel;
+	uint32_t horiz_pixels;
+};
+
 struct intel_plane {
 	struct drm_plane base;
 	int plane;
@@ -352,12 +359,7 @@ struct intel_plane {
 	 * as the other pieces of the struct may not reflect the values we want
 	 * for the watermark calculations. Currently only Haswell uses this.
 	 */
-	struct {
-		bool enabled;
-		bool scaled;
-		uint8_t bytes_per_pixel;
-		uint32_t horiz_pixels;
-	} wm;
+	struct intel_plane_wm_parameters wm;
 
 	void (*update_plane)(struct drm_plane *plane,
 			     struct drm_framebuffer *fb,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 43d05db..d9d07bc 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2148,15 +2148,11 @@ static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
 
 struct hsw_pipe_wm_parameters {
 	bool active;
-	bool sprite_enabled;
-	uint8_t pri_bytes_per_pixel;
-	uint8_t spr_bytes_per_pixel;
-	uint8_t cur_bytes_per_pixel;
-	uint32_t pri_horiz_pixels;
-	uint32_t spr_horiz_pixels;
-	uint32_t cur_horiz_pixels;
 	uint32_t pipe_htotal;
 	uint32_t pixel_rate;
+	struct intel_plane_wm_parameters pri;
+	struct intel_plane_wm_parameters spr;
+	struct intel_plane_wm_parameters cur;
 };
 
 struct hsw_wm_maximums {
@@ -2189,12 +2185,11 @@ static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 {
 	uint32_t method1, method2;
 
-	/* TODO: for now, assume the primary plane is always enabled. */
-	if (!params->active)
+	if (!params->active || !params->pri.enabled)
 		return 0;
 
 	method1 = ilk_wm_method1(params->pixel_rate,
-				 params->pri_bytes_per_pixel,
+				 params->pri.bytes_per_pixel,
 				 mem_value);
 
 	if (level == 0)
@@ -2202,8 +2197,8 @@ static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 
 	method2 = ilk_wm_method2(params->pixel_rate,
 				 params->pipe_htotal,
-				 params->pri_horiz_pixels,
-				 params->pri_bytes_per_pixel,
+				 params->pri.horiz_pixels,
+				 params->pri.bytes_per_pixel,
 				 mem_value);
 
 	return min(method1, method2);
@@ -2215,16 +2210,16 @@ static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
 {
 	uint32_t method1, method2;
 
-	if (!params->active || !params->sprite_enabled)
+	if (!params->active || !params->spr.enabled)
 		return 0;
 
 	method1 = ilk_wm_method1(params->pixel_rate,
-				 params->spr_bytes_per_pixel,
+				 params->spr.bytes_per_pixel,
 				 mem_value);
 	method2 = ilk_wm_method2(params->pixel_rate,
 				 params->pipe_htotal,
-				 params->spr_horiz_pixels,
-				 params->spr_bytes_per_pixel,
+				 params->spr.horiz_pixels,
+				 params->spr.bytes_per_pixel,
 				 mem_value);
 	return min(method1, method2);
 }
@@ -2233,13 +2228,13 @@ static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
 static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value)
 {
-	if (!params->active)
+	if (!params->active || !params->cur.enabled)
 		return 0;
 
 	return ilk_wm_method2(params->pixel_rate,
 			      params->pipe_htotal,
-			      params->cur_horiz_pixels,
-			      params->cur_bytes_per_pixel,
+			      params->cur.horiz_pixels,
+			      params->cur.bytes_per_pixel,
 			      mem_value);
 }
 
@@ -2247,12 +2242,12 @@ static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
 static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t pri_val)
 {
-	if (!params->active)
+	if (!params->active || !params->pri.enabled)
 		return 0;
 
 	return ilk_wm_fbc(pri_val,
-			  params->pri_horiz_pixels,
-			  params->pri_bytes_per_pixel);
+			  params->pri.horiz_pixels,
+			  params->pri.bytes_per_pixel);
 }
 
 static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
@@ -2589,11 +2584,14 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 
 		p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
 		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
-		p->pri_bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
-		p->cur_bytes_per_pixel = 4;
-		p->pri_horiz_pixels =
+		p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
+		p->cur.bytes_per_pixel = 4;
+		p->pri.horiz_pixels =
 			intel_crtc->config.requested_mode.hdisplay;
-		p->cur_horiz_pixels = 64;
+		p->cur.horiz_pixels = 64;
+		/* TODO: for now, assume primary and cursor planes are always enabled. */
+		p->pri.enabled = true;
+		p->cur.enabled = true;
 	}
 
 	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
@@ -2603,11 +2601,10 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 		pipe = intel_plane->pipe;
 		p = &params[pipe];
 
-		p->sprite_enabled = intel_plane->wm.enabled;
-		p->spr_bytes_per_pixel = intel_plane->wm.bytes_per_pixel;
-		p->spr_horiz_pixels = intel_plane->wm.horiz_pixels;
+		p->spr = intel_plane->wm;
 
-		config.sprites_enabled |= p->sprite_enabled;
+		config.sprites_enabled |= p->spr.enabled;
+		config.sprites_scaled |= p->spr.scaled;
 	}
 
 	ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 25/35] drm/i915: Pass crtc to our update/disable_plane hooks
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (23 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 24/35] drm/i915: Split plane watermark parameters into a separate struct ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 26/35] drm/i915: Don't try to disable plane if it's already disabled ville.syrjala
                   ` (10 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We're going to want to know which CRTC we're dealing with, so pass it
down to the update/disable_plane hooks.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h    |  4 +++-
 drivers/gpu/drm/i915/intel_sprite.c | 21 ++++++++++++---------
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 390d754..699d564 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -362,13 +362,15 @@ struct intel_plane {
 	struct intel_plane_wm_parameters wm;
 
 	void (*update_plane)(struct drm_plane *plane,
+			     struct drm_crtc *crtc,
 			     struct drm_framebuffer *fb,
 			     struct drm_i915_gem_object *obj,
 			     int crtc_x, int crtc_y,
 			     unsigned int crtc_w, unsigned int crtc_h,
 			     uint32_t x, uint32_t y,
 			     uint32_t src_w, uint32_t src_h);
-	void (*disable_plane)(struct drm_plane *plane);
+	void (*disable_plane)(struct drm_plane *plane,
+			      struct drm_crtc *crtc);
 	int (*update_colorkey)(struct drm_plane *plane,
 			       struct drm_intel_sprite_colorkey *key);
 	void (*get_colorkey)(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 7c6cce7..718a705 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -38,7 +38,8 @@
 #include "i915_drv.h"
 
 static void
-vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
+vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
+		 struct drm_framebuffer *fb,
 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 		 unsigned int crtc_w, unsigned int crtc_h,
 		 uint32_t x, uint32_t y,
@@ -140,7 +141,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
 }
 
 static void
-vlv_disable_plane(struct drm_plane *dplane)
+vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 {
 	struct drm_device *dev = dplane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -207,7 +208,8 @@ vlv_get_colorkey(struct drm_plane *dplane,
 }
 
 static void
-ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		 struct drm_framebuffer *fb,
 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 		 unsigned int crtc_w, unsigned int crtc_h,
 		 uint32_t x, uint32_t y,
@@ -319,7 +321,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 }
 
 static void
-ivb_disable_plane(struct drm_plane *plane)
+ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -399,7 +401,8 @@ ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 }
 
 static void
-ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		 struct drm_framebuffer *fb,
 		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 		 unsigned int crtc_w, unsigned int crtc_h,
 		 uint32_t x, uint32_t y,
@@ -486,7 +489,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 }
 
 static void
-ilk_disable_plane(struct drm_plane *plane)
+ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -821,11 +824,11 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		intel_enable_primary(crtc);
 
 	if (visible)
-		intel_plane->update_plane(plane, fb, obj,
+		intel_plane->update_plane(plane, crtc, fb, obj,
 					  crtc_x, crtc_y, crtc_w, crtc_h,
 					  src_x, src_y, src_w, src_h);
 	else
-		intel_plane->disable_plane(plane);
+		intel_plane->disable_plane(plane, crtc);
 
 	if (disable_primary)
 		intel_disable_primary(crtc);
@@ -860,7 +863,7 @@ intel_disable_plane(struct drm_plane *plane)
 
 	if (plane->crtc)
 		intel_enable_primary(plane->crtc);
-	intel_plane->disable_plane(plane);
+	intel_plane->disable_plane(plane, plane->crtc);
 
 	if (!intel_plane->obj)
 		goto out;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 26/35] drm/i915: Don't try to disable plane if it's already disabled
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (24 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 25/35] drm/i915: Pass crtc to our update/disable_plane hooks ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 27/35] drm/i915: Pass plane and crtc to intel_update_sprite_watermarks ville.syrjala
                   ` (9 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Check plane->fb in intel_disable_plane() to determin of the plane is
already disabled.

If the plane has an fb, then it must also have a crtc, so we can drop
the plane->crtc check and just call intel_enable_primary() directly.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_sprite.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 718a705..7f63045 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -861,8 +861,10 @@ intel_disable_plane(struct drm_plane *plane)
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int ret = 0;
 
-	if (plane->crtc)
-		intel_enable_primary(plane->crtc);
+	if (!plane->fb)
+		return 0;
+
+	intel_enable_primary(plane->crtc);
 	intel_plane->disable_plane(plane, plane->crtc);
 
 	if (!intel_plane->obj)
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 27/35] drm/i915: Pass plane and crtc to intel_update_sprite_watermarks
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (25 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 26/35] drm/i915: Don't try to disable plane if it's already disabled ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 28/35] drm/i915: Always call intel_update_sprite_watermarks() when disabling a plane ville.syrjala
                   ` (8 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We're going to want to know the crtc in the watermark code to avoid
doing more work than we have to. We should also pass the plane we're
disabling so that we know where to stick our watermark parameters
without having to go look the plane up.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h     |  3 ++-
 drivers/gpu/drm/i915/intel_drv.h    |  3 ++-
 drivers/gpu/drm/i915/intel_pm.c     | 34 ++++++++++++++++------------------
 drivers/gpu/drm/i915/intel_sprite.c |  8 ++++----
 4 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5c139fe..eabd3d5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -359,7 +359,8 @@ struct drm_i915_display_funcs {
 			  struct dpll *match_clock,
 			  struct dpll *best_clock);
 	void (*update_wm)(struct drm_device *dev);
-	void (*update_sprite_wm)(struct drm_device *dev, int pipe,
+	void (*update_sprite_wm)(struct drm_plane *plane,
+				 struct drm_crtc *crtc,
 				 uint32_t sprite_width, int pixel_size,
 				 bool enable, bool scaled);
 	void (*modeset_global_resources)(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 699d564..bd23fde 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -776,7 +776,8 @@ extern void intel_ddi_init(struct drm_device *dev, enum port port);
 
 /* For use by IVB LP watermark workaround in intel_sprite.c */
 extern void intel_update_watermarks(struct drm_device *dev);
-extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
+extern void intel_update_sprite_watermarks(struct drm_plane *plane,
+					   struct drm_crtc *crtc,
 					   uint32_t sprite_width, int pixel_size,
 					   bool enabled, bool scaled);
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d9d07bc..fdf5898 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2819,25 +2819,19 @@ static void haswell_update_wm(struct drm_device *dev)
 	hsw_write_wm_values(dev_priv, best_results, partitioning);
 }
 
-static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
+static void haswell_update_sprite_wm(struct drm_plane *plane,
+				     struct drm_crtc *crtc,
 				     uint32_t sprite_width, int pixel_size,
 				     bool enabled, bool scaled)
 {
-	struct drm_plane *plane;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
 
-	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-		struct intel_plane *intel_plane = to_intel_plane(plane);
+	intel_plane->wm.enabled = enabled;
+	intel_plane->wm.scaled = scaled;
+	intel_plane->wm.horiz_pixels = sprite_width;
+	intel_plane->wm.bytes_per_pixel = pixel_size;
 
-		if (intel_plane->pipe == pipe) {
-			intel_plane->wm.enabled = enabled;
-			intel_plane->wm.scaled = scaled;
-			intel_plane->wm.horiz_pixels = sprite_width;
-			intel_plane->wm.bytes_per_pixel = pixel_size;
-			break;
-		}
-	}
-
-	haswell_update_wm(dev);
+	haswell_update_wm(plane->dev);
 }
 
 static bool
@@ -2916,11 +2910,14 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
 	return *sprite_wm > 0x3ff ? false : true;
 }
 
-static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
+static void sandybridge_update_sprite_wm(struct drm_plane *plane,
+					 struct drm_crtc *crtc,
 					 uint32_t sprite_width, int pixel_size,
 					 bool enable, bool scaled)
 {
+	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = to_intel_plane(plane)->pipe;
 	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
 	u32 val;
 	int sprite_wm, reg;
@@ -3039,14 +3036,15 @@ void intel_update_watermarks(struct drm_device *dev)
 		dev_priv->display.update_wm(dev);
 }
 
-void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
+void intel_update_sprite_watermarks(struct drm_plane *plane,
+				    struct drm_crtc *crtc,
 				    uint32_t sprite_width, int pixel_size,
 				    bool enable, bool scaled)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = plane->dev->dev_private;
 
 	if (dev_priv->display.update_sprite_wm)
-		dev_priv->display.update_sprite_wm(dev, pipe, sprite_width,
+		dev_priv->display.update_sprite_wm(plane, crtc, sprite_width,
 						   pixel_size, enable, scaled);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 7f63045..6e12b74 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -109,7 +109,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 
 	sprctl |= SP_ENABLE;
 
-	intel_update_sprite_watermarks(dev, pipe, src_w, pixel_size, true,
+	intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
 	/* Sizes are 0 based */
@@ -265,7 +265,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (IS_HASWELL(dev))
 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
 
-	intel_update_sprite_watermarks(dev, pipe, src_w, pixel_size, true,
+	intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
 	/* Sizes are 0 based */
@@ -339,7 +339,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 
 	dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
 
-	intel_update_sprite_watermarks(dev, pipe, 0, 0, false, false);
+	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
 
 	/* potentially re-enable LP watermarks */
 	if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
@@ -454,7 +454,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
 	dvscntr |= DVS_ENABLE;
 
-	intel_update_sprite_watermarks(dev, pipe, src_w, pixel_size, true,
+	intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
 	/* Sizes are 0 based */
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 28/35] drm/i915: Always call intel_update_sprite_watermarks() when disabling a plane
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (26 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 27/35] drm/i915: Pass plane and crtc to intel_update_sprite_watermarks ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 29/35] drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset ville.syrjala
                   ` (7 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

ILK and VLV codepaths didn't update sprite watermarks when disabling a
sprite. Make them do that.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_sprite.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 6e12b74..92c15d1 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -154,6 +154,8 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 	/* Activate double buffered register update */
 	I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
 	POSTING_READ(SPSURF(pipe, plane));
+
+	intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
 }
 
 static int
@@ -502,6 +504,8 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 	/* Flush double buffered register updates */
 	I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
 	POSTING_READ(DVSSURF(pipe));
+
+	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
 }
 
 static void
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 29/35] drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (27 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 28/35] drm/i915: Always call intel_update_sprite_watermarks() when disabling a plane ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  9:32   ` Chris Wilson
  2013-07-05  8:57 ` [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code ville.syrjala
                   ` (6 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Passing the appropriate crtc to intel_update_watermarks() should help
in avoiding needless work in the future.

Also make the call intel_update_watermarks() just once during the
modeset. Ideally it should happen independently when each plane gets
enabled/disabled, but for now it seems better to keep it in one place.
We can improve things when we get all the planes sorted out in a better
way.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |  2 +-
 drivers/gpu/drm/i915/intel_display.c | 23 +++++++------------
 drivers/gpu/drm/i915/intel_drv.h     |  2 +-
 drivers/gpu/drm/i915/intel_pm.c      | 43 +++++++++++++++++++++---------------
 drivers/gpu/drm/i915/intel_sprite.c  |  6 ++---
 5 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index eabd3d5..fd57bed 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -358,7 +358,7 @@ struct drm_i915_display_funcs {
 			  int target, int refclk,
 			  struct dpll *match_clock,
 			  struct dpll *best_clock);
-	void (*update_wm)(struct drm_device *dev);
+	void (*update_wm)(struct drm_crtc *crtc);
 	void (*update_sprite_wm)(struct drm_plane *plane,
 				 struct drm_crtc *crtc,
 				 uint32_t sprite_width, int pixel_size,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 76796b1..54216d1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3231,8 +3231,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
 	intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
 
-	intel_update_watermarks(dev);
-
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_enable)
 			encoder->pre_enable(encoder);
@@ -3255,6 +3253,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	 */
 	intel_crtc_load_lut(crtc);
 
+	intel_update_watermarks(crtc);
 	intel_enable_pipe(dev_priv, pipe,
 			  intel_crtc->config.has_pch_encoder);
 	intel_enable_plane(dev_priv, plane, pipe);
@@ -3341,8 +3340,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	if (intel_crtc->config.has_pch_encoder)
 		intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
 
-	intel_update_watermarks(dev);
-
 	if (intel_crtc->config.has_pch_encoder)
 		dev_priv->display.fdi_link_train(crtc);
 
@@ -3363,6 +3360,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_ddi_set_pipe_settings(crtc);
 	intel_ddi_enable_transcoder_func(crtc);
 
+	intel_update_watermarks(crtc);
 	intel_enable_pipe(dev_priv, pipe,
 			  intel_crtc->config.has_pch_encoder);
 	intel_enable_plane(dev_priv, plane, pipe);
@@ -3473,7 +3471,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	}
 
 	intel_crtc->active = false;
-	intel_update_watermarks(dev);
+	intel_update_watermarks(crtc);
 
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
@@ -3530,7 +3528,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	}
 
 	intel_crtc->active = false;
-	intel_update_watermarks(dev);
+	intel_update_watermarks(crtc);
 
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
@@ -3629,7 +3627,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 		return;
 
 	intel_crtc->active = true;
-	intel_update_watermarks(dev);
 
 	mutex_lock(&dev_priv->dpio_lock);
 
@@ -3651,6 +3648,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 
 	intel_crtc_load_lut(crtc);
 
+	intel_update_watermarks(crtc);
 	intel_enable_pipe(dev_priv, pipe, false);
 	intel_enable_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
@@ -3676,7 +3674,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 		return;
 
 	intel_crtc->active = true;
-	intel_update_watermarks(dev);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_enable)
@@ -3688,6 +3685,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
 	intel_crtc_load_lut(crtc);
 
+	intel_update_watermarks(crtc);
 	intel_enable_pipe(dev_priv, pipe, false);
 	intel_enable_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
@@ -3758,8 +3756,9 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	intel_disable_pll(dev_priv, pipe);
 
 	intel_crtc->active = false;
+	intel_update_watermarks(crtc);
+
 	intel_update_fbc(dev);
-	intel_update_watermarks(dev);
 }
 
 static void i9xx_crtc_off(struct drm_crtc *crtc)
@@ -4924,8 +4923,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 
 	ret = intel_pipe_set_base(crtc, x, y, fb);
 
-	intel_update_watermarks(dev);
-
 	return ret;
 }
 
@@ -5786,8 +5783,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 
 	ret = intel_pipe_set_base(crtc, x, y, fb);
 
-	intel_update_watermarks(dev);
-
 	return ret;
 }
 
@@ -5940,8 +5935,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 
 	ret = intel_pipe_set_base(crtc, x, y, fb);
 
-	intel_update_watermarks(dev);
-
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bd23fde..4afaeb2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -775,7 +775,7 @@ extern void hsw_fdi_link_train(struct drm_crtc *crtc);
 extern void intel_ddi_init(struct drm_device *dev, enum port port);
 
 /* For use by IVB LP watermark workaround in intel_sprite.c */
-extern void intel_update_watermarks(struct drm_device *dev);
+extern void intel_update_watermarks(struct drm_crtc *crtc);
 extern void intel_update_sprite_watermarks(struct drm_plane *plane,
 					   struct drm_crtc *crtc,
 					   uint32_t sprite_width, int pixel_size,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index fdf5898..c4e94bb 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1072,10 +1072,10 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
 	return enabled;
 }
 
-static void pineview_update_wm(struct drm_device *dev)
+static void pineview_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
 	const struct cxsr_latency *latency;
 	u32 reg;
 	unsigned long wm;
@@ -1350,8 +1350,9 @@ static void vlv_update_drain_latency(struct drm_device *dev)
 
 #define single_plane_enabled(mask) is_power_of_2(mask)
 
-static void valleyview_update_wm(struct drm_device *dev)
+static void valleyview_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	static const int sr_latency_ns = 12000;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
@@ -1409,8 +1410,9 @@ static void valleyview_update_wm(struct drm_device *dev)
 		   (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
 }
 
-static void g4x_update_wm(struct drm_device *dev)
+static void g4x_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	static const int sr_latency_ns = 12000;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
@@ -1461,10 +1463,10 @@ static void g4x_update_wm(struct drm_device *dev)
 		   (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
 }
 
-static void i965_update_wm(struct drm_device *dev)
+static void i965_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
 	int srwm = 1;
 	int cursor_sr = 16;
 
@@ -1526,8 +1528,9 @@ static void i965_update_wm(struct drm_device *dev)
 	I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
 }
 
-static void i9xx_update_wm(struct drm_device *dev)
+static void i9xx_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	const struct intel_watermark_params *wm_info;
 	uint32_t fwater_lo;
@@ -1535,7 +1538,7 @@ static void i9xx_update_wm(struct drm_device *dev)
 	int cwm, srwm = 1;
 	int fifo_size;
 	int planea_wm, planeb_wm;
-	struct drm_crtc *crtc, *enabled = NULL;
+	struct drm_crtc *enabled = NULL;
 
 	if (IS_I945GM(dev))
 		wm_info = &i945_wm_info;
@@ -1643,10 +1646,10 @@ static void i9xx_update_wm(struct drm_device *dev)
 	}
 }
 
-static void i830_update_wm(struct drm_device *dev)
+static void i830_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
 	uint32_t fwater_lo;
 	int planea_wm;
 
@@ -1773,8 +1776,9 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
 				   display, cursor);
 }
 
-static void ironlake_update_wm(struct drm_device *dev)
+static void ironlake_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int fbc_wm, plane_wm, cursor_wm;
 	unsigned int enabled;
@@ -1856,8 +1860,9 @@ static void ironlake_update_wm(struct drm_device *dev)
 	 */
 }
 
-static void sandybridge_update_wm(struct drm_device *dev)
+static void sandybridge_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
 	u32 val;
@@ -1958,8 +1963,9 @@ static void sandybridge_update_wm(struct drm_device *dev)
 		   cursor_wm);
 }
 
-static void ivybridge_update_wm(struct drm_device *dev)
+static void ivybridge_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
 	u32 val;
@@ -2793,8 +2799,9 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
 }
 
-static void haswell_update_wm(struct drm_device *dev)
+static void haswell_update_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
 	struct hsw_pipe_wm_parameters params[3];
@@ -2831,7 +2838,7 @@ static void haswell_update_sprite_wm(struct drm_plane *plane,
 	intel_plane->wm.horiz_pixels = sprite_width;
 	intel_plane->wm.bytes_per_pixel = pixel_size;
 
-	haswell_update_wm(plane->dev);
+	haswell_update_wm(crtc);
 }
 
 static bool
@@ -3028,12 +3035,12 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
  * We don't use the sprite, so we can ignore that.  And on Crestline we have
  * to set the non-SR watermarks to 8.
  */
-void intel_update_watermarks(struct drm_device *dev)
+void intel_update_watermarks(struct drm_crtc *crtc)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 
 	if (dev_priv->display.update_wm)
-		dev_priv->display.update_wm(dev);
+		dev_priv->display.update_wm(crtc);
 }
 
 void intel_update_sprite_watermarks(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 92c15d1..750c294 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -285,7 +285,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		dev_priv->sprite_scaling_enabled |= 1 << pipe;
 
 		if (!scaling_was_enabled) {
-			intel_update_watermarks(dev);
+			intel_update_watermarks(crtc);
 			intel_wait_for_vblank(dev, pipe);
 		}
 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
@@ -319,7 +319,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
 	/* potentially re-enable LP watermarks */
 	if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
-		intel_update_watermarks(dev);
+		intel_update_watermarks(crtc);
 }
 
 static void
@@ -345,7 +345,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 
 	/* potentially re-enable LP watermarks */
 	if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
-		intel_update_watermarks(dev);
+		intel_update_watermarks(crtc);
 }
 
 static int
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (28 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 29/35] drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  9:37   ` Chris Wilson
  2013-07-05 17:51   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 31/35] drm/i915: Move HSW linetime watermark handling to modeset code ville.syrjala
                   ` (5 subsequent siblings)
  35 siblings, 2 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

There is a major problem with the watermark registers; they're not
double buffered. So we need to make sure we update them at the correct
time when messing about with planes. The correct time is the beginning
of vblank.

So when we determine that the watermarks need to updated hand in hand
with the next vblank, we store the pre-computed watermarks under
intel_crtc, and when the vblank happens, we promote the pending
watermarks to active status.

on HSW when the watermarks for any pipe change, we must merge the
watermarks from all pipes so that we can determine the correct LP1+
watermark levels. For simplicity we follow the same codepaths for
pre-HSW hardware as well, but there all the LP1+ watermarks will be
disabled when multiple pipes are enabled. Once the watermarks are
merged we check them for validity, disabling any invalid levels.

Touching the watermark registers causes the hardware to re-evaluate the
watermarks, which expeds some power. So after merging the watermarks
we check which watermark registers actually need to be changed. And
finally we write the watermarks registers in the correct order.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  |   12 +
 drivers/gpu/drm/i915/i915_irq.c  |   12 +-
 drivers/gpu/drm/i915/i915_reg.h  |    2 +
 drivers/gpu/drm/i915/intel_drv.h |   22 +
 drivers/gpu/drm/i915/intel_pm.c  | 1546 ++++++++++++++++----------------------
 5 files changed, 686 insertions(+), 908 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fd57bed..446be9a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1198,6 +1198,7 @@ typedef struct drm_i915_private {
 
 	struct i915_suspend_saved_registers regfile;
 
+	/* per-device watermark state */
 	struct {
 		/* watermark latency values for primary */
 		uint16_t pri_latency[5];
@@ -1205,6 +1206,17 @@ typedef struct drm_i915_private {
 		uint16_t spr_latency[5];
 		/* watermark latency values for cursor */
 		uint16_t cur_latency[5];
+		/* protects all watermark state */
+		spinlock_t lock;
+		/* current state of FBC_WM */
+		bool fbc_wm_enabled;
+		/* current state of DDB partitioning */
+		enum intel_ddb_partitioning ddb_partitioning;
+		/*
+		 * LP1+ values currently programmed into the hardware
+		 * [0] = LP1, [1] = LP2, [2] = LP3
+		 */
+		struct intel_wm_level hw[3];
 	} wm;
 
 	/* Old dri1 support infrastructure, beware the dragons ya fools entering
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 4c1b1e3..ee5127f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1240,8 +1240,10 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
 			intel_opregion_asle_intr(dev);
 
 		for (i = 0; i < 3; i++) {
-			if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
+			if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i))) {
+				ilk_update_pipe_wm(dev, i);
 				drm_handle_vblank(dev, i);
+			}
 			if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
 				intel_prepare_page_flip(dev, i);
 				intel_finish_page_flip_plane(dev, i);
@@ -1343,11 +1345,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 	if (de_iir & DE_GSE)
 		intel_opregion_asle_intr(dev);
 
-	if (de_iir & DE_PIPEA_VBLANK)
+	if (de_iir & DE_PIPEA_VBLANK) {
+		ilk_update_pipe_wm(dev, 0);
 		drm_handle_vblank(dev, 0);
+	}
 
-	if (de_iir & DE_PIPEB_VBLANK)
+	if (de_iir & DE_PIPEB_VBLANK) {
+		ilk_update_pipe_wm(dev, 1);
 		drm_handle_vblank(dev, 1);
+	}
 
 	if (de_iir & DE_POISON)
 		DRM_ERROR("Poison interrupt\n");
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 9b51be8..e595f54 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3762,6 +3762,8 @@
 #define DISP_ARB_CTL	0x45000
 #define  DISP_TILE_SURFACE_SWIZZLING	(1<<13)
 #define  DISP_FBC_WM_DIS		(1<<15)
+#define DISP_ARB_CTL2	0x45004
+#define  DISP_DATA_PARTITION_5_6	(1<<6)
 #define GEN7_MSG_CTL	0x45010
 #define  WAIT_FOR_PCH_RESET_ACK		(1<<1)
 #define  WAIT_FOR_PCH_FLR_ACK		(1<<0)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4afaeb2..a5c15ab 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -292,6 +292,15 @@ struct intel_crtc_config {
 	bool ips_enabled;
 };
 
+struct intel_pipe_wm {
+	bool pipe_enabled;
+	bool sprites_enabled;
+	bool sprites_scaled;
+	bool fbc_wm_enabled;
+	uint32_t linetime;
+	struct intel_wm_level wm[5];
+};
+
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
@@ -332,6 +341,18 @@ struct intel_crtc {
 	/* Access to these should be protected by dev_priv->irq_lock. */
 	bool cpu_fifo_underrun_disabled;
 	bool pch_fifo_underrun_disabled;
+
+	/* per-pipe watermark state */
+	struct {
+		/* watermarks queued for next vblank */
+		struct intel_pipe_wm pending;
+		/* watermarks currently being used  */
+		struct intel_pipe_wm active;
+		/* LP0 values currently programmed into the hardware */
+		struct intel_wm_level hw;
+		/* indicates that 'pending' contains changed watermarks */
+		bool dirty;
+	} wm;
 };
 
 struct intel_plane_wm_parameters {
@@ -838,5 +859,6 @@ extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
 extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 						 enum transcoder pch_transcoder,
 						 bool enable);
+extern void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c4e94bb..7fd922dc 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -32,6 +32,11 @@
 #include <linux/module.h>
 #include <drm/i915_powerwell.h>
 
+static const char *yesno(int v)
+{
+	return v ? "yes" : "no";
+}
+
 #define FORCEWAKE_ACK_TIMEOUT_MS 2
 
 /* FBC, or Frame Buffer Compression, is a technique employed to compress the
@@ -1668,424 +1673,6 @@ static void i830_update_wm(struct drm_crtc *crtc)
 	I915_WRITE(FW_BLC, fwater_lo);
 }
 
-#define ILK_LP0_PLANE_LATENCY		700
-#define ILK_LP0_CURSOR_LATENCY		1300
-
-/*
- * Check the wm result.
- *
- * If any calculated watermark values is larger than the maximum value that
- * can be programmed into the associated watermark register, that watermark
- * must be disabled.
- */
-static bool ironlake_check_srwm(struct drm_device *dev, int level,
-				int fbc_wm, int display_wm, int cursor_wm,
-				const struct intel_watermark_params *display,
-				const struct intel_watermark_params *cursor)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	DRM_DEBUG_KMS("watermark %d: display plane %d, fbc lines %d,"
-		      " cursor %d\n", level, display_wm, fbc_wm, cursor_wm);
-
-	if (fbc_wm > SNB_FBC_MAX_SRWM) {
-		DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n",
-			      fbc_wm, SNB_FBC_MAX_SRWM, level);
-
-		/* fbc has it's own way to disable FBC WM */
-		I915_WRITE(DISP_ARB_CTL,
-			   I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS);
-		return false;
-	} else if (INTEL_INFO(dev)->gen >= 6) {
-		/* enable FBC WM (except on ILK, where it must remain off) */
-		I915_WRITE(DISP_ARB_CTL,
-			   I915_READ(DISP_ARB_CTL) & ~DISP_FBC_WM_DIS);
-	}
-
-	if (display_wm > display->max_wm) {
-		DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n",
-			      display_wm, SNB_DISPLAY_MAX_SRWM, level);
-		return false;
-	}
-
-	if (cursor_wm > cursor->max_wm) {
-		DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n",
-			      cursor_wm, SNB_CURSOR_MAX_SRWM, level);
-		return false;
-	}
-
-	if (!(fbc_wm || display_wm || cursor_wm)) {
-		DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level);
-		return false;
-	}
-
-	return true;
-}
-
-/*
- * Compute watermark values of WM[1-3],
- */
-static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
-				  int latency_ns,
-				  const struct intel_watermark_params *display,
-				  const struct intel_watermark_params *cursor,
-				  int *fbc_wm, int *display_wm, int *cursor_wm)
-{
-	struct drm_crtc *crtc;
-	unsigned long line_time_us;
-	int hdisplay, htotal, pixel_size, clock;
-	int line_count, line_size;
-	int small, large;
-	int entries;
-
-	if (!latency_ns) {
-		*fbc_wm = *display_wm = *cursor_wm = 0;
-		return false;
-	}
-
-	crtc = intel_get_crtc_for_plane(dev, plane);
-	hdisplay = crtc->mode.hdisplay;
-	htotal = crtc->mode.htotal;
-	clock = crtc->mode.clock;
-	pixel_size = crtc->fb->bits_per_pixel / 8;
-
-	line_time_us = (htotal * 1000) / clock;
-	line_count = (latency_ns / line_time_us + 1000) / 1000;
-	line_size = hdisplay * pixel_size;
-
-	/* Use the minimum of the small and large buffer method for primary */
-	small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
-	large = line_count * line_size;
-
-	entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
-	*display_wm = entries + display->guard_size;
-
-	/*
-	 * Spec says:
-	 * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2
-	 */
-	*fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2;
-
-	/* calculate the self-refresh watermark for display cursor */
-	entries = line_count * pixel_size * 64;
-	entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
-	*cursor_wm = entries + cursor->guard_size;
-
-	return ironlake_check_srwm(dev, level,
-				   *fbc_wm, *display_wm, *cursor_wm,
-				   display, cursor);
-}
-
-static void ironlake_update_wm(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int fbc_wm, plane_wm, cursor_wm;
-	unsigned int enabled;
-
-	enabled = 0;
-	if (g4x_compute_wm0(dev, PIPE_A,
-			    &ironlake_display_wm_info,
-			    ILK_LP0_PLANE_LATENCY,
-			    &ironlake_cursor_wm_info,
-			    ILK_LP0_CURSOR_LATENCY,
-			    &plane_wm, &cursor_wm)) {
-		I915_WRITE(WM0_PIPEA_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
-		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-			      " plane %d, " "cursor: %d\n",
-			      plane_wm, cursor_wm);
-		enabled |= 1 << PIPE_A;
-	}
-
-	if (g4x_compute_wm0(dev, PIPE_B,
-			    &ironlake_display_wm_info,
-			    ILK_LP0_PLANE_LATENCY,
-			    &ironlake_cursor_wm_info,
-			    ILK_LP0_CURSOR_LATENCY,
-			    &plane_wm, &cursor_wm)) {
-		I915_WRITE(WM0_PIPEB_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
-		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-			      " plane %d, cursor: %d\n",
-			      plane_wm, cursor_wm);
-		enabled |= 1 << PIPE_B;
-	}
-
-	/*
-	 * Calculate and update the self-refresh watermark only when one
-	 * display plane is used.
-	 */
-	I915_WRITE(WM3_LP_ILK, 0);
-	I915_WRITE(WM2_LP_ILK, 0);
-	I915_WRITE(WM1_LP_ILK, 0);
-
-	if (!single_plane_enabled(enabled))
-		return;
-	enabled = ffs(enabled) - 1;
-
-	/* WM1 */
-	if (!ironlake_compute_srwm(dev, 1, enabled,
-				   ILK_READ_WM1_LATENCY() * 500,
-				   &ironlake_display_srwm_info,
-				   &ironlake_cursor_srwm_info,
-				   &fbc_wm, &plane_wm, &cursor_wm))
-		return;
-
-	I915_WRITE(WM1_LP_ILK,
-		   WM1_LP_SR_EN |
-		   (ILK_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-		   (fbc_wm << WM1_LP_FBC_SHIFT) |
-		   (plane_wm << WM1_LP_SR_SHIFT) |
-		   cursor_wm);
-
-	/* WM2 */
-	if (!ironlake_compute_srwm(dev, 2, enabled,
-				   ILK_READ_WM2_LATENCY() * 500,
-				   &ironlake_display_srwm_info,
-				   &ironlake_cursor_srwm_info,
-				   &fbc_wm, &plane_wm, &cursor_wm))
-		return;
-
-	I915_WRITE(WM2_LP_ILK,
-		   WM2_LP_EN |
-		   (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-		   (fbc_wm << WM1_LP_FBC_SHIFT) |
-		   (plane_wm << WM1_LP_SR_SHIFT) |
-		   cursor_wm);
-
-	/*
-	 * WM3 is unsupported on ILK, probably because we don't have latency
-	 * data for that power state
-	 */
-}
-
-static void sandybridge_update_wm(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
-	u32 val;
-	int fbc_wm, plane_wm, cursor_wm;
-	unsigned int enabled;
-
-	enabled = 0;
-	if (g4x_compute_wm0(dev, PIPE_A,
-			    &sandybridge_display_wm_info, latency,
-			    &sandybridge_cursor_wm_info, latency,
-			    &plane_wm, &cursor_wm)) {
-		val = I915_READ(WM0_PIPEA_ILK);
-		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-		I915_WRITE(WM0_PIPEA_ILK, val |
-			   ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-			      " plane %d, " "cursor: %d\n",
-			      plane_wm, cursor_wm);
-		enabled |= 1 << PIPE_A;
-	}
-
-	if (g4x_compute_wm0(dev, PIPE_B,
-			    &sandybridge_display_wm_info, latency,
-			    &sandybridge_cursor_wm_info, latency,
-			    &plane_wm, &cursor_wm)) {
-		val = I915_READ(WM0_PIPEB_ILK);
-		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-		I915_WRITE(WM0_PIPEB_ILK, val |
-			   ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-			      " plane %d, cursor: %d\n",
-			      plane_wm, cursor_wm);
-		enabled |= 1 << PIPE_B;
-	}
-
-	/*
-	 * Calculate and update the self-refresh watermark only when one
-	 * display plane is used.
-	 *
-	 * SNB support 3 levels of watermark.
-	 *
-	 * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
-	 * and disabled in the descending order
-	 *
-	 */
-	I915_WRITE(WM3_LP_ILK, 0);
-	I915_WRITE(WM2_LP_ILK, 0);
-	I915_WRITE(WM1_LP_ILK, 0);
-
-	if (!single_plane_enabled(enabled) ||
-	    dev_priv->sprite_scaling_enabled)
-		return;
-	enabled = ffs(enabled) - 1;
-
-	/* WM1 */
-	if (!ironlake_compute_srwm(dev, 1, enabled,
-				   SNB_READ_WM1_LATENCY() * 500,
-				   &sandybridge_display_srwm_info,
-				   &sandybridge_cursor_srwm_info,
-				   &fbc_wm, &plane_wm, &cursor_wm))
-		return;
-
-	I915_WRITE(WM1_LP_ILK,
-		   WM1_LP_SR_EN |
-		   (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-		   (fbc_wm << WM1_LP_FBC_SHIFT) |
-		   (plane_wm << WM1_LP_SR_SHIFT) |
-		   cursor_wm);
-
-	/* WM2 */
-	if (!ironlake_compute_srwm(dev, 2, enabled,
-				   SNB_READ_WM2_LATENCY() * 500,
-				   &sandybridge_display_srwm_info,
-				   &sandybridge_cursor_srwm_info,
-				   &fbc_wm, &plane_wm, &cursor_wm))
-		return;
-
-	I915_WRITE(WM2_LP_ILK,
-		   WM2_LP_EN |
-		   (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-		   (fbc_wm << WM1_LP_FBC_SHIFT) |
-		   (plane_wm << WM1_LP_SR_SHIFT) |
-		   cursor_wm);
-
-	/* WM3 */
-	if (!ironlake_compute_srwm(dev, 3, enabled,
-				   SNB_READ_WM3_LATENCY() * 500,
-				   &sandybridge_display_srwm_info,
-				   &sandybridge_cursor_srwm_info,
-				   &fbc_wm, &plane_wm, &cursor_wm))
-		return;
-
-	I915_WRITE(WM3_LP_ILK,
-		   WM3_LP_EN |
-		   (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-		   (fbc_wm << WM1_LP_FBC_SHIFT) |
-		   (plane_wm << WM1_LP_SR_SHIFT) |
-		   cursor_wm);
-}
-
-static void ivybridge_update_wm(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
-	u32 val;
-	int fbc_wm, plane_wm, cursor_wm;
-	int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm;
-	unsigned int enabled;
-
-	enabled = 0;
-	if (g4x_compute_wm0(dev, PIPE_A,
-			    &sandybridge_display_wm_info, latency,
-			    &sandybridge_cursor_wm_info, latency,
-			    &plane_wm, &cursor_wm)) {
-		val = I915_READ(WM0_PIPEA_ILK);
-		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-		I915_WRITE(WM0_PIPEA_ILK, val |
-			   ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-			      " plane %d, " "cursor: %d\n",
-			      plane_wm, cursor_wm);
-		enabled |= 1 << PIPE_A;
-	}
-
-	if (g4x_compute_wm0(dev, PIPE_B,
-			    &sandybridge_display_wm_info, latency,
-			    &sandybridge_cursor_wm_info, latency,
-			    &plane_wm, &cursor_wm)) {
-		val = I915_READ(WM0_PIPEB_ILK);
-		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-		I915_WRITE(WM0_PIPEB_ILK, val |
-			   ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-			      " plane %d, cursor: %d\n",
-			      plane_wm, cursor_wm);
-		enabled |= 1 << PIPE_B;
-	}
-
-	if (g4x_compute_wm0(dev, PIPE_C,
-			    &sandybridge_display_wm_info, latency,
-			    &sandybridge_cursor_wm_info, latency,
-			    &plane_wm, &cursor_wm)) {
-		val = I915_READ(WM0_PIPEC_IVB);
-		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-		I915_WRITE(WM0_PIPEC_IVB, val |
-			   ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-		DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
-			      " plane %d, cursor: %d\n",
-			      plane_wm, cursor_wm);
-		enabled |= 1 << PIPE_C;
-	}
-
-	/*
-	 * Calculate and update the self-refresh watermark only when one
-	 * display plane is used.
-	 *
-	 * SNB support 3 levels of watermark.
-	 *
-	 * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
-	 * and disabled in the descending order
-	 *
-	 */
-	I915_WRITE(WM3_LP_ILK, 0);
-	I915_WRITE(WM2_LP_ILK, 0);
-	I915_WRITE(WM1_LP_ILK, 0);
-
-	if (!single_plane_enabled(enabled) ||
-	    dev_priv->sprite_scaling_enabled)
-		return;
-	enabled = ffs(enabled) - 1;
-
-	/* WM1 */
-	if (!ironlake_compute_srwm(dev, 1, enabled,
-				   SNB_READ_WM1_LATENCY() * 500,
-				   &sandybridge_display_srwm_info,
-				   &sandybridge_cursor_srwm_info,
-				   &fbc_wm, &plane_wm, &cursor_wm))
-		return;
-
-	I915_WRITE(WM1_LP_ILK,
-		   WM1_LP_SR_EN |
-		   (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-		   (fbc_wm << WM1_LP_FBC_SHIFT) |
-		   (plane_wm << WM1_LP_SR_SHIFT) |
-		   cursor_wm);
-
-	/* WM2 */
-	if (!ironlake_compute_srwm(dev, 2, enabled,
-				   SNB_READ_WM2_LATENCY() * 500,
-				   &sandybridge_display_srwm_info,
-				   &sandybridge_cursor_srwm_info,
-				   &fbc_wm, &plane_wm, &cursor_wm))
-		return;
-
-	I915_WRITE(WM2_LP_ILK,
-		   WM2_LP_EN |
-		   (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-		   (fbc_wm << WM1_LP_FBC_SHIFT) |
-		   (plane_wm << WM1_LP_SR_SHIFT) |
-		   cursor_wm);
-
-	/* WM3, note we have to correct the cursor latency */
-	if (!ironlake_compute_srwm(dev, 3, enabled,
-				   SNB_READ_WM3_LATENCY() * 500,
-				   &sandybridge_display_srwm_info,
-				   &sandybridge_cursor_srwm_info,
-				   &fbc_wm, &plane_wm, &ignore_cursor_wm) ||
-	    !ironlake_compute_srwm(dev, 3, enabled,
-				   2 * SNB_READ_WM3_LATENCY() * 500,
-				   &sandybridge_display_srwm_info,
-				   &sandybridge_cursor_srwm_info,
-				   &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm))
-		return;
-
-	I915_WRITE(WM3_LP_ILK,
-		   WM3_LP_EN |
-		   (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-		   (fbc_wm << WM1_LP_FBC_SHIFT) |
-		   (plane_wm << WM1_LP_SR_SHIFT) |
-		   cursor_wm);
-}
-
 static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
 				    struct drm_crtc *crtc)
 {
@@ -2168,14 +1755,6 @@ struct hsw_wm_maximums {
 	uint16_t fbc;
 };
 
-struct hsw_wm_values {
-	uint32_t wm_pipe[3];
-	uint32_t wm_lp[3];
-	uint32_t wm_lp_spr[3];
-	uint32_t wm_linetime[3];
-	bool enable_fbc_wm;
-};
-
 /* used in computing the new watermarks state */
 struct intel_wm_config {
 	unsigned int pipes_active;
@@ -2351,6 +1930,16 @@ static void ilk_wm_max(struct drm_device *dev,
 	max->fbc = ilk_fbc_wm_max();
 }
 
+/*
+ * We use memcmp() to determine if watermarks need updating,
+ * so keeping all disabled watermark levels consistently
+ * zeroed avoids false positives.
+ */
+static void ilk_disable_wm_level(struct intel_wm_level *wm)
+{
+	memset(wm, 0, sizeof(*wm));
+}
+
 static bool ilk_check_wm(int level,
 			 const struct hsw_wm_maximums *max,
 			 struct intel_wm_level *result)
@@ -2381,6 +1970,9 @@ static bool ilk_check_wm(int level,
 
 	DRM_DEBUG_KMS("WM%d: %sabled\n", level, result->enable ? "en" : "dis");
 
+	if (!result->enable)
+		ilk_disable_wm_level(result);
+
 	return ret;
 }
 
@@ -2406,52 +1998,603 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
 	result->enable = true;
 }
 
-static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
-			      int level, struct hsw_wm_maximums *max,
-			      struct hsw_pipe_wm_parameters *params,
-			      struct intel_wm_level *result)
-{
-	enum pipe pipe;
-	struct intel_wm_level res[3];
-
-	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++)
-		ilk_compute_wm_level(dev_priv, level, &params[pipe], &res[pipe]);
-
-	result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val);
-	result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val);
-	result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val);
-	result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val);
-	result->enable = true;
-
-	return ilk_check_wm(level, max, result);
-}
-
-static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
-				    enum pipe pipe,
-				    struct hsw_pipe_wm_parameters *params)
-{
-	uint32_t pri_val, cur_val, spr_val;
-	uint16_t pri_latency = dev_priv->wm.pri_latency[0];
-	uint16_t spr_latency = dev_priv->wm.spr_latency[0];
-	uint16_t cur_latency = dev_priv->wm.cur_latency[0];
-
-	pri_val = ilk_compute_pri_wm(params, pri_latency, 0);
-	spr_val = ilk_compute_spr_wm(params, spr_latency);
-	cur_val = ilk_compute_cur_wm(params, cur_latency);
-
-	WARN(pri_val > 127,
-	     "Primary WM error, mode not supported for pipe %c\n",
-	     pipe_name(pipe));
-	WARN(spr_val > 127,
-	     "Sprite WM error, mode not supported for pipe %c\n",
-	     pipe_name(pipe));
-	WARN(cur_val > 63,
-	     "Cursor WM error, mode not supported for pipe %c\n",
-	     pipe_name(pipe));
-
-	return (pri_val << WM0_PIPE_PLANE_SHIFT) |
-	       (spr_val << WM0_PIPE_SPRITE_SHIFT) |
-	       cur_val;
+/* The value we need to program into the WM_LPx latency field */
+static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev))
+		return 2 * level;
+	else
+		return dev_priv->wm.pri_latency[level];
+}
+
+/*
+ * Merge the watermarks from all active pipes for a specific level.
+ */
+static void ilk_merge_wm_level(struct drm_device *dev,
+			       int level,
+			       struct intel_wm_level *ret_wm)
+{
+	struct intel_crtc *intel_crtc;
+
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
+		const struct intel_pipe_wm *pipe_wm = &intel_crtc->wm.active;
+		const struct intel_wm_level *wm = &pipe_wm->wm[level];
+
+		if (!pipe_wm->pipe_enabled)
+			continue;
+
+		if (!wm->enable)
+			break;
+
+		ret_wm->enable = true;
+		ret_wm->pri_val = max(ret_wm->pri_val, wm->pri_val);
+		ret_wm->spr_val = max(ret_wm->spr_val, wm->spr_val);
+		ret_wm->cur_val = max(ret_wm->cur_val, wm->cur_val);
+		ret_wm->fbc_val = max(ret_wm->fbc_val, wm->fbc_val);
+	}
+}
+
+/*
+ * Merge all low power watermarks for all active pipes.
+ */
+static void ilk_wm_merge(struct drm_device *dev,
+			 struct intel_wm_config *config,
+			 struct intel_pipe_wm *merged)
+{
+	int level;
+
+	/* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
+	if (config->pipes_active > 1 &&
+	    (INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)))
+		return;
+
+	/* ILK: FBC WM must remain disabled */
+	merged->fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6;
+
+	/* merge each level */
+	for (level = 1; level <= 4; level++) {
+		struct intel_wm_level *wm = &merged->wm[level];
+
+		ilk_merge_wm_level(dev, level, wm);
+	}
+}
+
+static void ilk_wm_limit(struct drm_device *dev,
+			 const struct intel_wm_config *config,
+			 const struct hsw_wm_maximums *max,
+			 struct intel_pipe_wm *merged)
+{
+	int level;
+
+	for (level = 1; level <= 4; level++) {
+		struct intel_wm_level *wm = &merged->wm[level];
+
+		if (!ilk_check_wm(level, max, wm))
+			break;
+
+		/*
+		 * If FBC WM is exceeded, disable just FBC WM
+		 * instead if the whole level.
+		 */
+		if (wm->fbc_val > max->fbc)
+			merged->fbc_wm_enabled = false;
+	}
+
+	if (merged->fbc_wm_enabled)
+		return;
+
+	/* Make sure we don't write garbage to the registers, */
+	for (level = 1; level <= 4; level++) {
+		struct intel_wm_level *wm = &merged->wm[level];
+
+		wm->fbc_val = 0;
+	}
+
+	/*
+	 * LP2+ watermarks must be disabled when FBC watermark is disabled on ILK
+	 * In practice this is always happens since we always disable FBC WM on ILK.
+	 */
+	if (INTEL_INFO(dev)->gen == 5 && intel_fbc_enabled(dev)) {
+		for (level = 2; level <= 4; level++) {
+			struct intel_wm_level *wm = &merged->wm[level];
+
+			ilk_disable_wm_level(wm);
+		}
+	}
+}
+
+static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *merged)
+{
+	/* LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4  */
+	return wm_lp + (wm_lp >= 2 && merged->wm[4].enable);
+}
+
+/* dirty bits used to track which watermarks need changes */
+#define WM_DIRTY_PIPE(pipe) (1 << (pipe))
+#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp)))
+#define WM_DIRTY_FBC (1 << 24)
+#define WM_DIRTY_DDB (1 << 25)
+
+/* Determine which watermarks registers need reprogramming. */
+static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
+					 const struct intel_wm_config *config,
+					 enum intel_ddb_partitioning ddb_partitioning,
+					 const struct intel_pipe_wm *merged)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc;
+	unsigned int dirty = 0;
+	int wm_lp;
+
+	/* Do LP0 watermarks need updates? */
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
+		const struct intel_wm_level *wm = &intel_crtc->wm.active.wm[0];
+
+		if (memcmp(&intel_crtc->wm.hw, wm, sizeof(*wm)))
+			dirty |= WM_DIRTY_PIPE(intel_crtc->pipe);
+	}
+
+	if (config->fbc_wm_enabled != dev_priv->wm.fbc_wm_enabled)
+		dirty |= WM_DIRTY_FBC;
+
+	if (ddb_partitioning != dev_priv->wm.ddb_partitioning)
+		dirty |= WM_DIRTY_DDB;
+
+	/* Need to disable LP1+ watermarks when changing DDB/FBC WM */
+	if (dirty & (WM_DIRTY_FBC | WM_DIRTY_DDB)) {
+		dirty |= WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3);
+
+		/* LP1+ watermarks already deemed dirty, no need to continue */
+		return dirty;
+	}
+
+	/* Find the lowest numbered LP1+ watermark in need of an update... */
+	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
+		int level = ilk_wm_lp_to_level(wm_lp, merged);
+		const struct intel_wm_level *wm = &merged->wm[level];
+
+		if (memcmp(&dev_priv->wm.hw[wm_lp - 1], wm, sizeof(*wm)))
+			break;
+	}
+
+	/* ...and mark it and all higher numbered LP1+ watermarks as dirty */
+	for (; wm_lp <= 3; wm_lp++)
+		dirty |= WM_DIRTY_LP(wm_lp);
+
+	return dirty;
+}
+
+/* Disable LP1+ watermarks */
+static void ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
+			      unsigned int dirty)
+{
+	int wm_lp;
+
+	for (wm_lp = 3; wm_lp >= 1; wm_lp--) {
+		static const unsigned int ilk_wm_lp_reg[] = {
+			[1] = WM1_LP_ILK,
+			[2] = WM2_LP_ILK,
+			[3] = WM3_LP_ILK,
+		};
+		struct intel_wm_level *hw = &dev_priv->wm.hw[wm_lp - 1];
+
+		if (!(dirty & WM_DIRTY_LP(wm_lp))) {
+			/* all lower dirty bits must be set when a higher bit is set */
+			WARN_ON(wm_lp > 1 && dirty & WM_DIRTY_LP(wm_lp - 1));
+			WARN_ON(wm_lp > 2 && dirty & WM_DIRTY_LP(wm_lp - 2));
+			break;
+		}
+
+		/* This LP watermark already disabled? */
+		if (!hw->enable)
+			continue;
+
+		DRM_DEBUG_KMS("disabling LP%d watermark\n", wm_lp);
+
+		/*
+		 * Simply writing 0 to the register in the middle of the frame
+		 * can cause immediate underruns on ILK. Instead we must clear
+		 * only the enable bit. I assume the hardware will take a while
+		 * to get out of low power mode, during which time it still
+		 * consults the watermarks levels.
+		 */
+		I915_WRITE(ilk_wm_lp_reg[wm_lp],
+			   I915_READ(ilk_wm_lp_reg[wm_lp]) & ~WM1_LP_SR_EN);
+
+		/* ILK/SNB have a separate enable bit for sprite LP1 watermark */
+		if (hw->spr_val && INTEL_INFO(dev_priv->dev)->gen <= 6) {
+			WARN_ON(wm_lp != 1);
+			I915_WRITE(WM1S_LP_ILK, I915_READ(WM1S_LP_ILK) & ~WM1S_LP_EN);
+		}
+
+		ilk_disable_wm_level(hw);
+	}
+}
+
+struct intel_pipe_wm *ivb_find_best_wm(struct intel_pipe_wm *r1,
+				       struct intel_pipe_wm *r2)
+{
+	int level, level1 = 0, level2 = 0;
+
+	for (level = 1; level <= 4; level++) {
+		if (r1->wm[level].enable)
+			level1 = level;
+		if (r2->wm[level].enable)
+			level2 = level;
+	}
+
+	if (level1 == level2) {
+		if (r2->fbc_wm_enabled && !r1->fbc_wm_enabled)
+			return r2;
+		else
+			return r1;
+	} else if (level1 > level2) {
+		return r1;
+	} else {
+		return r2;
+	}
+}
+
+/* Program the watermark registers */
+static void ilk_program_watermarks(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct intel_pipe_wm merged_1_2 = {}, merged_5_6 = {}, *merged;
+	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
+	int wm_lp;
+	unsigned int dirty;
+	struct intel_wm_config config = {};
+	struct intel_crtc *intel_crtc;
+	enum intel_ddb_partitioning ddb_partitioning;
+
+	/* ILK: FBC WM must remain disabled */
+	config.fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6 && intel_fbc_enabled(dev);
+
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
+		const struct intel_pipe_wm *wm = &intel_crtc->wm.active;
+
+		if (!wm->pipe_enabled)
+			continue;
+
+		config.sprites_enabled |= wm->sprites_enabled;
+		config.sprites_scaled |= wm->sprites_scaled;
+		config.pipes_active++;
+	}
+
+	ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &lp_max_1_2);
+
+	ilk_wm_merge(dev, &config, &merged_1_2);
+
+	/* 5/6 DDB partitioning only in single pipe config on IVB+ */
+	if (INTEL_INFO(dev)->gen >= 7 && config.pipes_active <= 1) {
+		ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &lp_max_5_6);
+
+		merged_5_6 = merged_1_2;
+
+		ilk_wm_limit(dev, &config, &lp_max_1_2, &merged_1_2);
+		ilk_wm_limit(dev, &config, &lp_max_5_6, &merged_5_6);
+
+		merged = ivb_find_best_wm(&merged_1_2, &merged_5_6);
+	} else {
+		ilk_wm_limit(dev, &config, &lp_max_1_2, &merged_1_2);
+		merged = &merged_1_2;
+	}
+
+	ddb_partitioning = merged == &merged_1_2 ?
+		INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
+
+	DRM_DEBUG_KMS("WM: pipes  active=%u, sprites enabled=%s, "
+		      "sprites scaled=%s, FBC WM enabled=%s, "
+		      "DDB partitioning=%s\n",
+		      config.pipes_active,
+		      yesno(config.sprites_enabled),
+		      yesno(config.sprites_scaled),
+		      yesno(config.fbc_wm_enabled),
+		      ddb_partitioning == INTEL_DDB_PART_1_2 ? "1/2" : "5/6");
+
+	dirty = ilk_compute_wm_dirty(dev, &config, ddb_partitioning, merged);
+	if (!dirty) {
+		DRM_DEBUG_KMS("WM: all clean\n");
+		return;
+	}
+
+	DRM_DEBUG_KMS("WM: dirty %s%s%s%s%s%s%s%s\n",
+		      dirty & WM_DIRTY_DDB ? "DDB," : "",
+		      dirty & WM_DIRTY_FBC ? "FBC," : "",
+		      dirty & WM_DIRTY_LP(3) ? "LP3," : "",
+		      dirty & WM_DIRTY_LP(2) ? "LP2," : "",
+		      dirty & WM_DIRTY_LP(1) ? "LP1," : "",
+		      dirty & WM_DIRTY_PIPE(PIPE_A) ? "LP0(A)," : "",
+		      dirty & WM_DIRTY_PIPE(PIPE_B) ? "LP0(B)," : "",
+		      dirty & WM_DIRTY_PIPE(PIPE_C) ? "LP0(C)," : "");
+
+	/*
+	 * LP1+ watermarks need to be disabled prior to
+	 * changing DDB partitioning, FBC watermark disable,
+	 * or lower numbered LP1+ watermarks. "dirty" knows
+	 * which watermarks need disabling.
+	 */
+	ilk_disable_lp_wm(dev_priv, dirty);
+
+	/* program LP0 watermarks */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		static const unsigned int ilk_wm0_pipe_reg[] = {
+			[PIPE_A] = WM0_PIPEA_ILK,
+			[PIPE_B] = WM0_PIPEB_ILK,
+			[PIPE_C] = WM0_PIPEC_IVB,
+		};
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+		const struct intel_pipe_wm *pipe_wm = &intel_crtc->wm.active;
+		const struct intel_wm_level *wm = &pipe_wm->wm[0];
+
+		if (!(dirty & WM_DIRTY_PIPE(intel_crtc->pipe)))
+			continue;
+
+		DRM_DEBUG_KMS("Pipe %c LP0: pri=%u, spr=%u, cur=%u\n",
+			      pipe_name(intel_crtc->pipe),
+			      wm->pri_val, wm->spr_val, wm->cur_val);
+
+		I915_WRITE(ilk_wm0_pipe_reg[intel_crtc->pipe],
+			   wm->pri_val << WM0_PIPE_PLANE_SHIFT |
+			   wm->spr_val << WM0_PIPE_SPRITE_SHIFT |
+			   wm->cur_val);
+
+		if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev))
+			I915_WRITE(PIPE_WM_LINETIME(intel_crtc->pipe),
+				   pipe_wm->linetime);
+
+		intel_crtc->wm.hw = *wm;
+	}
+
+	/* configure FBC watermark */
+	if (dirty & WM_DIRTY_FBC) {
+		uint32_t tmp = I915_READ(DISP_ARB_CTL);
+
+		DRM_DEBUG_KMS("WM: FBC watermark = %s\n", yesno(config.fbc_wm_enabled));
+
+		if (config.fbc_wm_enabled)
+			tmp &= ~DISP_FBC_WM_DIS;
+		else
+			tmp |= DISP_FBC_WM_DIS;
+
+		I915_WRITE(DISP_ARB_CTL, tmp);
+
+		dev_priv->wm.fbc_wm_enabled = config.fbc_wm_enabled;
+	}
+
+	/* configure DDB partitioning */
+	if (dirty & WM_DIRTY_DDB) {
+		DRM_DEBUG_KMS("WM: DDB partitioning = %s\n",
+			      ddb_partitioning == INTEL_DDB_PART_1_2 ? "1/2" : "5/6");
+
+		if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev)) {
+			uint32_t tmp = I915_READ(WM_MISC);
+
+			if (ddb_partitioning == INTEL_DDB_PART_5_6)
+				tmp |= WM_MISC_DATA_PARTITION_5_6;
+			else
+				tmp &= ~WM_MISC_DATA_PARTITION_5_6;
+
+			I915_WRITE(DISP_ARB_CTL, tmp);
+		} else {
+			uint32_t tmp = I915_READ(DISP_ARB_CTL2);
+
+			if (ddb_partitioning == INTEL_DDB_PART_5_6)
+				tmp |= DISP_DATA_PARTITION_5_6;
+			else
+				tmp &= ~DISP_DATA_PARTITION_5_6;
+
+			I915_WRITE(DISP_ARB_CTL2, tmp);
+		}
+
+		dev_priv->wm.ddb_partitioning = ddb_partitioning;
+	}
+
+	/* program LP1+ watermarks */
+	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
+		static const unsigned int wm_lp_reg[] = {
+			[1] = WM1_LP_ILK,
+			[2] = WM2_LP_ILK,
+			[3] = WM3_LP_ILK,
+		};
+		static const unsigned int wm_spr_lp_reg[] = {
+			[1] = WM1S_LP_ILK,
+			[2] = WM2S_LP_IVB,
+			[3] = WM3S_LP_IVB,
+		};
+		int level = ilk_wm_lp_to_level(wm_lp, merged);
+		const struct intel_wm_level *wm = &merged->wm[level];
+
+		if (!wm->enable)
+			break;
+
+		if (!(dirty & WM_DIRTY_LP(wm_lp)))
+			continue;
+
+		DRM_DEBUG_KMS("LP%d (level %d): pri=%u, spr=%u, cur=%u, fbc=%u, latency=%u\n",
+			      wm_lp, level, wm->pri_val, wm->spr_val,
+			      wm->cur_val, wm->fbc_val, ilk_wm_lp_latency(dev, level));
+
+		if (wm->spr_val) {
+			if (INTEL_INFO(dev)->gen <= 6) {
+				WARN_ON(wm_lp != 1);
+				I915_WRITE(WM1S_LP_ILK, WM1S_LP_EN | wm->spr_val);
+			} else {
+				I915_WRITE(wm_spr_lp_reg[wm_lp], wm->spr_val);
+			}
+		}
+
+		I915_WRITE(wm_lp_reg[wm_lp], WM1_LP_SR_EN |
+			   ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT |
+			   wm->fbc_val << WM1_LP_FBC_SHIFT |
+			   wm->pri_val << WM1_LP_SR_SHIFT |
+			   wm->cur_val);
+
+		dev_priv->wm.hw[wm_lp - 1] = *wm;
+	}
+}
+
+static uint32_t
+hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc);
+
+static int ilk_max_wm_level(const struct drm_device *dev,
+			    const struct intel_pipe_wm *pipe_wm)
+{
+	/* HSW: LP1+ watermarks allowed even with multiple pipes */
+	if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev)) {
+		WARN_ON(pipe_wm->sprites_scaled);
+		return 4;
+	}
+
+	/* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
+	if (pipe_wm->sprites_scaled)
+		return 0;
+
+	/* ILK/SNB: LP2+ watermarks only w/o sprites */
+	if (INTEL_INFO(dev)->gen <= 6 && pipe_wm->sprites_enabled)
+		return 1;
+
+	return 3;
+}
+
+/* Compute new watermarks for the pipe */
+static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
+				  struct intel_pipe_wm *pipe_wm)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct hsw_wm_maximums max;
+	struct drm_plane *plane;
+	struct hsw_pipe_wm_parameters p = {};
+	struct intel_wm_config config = {};
+	int level, max_level;
+
+	p.active = intel_crtc_active(crtc);
+
+	if (p.active) {
+		p.pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
+		p.pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
+
+		/* TODO: for now, assume primary and cursor planes are always enabled. */
+		p.pri.enabled = true;
+		p.pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
+		p.pri.horiz_pixels = intel_crtc->config.requested_mode.hdisplay;
+
+		p.cur.enabled = true;
+		p.cur.bytes_per_pixel = 4;
+		p.cur.horiz_pixels = 64;
+
+		config.pipes_active = 1;
+	}
+
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+		struct intel_plane *intel_plane = to_intel_plane(plane);
+
+		if (intel_plane->pipe != intel_crtc->pipe)
+			continue;
+
+		p.spr = intel_plane->wm;
+
+		config.sprites_enabled |= p.spr.enabled;
+		config.sprites_scaled |= p.spr.scaled;
+	}
+
+	pipe_wm->pipe_enabled = p.active;
+	pipe_wm->sprites_enabled = config.sprites_enabled;
+	pipe_wm->sprites_scaled = config.sprites_scaled;
+
+	max_level = ilk_max_wm_level(dev, pipe_wm);
+
+	for (level = 0; level <= max_level; level++)
+		ilk_compute_wm_level(dev_priv, level, &p, &pipe_wm->wm[level]);
+
+	if (IS_HASWELL(dev))
+		pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
+
+	ilk_wm_max(dev, 0, &config, false, &max);
+
+	/* At least LP0 must be valid */
+	return ilk_check_wm(0, &max, &pipe_wm->wm[0]);
+}
+
+/* Prepare the pipe to update the its watermarks on the next vblank */
+static void intel_setup_pipe_wm(struct intel_crtc *intel_crtc,
+				const struct intel_pipe_wm *pipe_wm)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = intel_crtc->pipe;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->wm.lock, flags);
+
+	/* do the watermarks actually need changing? */
+	if (!memcmp(&intel_crtc->wm.pending, pipe_wm, sizeof(*pipe_wm)))
+		goto out;
+
+	/*
+	 * We might already have a pending watermark update, in
+	 * which case we shouldn't grab another vblank reference.
+	 */
+	if (!intel_crtc->wm.dirty && drm_vblank_get(dev, pipe)) {
+		if (intel_crtc->active)
+			DRM_ERROR("can't setup watermarks for pipe %c\n", pipe_name(pipe));
+		/* copy the new stuff over anyway. */
+		intel_crtc->wm.pending = *pipe_wm;
+		goto out;
+	}
+
+	/*
+	 * When going from no-scaling to scaling, disable LP1+
+	 * watermarks ahead of time.
+	 *
+	 * WaCxSRDisabledForSpriteScaling:ivb
+	 */
+	/*
+	 * FIXME is this sufficient of do we need extra vbl waits?
+	 * Something like this is needed on IVB. Do we need this on ILK/SNB too?
+	 */
+	if (!intel_crtc->wm.active.sprites_scaled && pipe_wm->sprites_scaled) {
+		DRM_DEBUG_KMS("going to enable scaling, disabling LP1+ watermarks\n");
+		ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP(1) |
+				  WM_DIRTY_LP(2) | WM_DIRTY_LP(3));
+	}
+
+	intel_crtc->wm.pending = *pipe_wm;
+	intel_crtc->wm.dirty = true;
+	DRM_DEBUG_KMS("pipe %c new watermarks are pending\n", pipe_name(pipe));
+
+ out:
+	spin_unlock_irqrestore(&dev_priv->wm.lock, flags);
+}
+
+/* Call from vblank irq */
+void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->wm.lock, flags);
+
+	if (intel_crtc->wm.dirty) {
+		DRM_DEBUG_KMS("pipe %c vblank, programming new watermarks\n",
+			      pipe_name(pipe));
+
+		drm_vblank_put(dev, pipe);
+
+		intel_crtc->wm.active = intel_crtc->wm.pending;
+		intel_crtc->wm.dirty = false;
+
+		ilk_program_watermarks(dev);
+	}
+
+	spin_unlock_irqrestore(&dev_priv->wm.lock, flags);
 }
 
 static uint32_t
@@ -2565,271 +2708,24 @@ static void intel_setup_wm_latency(struct drm_device *dev)
 	intel_print_wm_latency(dev, dev_priv->wm.cur_latency);
 }
 
-static void hsw_compute_wm_parameters(struct drm_device *dev,
-				      struct hsw_pipe_wm_parameters *params,
-				      struct hsw_wm_maximums *lp_max_1_2,
-				      struct hsw_wm_maximums *lp_max_5_6)
+static void ilk_update_wm(struct drm_crtc *crtc)
 {
-	struct drm_crtc *crtc;
-	struct drm_plane *plane;
-	enum pipe pipe;
-	struct intel_wm_config config = {};
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_pipe_wm pipe_wm = {};
+	bool ret;
 
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-		struct hsw_pipe_wm_parameters *p;
+	ret = intel_compute_pipe_wm(crtc, &pipe_wm);
+	if (!ret)
+		DRM_ERROR("crtc %u (pipe %c) LP0 watermarks invalid\n",
+			  crtc->base.id, pipe_name(intel_crtc->pipe));
 
-		pipe = intel_crtc->pipe;
-		p = &params[pipe];
-
-		p->active = intel_crtc_active(crtc);
-		if (!p->active)
-			continue;
-
-		config.pipes_active++;
-
-		p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
-		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
-		p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
-		p->cur.bytes_per_pixel = 4;
-		p->pri.horiz_pixels =
-			intel_crtc->config.requested_mode.hdisplay;
-		p->cur.horiz_pixels = 64;
-		/* TODO: for now, assume primary and cursor planes are always enabled. */
-		p->pri.enabled = true;
-		p->cur.enabled = true;
-	}
-
-	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-		struct intel_plane *intel_plane = to_intel_plane(plane);
-		struct hsw_pipe_wm_parameters *p;
-
-		pipe = intel_plane->pipe;
-		p = &params[pipe];
-
-		p->spr = intel_plane->wm;
-
-		config.sprites_enabled |= p->spr.enabled;
-		config.sprites_scaled |= p->spr.scaled;
-	}
-
-	ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
-
-	/* 5/6 split only in single pipe config on IVB+ */
-	if (INTEL_INFO(dev)->gen >= 7 && config.pipes_active <= 1)
-		ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6);
-	else
-		*lp_max_5_6 = *lp_max_1_2;
-}
-
-static void hsw_compute_wm_results(struct drm_device *dev,
-				   struct hsw_pipe_wm_parameters *params,
-				   struct hsw_wm_maximums *lp_maximums,
-				   struct hsw_wm_values *results)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	struct intel_wm_level lp_results[4] = {};
-	enum pipe pipe;
-	int level, max_level, wm_lp;
-
-	for (level = 1; level <= 4; level++)
-		if (!hsw_compute_lp_wm(dev_priv, level,
-				       lp_maximums, params,
-				       &lp_results[level - 1]))
-			break;
-	max_level = level - 1;
-
-	/* The spec says it is preferred to disable FBC WMs instead of disabling
-	 * a WM level. */
-	results->enable_fbc_wm = true;
-	for (level = 1; level <= max_level; level++) {
-		if (!lp_results[level - 1].fbc_val > lp_maximums->fbc) {
-			results->enable_fbc_wm = false;
-			lp_results[level - 1].fbc_val = 0;
-		}
-	}
-
-	memset(results, 0, sizeof(*results));
-	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
-		const struct intel_wm_level *r;
-
-		level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp;
-		if (level > max_level)
-			break;
-
-		r = &lp_results[level - 1];
-		results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2,
-							  r->fbc_val,
-							  r->pri_val,
-							  r->cur_val);
-		results->wm_lp_spr[wm_lp - 1] = r->spr_val;
-	}
-
-	for_each_pipe(pipe)
-		results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev_priv, pipe,
-							     &params[pipe]);
-
-	for_each_pipe(pipe) {
-		crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-		results->wm_linetime[pipe] = hsw_compute_linetime_wm(dev, crtc);
-	}
-}
-
-/* Find the result with the highest level enabled. Check for enable_fbc_wm in
- * case both are at the same level. Prefer r1 in case they're the same. */
-static struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1,
-						  struct hsw_wm_values *r2)
-{
-	int i, val_r1 = 0, val_r2 = 0;
-
-	for (i = 0; i < 3; i++) {
-		if (r1->wm_lp[i] & WM3_LP_EN)
-			val_r1 = r1->wm_lp[i] & WM1_LP_LATENCY_MASK;
-		if (r2->wm_lp[i] & WM3_LP_EN)
-			val_r2 = r2->wm_lp[i] & WM1_LP_LATENCY_MASK;
-	}
-
-	if (val_r1 == val_r2) {
-		if (r2->enable_fbc_wm && !r1->enable_fbc_wm)
-			return r2;
-		else
-			return r1;
-	} else if (val_r1 > val_r2) {
-		return r1;
-	} else {
-		return r2;
-	}
-}
-
-/*
- * The spec says we shouldn't write when we don't need, because every write
- * causes WMs to be re-evaluated, expending some power.
- */
-static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
-				struct hsw_wm_values *results,
-				enum intel_ddb_partitioning partitioning)
-{
-	struct hsw_wm_values previous;
-	uint32_t val;
-	enum intel_ddb_partitioning prev_partitioning;
-	bool prev_enable_fbc_wm;
-
-	previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
-	previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
-	previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
-	previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
-	previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
-	previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
-	previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
-	previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
-	previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
-	previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
-	previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
-	previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
-
-	prev_partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
-				INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
-
-	prev_enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
-
-	if (memcmp(results->wm_pipe, previous.wm_pipe,
-		   sizeof(results->wm_pipe)) == 0 &&
-	    memcmp(results->wm_lp, previous.wm_lp,
-		   sizeof(results->wm_lp)) == 0 &&
-	    memcmp(results->wm_lp_spr, previous.wm_lp_spr,
-		   sizeof(results->wm_lp_spr)) == 0 &&
-	    memcmp(results->wm_linetime, previous.wm_linetime,
-		   sizeof(results->wm_linetime)) == 0 &&
-	    partitioning == prev_partitioning &&
-	    results->enable_fbc_wm == prev_enable_fbc_wm)
-		return;
-
-	if (previous.wm_lp[2] != 0)
-		I915_WRITE(WM3_LP_ILK, 0);
-	if (previous.wm_lp[1] != 0)
-		I915_WRITE(WM2_LP_ILK, 0);
-	if (previous.wm_lp[0] != 0)
-		I915_WRITE(WM1_LP_ILK, 0);
-
-	if (previous.wm_pipe[0] != results->wm_pipe[0])
-		I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
-	if (previous.wm_pipe[1] != results->wm_pipe[1])
-		I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]);
-	if (previous.wm_pipe[2] != results->wm_pipe[2])
-		I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]);
-
-	if (previous.wm_linetime[0] != results->wm_linetime[0])
-		I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]);
-	if (previous.wm_linetime[1] != results->wm_linetime[1])
-		I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]);
-	if (previous.wm_linetime[2] != results->wm_linetime[2])
-		I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
-
-	if (prev_partitioning != partitioning) {
-		val = I915_READ(WM_MISC);
-		if (partitioning == INTEL_DDB_PART_1_2)
-			val &= ~WM_MISC_DATA_PARTITION_5_6;
-		else
-			val |= WM_MISC_DATA_PARTITION_5_6;
-		I915_WRITE(WM_MISC, val);
-	}
-
-	if (prev_enable_fbc_wm != results->enable_fbc_wm) {
-		val = I915_READ(DISP_ARB_CTL);
-		if (results->enable_fbc_wm)
-			val &= ~DISP_FBC_WM_DIS;
-		else
-			val |= DISP_FBC_WM_DIS;
-		I915_WRITE(DISP_ARB_CTL, val);
-	}
-
-	if (previous.wm_lp_spr[0] != results->wm_lp_spr[0])
-		I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
-	if (previous.wm_lp_spr[1] != results->wm_lp_spr[1])
-		I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
-	if (previous.wm_lp_spr[2] != results->wm_lp_spr[2])
-		I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
-
-	if (results->wm_lp[0] != 0)
-		I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
-	if (results->wm_lp[1] != 0)
-		I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
-	if (results->wm_lp[2] != 0)
-		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
-}
-
-static void haswell_update_wm(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
-	struct hsw_pipe_wm_parameters params[3];
-	struct hsw_wm_values results_1_2, results_5_6, *best_results;
-	enum intel_ddb_partitioning partitioning;
-
-	hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
-
-	hsw_compute_wm_results(dev, params,
-			       &lp_max_1_2, &results_1_2);
-	if (lp_max_1_2.pri != lp_max_5_6.pri) {
-		hsw_compute_wm_results(dev, params,
-				       &lp_max_5_6, &results_5_6);
-		best_results = hsw_find_best_result(&results_1_2, &results_5_6);
-	} else {
-		best_results = &results_1_2;
-	}
-
-	partitioning = (best_results == &results_1_2) ?
-		       INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
-
-	hsw_write_wm_values(dev_priv, best_results, partitioning);
+	intel_setup_pipe_wm(intel_crtc, &pipe_wm);
 }
 
-static void haswell_update_sprite_wm(struct drm_plane *plane,
-				     struct drm_crtc *crtc,
-				     uint32_t sprite_width, int pixel_size,
-				     bool enabled, bool scaled)
+static void ilk_update_sprite_wm(struct drm_plane *plane,
+				 struct drm_crtc *crtc,
+				 uint32_t sprite_width, int pixel_size,
+				 bool enabled, bool scaled)
 {
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 
@@ -2838,169 +2734,7 @@ static void haswell_update_sprite_wm(struct drm_plane *plane,
 	intel_plane->wm.horiz_pixels = sprite_width;
 	intel_plane->wm.bytes_per_pixel = pixel_size;
 
-	haswell_update_wm(crtc);
-}
-
-static bool
-sandybridge_compute_sprite_wm(struct drm_device *dev, int plane,
-			      uint32_t sprite_width, int pixel_size,
-			      const struct intel_watermark_params *display,
-			      int display_latency_ns, int *sprite_wm)
-{
-	struct drm_crtc *crtc;
-	int clock;
-	int entries, tlb_miss;
-
-	crtc = intel_get_crtc_for_plane(dev, plane);
-	if (!intel_crtc_active(crtc)) {
-		*sprite_wm = display->guard_size;
-		return false;
-	}
-
-	clock = crtc->mode.clock;
-
-	/* Use the small buffer method to calculate the sprite watermark */
-	entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
-	tlb_miss = display->fifo_size*display->cacheline_size -
-		sprite_width * 8;
-	if (tlb_miss > 0)
-		entries += tlb_miss;
-	entries = DIV_ROUND_UP(entries, display->cacheline_size);
-	*sprite_wm = entries + display->guard_size;
-	if (*sprite_wm > (int)display->max_wm)
-		*sprite_wm = display->max_wm;
-
-	return true;
-}
-
-static bool
-sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
-				uint32_t sprite_width, int pixel_size,
-				const struct intel_watermark_params *display,
-				int latency_ns, int *sprite_wm)
-{
-	struct drm_crtc *crtc;
-	unsigned long line_time_us;
-	int clock;
-	int line_count, line_size;
-	int small, large;
-	int entries;
-
-	if (!latency_ns) {
-		*sprite_wm = 0;
-		return false;
-	}
-
-	crtc = intel_get_crtc_for_plane(dev, plane);
-	clock = crtc->mode.clock;
-	if (!clock) {
-		*sprite_wm = 0;
-		return false;
-	}
-
-	line_time_us = (sprite_width * 1000) / clock;
-	if (!line_time_us) {
-		*sprite_wm = 0;
-		return false;
-	}
-
-	line_count = (latency_ns / line_time_us + 1000) / 1000;
-	line_size = sprite_width * pixel_size;
-
-	/* Use the minimum of the small and large buffer method for primary */
-	small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
-	large = line_count * line_size;
-
-	entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
-	*sprite_wm = entries + display->guard_size;
-
-	return *sprite_wm > 0x3ff ? false : true;
-}
-
-static void sandybridge_update_sprite_wm(struct drm_plane *plane,
-					 struct drm_crtc *crtc,
-					 uint32_t sprite_width, int pixel_size,
-					 bool enable, bool scaled)
-{
-	struct drm_device *dev = plane->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipe = to_intel_plane(plane)->pipe;
-	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
-	u32 val;
-	int sprite_wm, reg;
-	int ret;
-
-	if (!enable)
-		return;
-
-	switch (pipe) {
-	case 0:
-		reg = WM0_PIPEA_ILK;
-		break;
-	case 1:
-		reg = WM0_PIPEB_ILK;
-		break;
-	case 2:
-		reg = WM0_PIPEC_IVB;
-		break;
-	default:
-		return; /* bad pipe */
-	}
-
-	ret = sandybridge_compute_sprite_wm(dev, pipe, sprite_width, pixel_size,
-					    &sandybridge_display_wm_info,
-					    latency, &sprite_wm);
-	if (!ret) {
-		DRM_DEBUG_KMS("failed to compute sprite wm for pipe %c\n",
-			      pipe_name(pipe));
-		return;
-	}
-
-	val = I915_READ(reg);
-	val &= ~WM0_PIPE_SPRITE_MASK;
-	I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));
-	DRM_DEBUG_KMS("sprite watermarks For pipe %c - %d\n", pipe_name(pipe), sprite_wm);
-
-
-	ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-					      pixel_size,
-					      &sandybridge_display_srwm_info,
-					      SNB_READ_WM1_LATENCY() * 500,
-					      &sprite_wm);
-	if (!ret) {
-		DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %c\n",
-			      pipe_name(pipe));
-		return;
-	}
-	I915_WRITE(WM1S_LP_ILK, sprite_wm);
-
-	/* Only IVB has two more LP watermarks for sprite */
-	if (!IS_IVYBRIDGE(dev))
-		return;
-
-	ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-					      pixel_size,
-					      &sandybridge_display_srwm_info,
-					      SNB_READ_WM2_LATENCY() * 500,
-					      &sprite_wm);
-	if (!ret) {
-		DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %c\n",
-			      pipe_name(pipe));
-		return;
-	}
-	I915_WRITE(WM2S_LP_IVB, sprite_wm);
-
-	ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-					      pixel_size,
-					      &sandybridge_display_srwm_info,
-					      SNB_READ_WM3_LATENCY() * 500,
-					      &sprite_wm);
-	if (!ret) {
-		DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %c\n",
-			      pipe_name(pipe));
-		return;
-	}
-	I915_WRITE(WM3S_LP_IVB, sprite_wm);
+	ilk_update_wm(crtc);
 }
 
 /**
@@ -5372,6 +5106,8 @@ void intel_init_pm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	spin_lock_init(&dev_priv->wm.lock);
+
 	if (I915_HAS_FBC(dev)) {
 		if (HAS_PCH_SPLIT(dev)) {
 			dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
@@ -5407,9 +5143,10 @@ void intel_init_pm(struct drm_device *dev)
 		if (IS_GEN5(dev)) {
 			if (dev_priv->wm.pri_latency[1] &&
 			    dev_priv->wm.spr_latency[1] &&
-			    dev_priv->wm.cur_latency[1])
-				dev_priv->display.update_wm = ironlake_update_wm;
-			else {
+			    dev_priv->wm.cur_latency[1]) {
+				dev_priv->display.update_wm = ilk_update_wm;
+				dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
+			} else {
 				DRM_DEBUG_KMS("Failed to get proper latency. "
 					      "Disable CxSR\n");
 				dev_priv->display.update_wm = NULL;
@@ -5419,8 +5156,8 @@ void intel_init_pm(struct drm_device *dev)
 			if (dev_priv->wm.pri_latency[0] &&
 			    dev_priv->wm.spr_latency[0] &&
 			    dev_priv->wm.cur_latency[0]) {
-				dev_priv->display.update_wm = sandybridge_update_wm;
-				dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
+				dev_priv->display.update_wm = ilk_update_wm;
+				dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
 			} else {
 				DRM_DEBUG_KMS("Failed to read display plane latency. "
 					      "Disable CxSR\n");
@@ -5431,8 +5168,8 @@ void intel_init_pm(struct drm_device *dev)
 			if (dev_priv->wm.pri_latency[0] &&
 			    dev_priv->wm.spr_latency[0] &&
 			    dev_priv->wm.cur_latency[0]) {
-				dev_priv->display.update_wm = ivybridge_update_wm;
-				dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
+				dev_priv->display.update_wm = ilk_update_wm;
+				dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
 			} else {
 				DRM_DEBUG_KMS("Failed to read display plane latency. "
 					      "Disable CxSR\n");
@@ -5443,9 +5180,8 @@ void intel_init_pm(struct drm_device *dev)
 			if (dev_priv->wm.pri_latency[0] &&
 			    dev_priv->wm.spr_latency[0] &&
 			    dev_priv->wm.cur_latency[0]) {
-				dev_priv->display.update_wm = haswell_update_wm;
-				dev_priv->display.update_sprite_wm =
-					haswell_update_sprite_wm;
+				dev_priv->display.update_wm = ilk_update_wm;
+				dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
 			} else {
 				DRM_DEBUG_KMS("Failed to read display plane latency. "
 					      "Disable CxSR\n");
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 31/35] drm/i915: Move HSW linetime watermark handling to modeset code
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (29 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05 17:44   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 32/35] hack: Add debug prints to watermark compute funcs ville.syrjala
                   ` (4 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The linetime watermarks don't change, except when doing a full modeset,
so having them as part of the full dynamic watermarks code is pointless.

Just move the linetime watermark setup to occur just before enabling the
pipe on HSW, and leave it alone after that.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  1 -
 drivers/gpu/drm/i915/intel_pm.c      | 32 --------------------------------
 3 files changed, 22 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 54216d1..7ad66de 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3320,6 +3320,26 @@ static void hsw_disable_ips(struct intel_crtc *crtc)
 	intel_wait_for_vblank(dev, crtc->pipe);
 }
 
+static void
+hsw_setup_linetime_wm(struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
+	u32 linetime, ips_linetime;
+
+	/* The WM are computed with base on how long it takes to fill a single
+	 * row at the given clock rate, multiplied by 8.
+	 * */
+	linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, mode->clock);
+	ips_linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8,
+					 intel_ddi_get_cdclk_freq(dev_priv));
+
+	I915_WRITE(PIPE_WM_LINETIME(intel_crtc->pipe),
+		   PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
+		   PIPE_WM_LINETIME_TIME(linetime));
+}
+
 static void haswell_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3360,6 +3380,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_ddi_set_pipe_settings(crtc);
 	intel_ddi_enable_transcoder_func(crtc);
 
+	hsw_setup_linetime_wm(crtc);
+
 	intel_update_watermarks(crtc);
 	intel_enable_pipe(dev_priv, pipe,
 			  intel_crtc->config.has_pch_encoder);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a5c15ab..d7996e0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -297,7 +297,6 @@ struct intel_pipe_wm {
 	bool sprites_enabled;
 	bool sprites_scaled;
 	bool fbc_wm_enabled;
-	uint32_t linetime;
 	struct intel_wm_level wm[5];
 };
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7fd922dc..d2cbc94 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2342,10 +2342,6 @@ static void ilk_program_watermarks(struct drm_device *dev)
 			   wm->spr_val << WM0_PIPE_SPRITE_SHIFT |
 			   wm->cur_val);
 
-		if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev))
-			I915_WRITE(PIPE_WM_LINETIME(intel_crtc->pipe),
-				   pipe_wm->linetime);
-
 		intel_crtc->wm.hw = *wm;
 	}
 
@@ -2437,9 +2433,6 @@ static void ilk_program_watermarks(struct drm_device *dev)
 	}
 }
 
-static uint32_t
-hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc);
-
 static int ilk_max_wm_level(const struct drm_device *dev,
 			    const struct intel_pipe_wm *pipe_wm)
 {
@@ -2512,9 +2505,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	for (level = 0; level <= max_level; level++)
 		ilk_compute_wm_level(dev_priv, level, &p, &pipe_wm->wm[level]);
 
-	if (IS_HASWELL(dev))
-		pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
-
 	ilk_wm_max(dev, 0, &config, false, &max);
 
 	/* At least LP0 must be valid */
@@ -2597,28 +2587,6 @@ void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe)
 	spin_unlock_irqrestore(&dev_priv->wm.lock, flags);
 }
 
-static uint32_t
-hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
-	u32 linetime, ips_linetime;
-
-	if (!intel_crtc_active(crtc))
-		return 0;
-
-	/* The WM are computed with base on how long it takes to fill a single
-	 * row at the given clock rate, multiplied by 8.
-	 * */
-	linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, mode->clock);
-	ips_linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8,
-					 intel_ddi_get_cdclk_freq(dev_priv));
-
-	return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
-	       PIPE_WM_LINETIME_TIME(linetime);
-}
-
 static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 32/35] hack: Add debug prints to watermark compute funcs
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (30 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 31/35] drm/i915: Move HSW linetime watermark handling to modeset code ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05  8:57 ` [PATCH 33/35] hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB ville.syrjala
                   ` (3 subsequent siblings)
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

---
 drivers/gpu/drm/i915/intel_pm.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d2cbc94..782c644 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1770,6 +1770,13 @@ static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
 {
 	uint32_t method1, method2;
 
+	DRM_DEBUG_KMS("active = %s, pipe_htotal = %u, pixel_rate = %u, "
+		      "enabled = %s, horiz_pixels = %u, bytes_per_pixel = %u, "
+		      "latency = %u\n",
+		      yesno(params->active), params->pipe_htotal, params->pixel_rate,
+		      yesno(params->pri.enabled), params->pri.horiz_pixels, params->pri.bytes_per_pixel,
+		      mem_value);
+
 	if (!params->active || !params->pri.enabled)
 		return 0;
 
@@ -1795,6 +1802,13 @@ static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
 {
 	uint32_t method1, method2;
 
+	DRM_DEBUG_KMS("active = %s, pipe_htotal = %u, pixel_rate = %u, "
+		      "enabled = %s, horiz_pixels = %u, bytes_per_pixel = %u, "
+		      "latency = %u\n",
+		      yesno(params->active), params->pipe_htotal, params->pixel_rate,
+		      yesno(params->spr.enabled), params->spr.horiz_pixels, params->spr.bytes_per_pixel,
+		      mem_value);
+
 	if (!params->active || !params->spr.enabled)
 		return 0;
 
@@ -1813,6 +1827,13 @@ static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
 static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t mem_value)
 {
+	DRM_DEBUG_KMS("active = %s, pipe_htotal = %u, pixel_rate = %u, "
+		      "enabled = %s, horiz_pixels = %u, bytes_per_pixel = %u, "
+		      "latency = %u\n",
+		      yesno(params->active), params->pipe_htotal, params->pixel_rate,
+		      yesno(params->cur.enabled), params->cur.horiz_pixels, params->cur.bytes_per_pixel,
+		      mem_value);
+
 	if (!params->active || !params->cur.enabled)
 		return 0;
 
@@ -1827,6 +1848,13 @@ static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
 static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
 				   uint32_t pri_val)
 {
+	DRM_DEBUG_KMS("active = %s, pipe_htotal = %u, pixel_rate = %u, "
+		      "enabled = %s, horiz_pixels = %u, bytes_per_pixel = %u, "
+		      "pri_val = %u\n",
+		      yesno(params->active), params->pipe_htotal, params->pixel_rate,
+		      yesno(params->pri.enabled), params->pri.horiz_pixels, params->pri.bytes_per_pixel,
+		      pri_val);
+
 	if (!params->active || !params->pri.enabled)
 		return 0;
 
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 33/35] hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (31 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 32/35] hack: Add debug prints to watermark compute funcs ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05 17:19   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 34/35] hack: Make fifo underruns DRM_ERROR ville.syrjala
                   ` (2 subsequent siblings)
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Don't want to lose them in the noise. Just let them happen.
---
 drivers/gpu/drm/i915/i915_irq.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ee5127f..10554bf 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1102,15 +1102,15 @@ static void ivb_err_int_handler(struct drm_device *dev)
 		DRM_ERROR("Poison interrupt\n");
 
 	if (err_int & ERR_INT_FIFO_UNDERRUN_A)
-		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false))
+		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
 			DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
 
 	if (err_int & ERR_INT_FIFO_UNDERRUN_B)
-		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false))
+		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
 			DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
 
 	if (err_int & ERR_INT_FIFO_UNDERRUN_C)
-		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, false))
+		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, true))
 			DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n");
 
 	I915_WRITE(GEN7_ERR_INT, err_int);
@@ -1359,11 +1359,11 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 		DRM_ERROR("Poison interrupt\n");
 
 	if (de_iir & DE_PIPEA_FIFO_UNDERRUN)
-		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false))
+		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
 			DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
 
 	if (de_iir & DE_PIPEB_FIFO_UNDERRUN)
-		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false))
+		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
 			DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
 
 	if (de_iir & DE_PLANEA_FLIP_DONE) {
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 34/35] hack: Make fifo underruns DRM_ERROR
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (32 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 33/35] hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05 17:19   ` Paulo Zanoni
  2013-07-05  8:57 ` [PATCH 35/35] hack: Print watermark programming duration ville.syrjala
  2013-07-05 16:54 ` [PATCH 00/35] drm/i915: ILK+ watermark rewrite Paulo Zanoni
  35 siblings, 1 reply; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Want to see them w/ debugs turned off.
---
 drivers/gpu/drm/i915/i915_irq.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 10554bf..a55a231 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1103,15 +1103,15 @@ static void ivb_err_int_handler(struct drm_device *dev)
 
 	if (err_int & ERR_INT_FIFO_UNDERRUN_A)
 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
-			DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
+			DRM_ERROR("Pipe A FIFO underrun\n");
 
 	if (err_int & ERR_INT_FIFO_UNDERRUN_B)
 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
-			DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
+			DRM_ERROR("Pipe B FIFO underrun\n");
 
 	if (err_int & ERR_INT_FIFO_UNDERRUN_C)
 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, true))
-			DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n");
+			DRM_ERROR("Pipe C FIFO underrun\n");
 
 	I915_WRITE(GEN7_ERR_INT, err_int);
 }
@@ -1360,11 +1360,11 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 
 	if (de_iir & DE_PIPEA_FIFO_UNDERRUN)
 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
-			DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
+			DRM_ERROR("Pipe A FIFO underrun\n");
 
 	if (de_iir & DE_PIPEB_FIFO_UNDERRUN)
 		if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
-			DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
+			DRM_ERROR("Pipe B FIFO underrun\n");
 
 	if (de_iir & DE_PLANEA_FLIP_DONE) {
 		intel_prepare_page_flip(dev, 0);
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* [PATCH 35/35] hack: Print watermark programming duration
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (33 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 34/35] hack: Make fifo underruns DRM_ERROR ville.syrjala
@ 2013-07-05  8:57 ` ville.syrjala
  2013-07-05 16:54 ` [PATCH 00/35] drm/i915: ILK+ watermark rewrite Paulo Zanoni
  35 siblings, 0 replies; 74+ messages in thread
From: ville.syrjala @ 2013-07-05  8:57 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Print how long watermark programming took. Seems to be ~5 usec on ILK
and IVB at the moment.
---
 drivers/gpu/drm/i915/intel_pm.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 782c644..1e49c94 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2601,15 +2601,26 @@ void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe)
 	spin_lock_irqsave(&dev_priv->wm.lock, flags);
 
 	if (intel_crtc->wm.dirty) {
+		ktime_t stime, etime;
+		s64 duration_ns;
+
 		DRM_DEBUG_KMS("pipe %c vblank, programming new watermarks\n",
 			      pipe_name(pipe));
 
+		stime = ktime_get();
+
 		drm_vblank_put(dev, pipe);
 
 		intel_crtc->wm.active = intel_crtc->wm.pending;
 		intel_crtc->wm.dirty = false;
 
 		ilk_program_watermarks(dev);
+
+		etime = ktime_get();
+
+		duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime);
+		DRM_ERROR("pipe %c watermark programming took %lld ns\n",
+			  pipe_name(pipe), duration_ns);
 	}
 
 	spin_unlock_irqrestore(&dev_priv->wm.lock, flags);
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 74+ messages in thread

* Re: [PATCH 09/35] drm/i915: Split out reading of HSW watermark latency values
  2013-07-05  8:57 ` [PATCH 09/35] drm/i915: Split out reading of HSW watermark latency values ville.syrjala
@ 2013-07-05  9:19   ` Chris Wilson
  2013-07-05 10:51     ` Ville Syrjälä
  2013-07-30 20:09   ` Paulo Zanoni
  1 sibling, 1 reply; 74+ messages in thread
From: Chris Wilson @ 2013-07-05  9:19 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Fri, Jul 05, 2013 at 11:57:21AM +0300, ville.syrjala@linux.intel.com wrote:
> @@ -2593,10 +2598,11 @@ static void haswell_update_wm(struct drm_device *dev)
>  	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
>  	struct hsw_pipe_wm_parameters params[3];
>  	struct hsw_wm_values results_1_2, results_5_6, *best_results;
> -	uint16_t wm[5];
> +	uint16_t wm[5] = {};

Trying to hide a warning?
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 29/35] drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset
  2013-07-05  8:57 ` [PATCH 29/35] drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset ville.syrjala
@ 2013-07-05  9:32   ` Chris Wilson
  0 siblings, 0 replies; 74+ messages in thread
From: Chris Wilson @ 2013-07-05  9:32 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Fri, Jul 05, 2013 at 11:57:41AM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Passing the appropriate crtc to intel_update_watermarks() should help
> in avoiding needless work in the future.
> 
> Also make the call intel_update_watermarks() just once during the
> modeset. Ideally it should happen independently when each plane gets
> enabled/disabled, but for now it seems better to keep it in one place.
> We can improve things when we get all the planes sorted out in a better
> way.

Two patches in one here. I'd like to have the change in calling
semantics from set_base as a separate patch.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
  2013-07-05  8:57 ` [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code ville.syrjala
@ 2013-07-05  9:37   ` Chris Wilson
  2013-07-05 10:49     ` Ville Syrjälä
  2013-07-05 17:51   ` Paulo Zanoni
  1 sibling, 1 reply; 74+ messages in thread
From: Chris Wilson @ 2013-07-05  9:37 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Fri, Jul 05, 2013 at 11:57:42AM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> There is a major problem with the watermark registers; they're not
> double buffered. So we need to make sure we update them at the correct
> time when messing about with planes. The correct time is the beginning
> of vblank.
> 
> So when we determine that the watermarks need to updated hand in hand
> with the next vblank, we store the pre-computed watermarks under
> intel_crtc, and when the vblank happens, we promote the pending
> watermarks to active status.
> 
> on HSW when the watermarks for any pipe change, we must merge the
> watermarks from all pipes so that we can determine the correct LP1+
> watermark levels. For simplicity we follow the same codepaths for
> pre-HSW hardware as well, but there all the LP1+ watermarks will be
> disabled when multiple pipes are enabled. Once the watermarks are
> merged we check them for validity, disabling any invalid levels.
> 
> Touching the watermark registers causes the hardware to re-evaluate the
> watermarks, which expeds some power. So after merging the watermarks
> we check which watermark registers actually need to be changed. And
> finally we write the watermarks registers in the correct order.

Yet you do not justify doing so from interrupt context. A simple way
would be to set safe WM (min of current vs next) before the config
change, then schedule an update outside of interrupt context after the
vblank.

I really want an explanation for why doing so in interrupt context is
the only sane way. Real power numbers vs complexity please.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
  2013-07-05  9:37   ` Chris Wilson
@ 2013-07-05 10:49     ` Ville Syrjälä
  2013-07-05 17:46       ` Paulo Zanoni
  0 siblings, 1 reply; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-05 10:49 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On Fri, Jul 05, 2013 at 10:37:08AM +0100, Chris Wilson wrote:
> On Fri, Jul 05, 2013 at 11:57:42AM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > There is a major problem with the watermark registers; they're not
> > double buffered. So we need to make sure we update them at the correct
> > time when messing about with planes. The correct time is the beginning
> > of vblank.
> > 
> > So when we determine that the watermarks need to updated hand in hand
> > with the next vblank, we store the pre-computed watermarks under
> > intel_crtc, and when the vblank happens, we promote the pending
> > watermarks to active status.
> > 
> > on HSW when the watermarks for any pipe change, we must merge the
> > watermarks from all pipes so that we can determine the correct LP1+
> > watermark levels. For simplicity we follow the same codepaths for
> > pre-HSW hardware as well, but there all the LP1+ watermarks will be
> > disabled when multiple pipes are enabled. Once the watermarks are
> > merged we check them for validity, disabling any invalid levels.
> > 
> > Touching the watermark registers causes the hardware to re-evaluate the
> > watermarks, which expeds some power. So after merging the watermarks
> > we check which watermark registers actually need to be changed. And
> > finally we write the watermarks registers in the correct order.
> 
> Yet you do not justify doing so from interrupt context. A simple way
> would be to set safe WM (min of current vs next) before the config
> change, then schedule an update outside of interrupt context after the
> vblank.
> 
> I really want an explanation for why doing so in interrupt context is
> the only sane way. Real power numbers vs complexity please.

One problem is that there might not be a safe set of values that satisfy
both current and future constraints. One example could be a "low bpp/no
primary + sprite -> high bpp primary + no sprite" case. I guess we could
just reject such changes, but that feels a bit wrong. It would introduce
a weird restriction that would propably baffle userspace (doing a->c fails
but doing a->b->wait_for_vbl->c works), or we'd need to block for one frame
which is a big no-no these days.

Also we would still need to track how the current hardware state
changes across vblanks, so it would still end up doing some extra
stuff at irq time.

My hope was that the current approach wouldn't turn out to be too
expensive. Whether people consider 5 usec excessive, I don't know.
And maybe we could shave some of that off still.

Not that I'm 100% attached to the current design. We could certainly
try other ways, if people think that's worthwile.

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 09/35] drm/i915: Split out reading of HSW watermark latency values
  2013-07-05  9:19   ` Chris Wilson
@ 2013-07-05 10:51     ` Ville Syrjälä
  0 siblings, 0 replies; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-05 10:51 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On Fri, Jul 05, 2013 at 10:19:29AM +0100, Chris Wilson wrote:
> On Fri, Jul 05, 2013 at 11:57:21AM +0300, ville.syrjala@linux.intel.com wrote:
> > @@ -2593,10 +2598,11 @@ static void haswell_update_wm(struct drm_device *dev)
> >  	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
> >  	struct hsw_pipe_wm_parameters params[3];
> >  	struct hsw_wm_values results_1_2, results_5_6, *best_results;
> > -	uint16_t wm[5];
> > +	uint16_t wm[5] = {};
> 
> Trying to hide a warning?

It's actually for the future ILK/SNB/IVB patches where we won't have
latency values for all 5 levels. I guess it should have been part of
those patches instead.

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 00/35] drm/i915: ILK+ watermark rewrite
  2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
                   ` (34 preceding siblings ...)
  2013-07-05  8:57 ` [PATCH 35/35] hack: Print watermark programming duration ville.syrjala
@ 2013-07-05 16:54 ` Paulo Zanoni
  2013-07-05 17:22   ` Ville Syrjälä
  35 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-05 16:54 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> Here's my big ILK+ watermark rewrite. The main idea of the series is to
> write the watermark registers at vblank to make the changes (almost) in
> sync with the plane changes that caused the change in watermarks.
>
> I sent a massive RFC patch a while back, and this is now the somewhat
> split up version.
>
> It's still not quite where we need to get wrt. pre-computing and
> properly checking the LP0 watermarks, but at least it gets us a bit
> closer to that goal.
>
> There's quite a bit of refactoring, small fixes, renaming, and what have you
> at the beginning of the series, so a lot of it should be mergeable w/o too much
> risk. Many of the patches only touch codepaths that are used by HSW currently,
> but by the end of the series, ILK,SNB,IVB,HSW are all using the exact same
> code.
>
> So far I've run this somewhat succesfully on ILK and IVB.

I booted your series on Haswell, on top of drm-intel-nightly.

I booted with only an eDP output (1920x1080). After booting, I checked
dmesg and there's this message:
[   15.754282] [drm:ilk_update_pipe_wm] *ERROR* pipe A watermark
programming took 94278 ns

Also, I ran intel_reg_dumper and now WM_PIPE_B and WM_PIPE_C are
enabled with the maximum values, but the watermarks calculator tells
me to use 0 on them. The other values are correct.

Then I plugged a DP monitor (2560x1440), and right after enabling it I
see a new message:
[  323.354641] [drm:ilk_update_pipe_wm] *ERROR* pipe B watermark
programming took 96015 ns

Then I ran intel_reg_dumper and WM_PIPE_C is still configured with the
maximum values. Also, WM_LP2 and WM_LP3 are enabled, but they
shouldn't be enabled. WM_LP1 has the correct values. Also, when I run
intel_reg_dumper I see screen corruption, but I guess this may be just
a consequence of WM_LP2 and WM_LP3 being enabled.

Then I disabled the eDP output, leaving only DP. The desktop
environment automagically moved the DP output to pipe A. The WM_PIPE_B
and PIPE_WM_LINETIME_B registers did not get zeroed. The WM_LP1 values
are correct, but WM_LP2 and WM_LP3 do not match the spec: the WM
calculator disabled the LP4 level, but your code enabled it, so the
value that should be written in WM_LP3 is now in WM_LP2, and WM_LP3 is
wrong.

So three small bugs: (i) stuff not being correctly zeroed and (ii)
using LP4 as the max level instead of LP3 when using a mode with
2560hsrc 2720htotal 241.50MHz and (iii) that dmesg error.


>
> ----------------------------------------------------------------
> Ville Syrjälä (35):
>       drm/i915: Add scaled paramater to update_sprite_watermarks()
>       drm/i915: Pass the actual sprite width to watermarks functions
>       drm/i915: Calculate the sprite WM based on the source width instead of the destination width
>       drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate
>       drm/i915: Rename most wm compute functions to ilk_ prefix
>       drm/i915: Pass the watermark level to primary WM compute functions
>       drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm
>       drm/i915: Change the watermark latency type to uint16_t
>       drm/i915: Split out reading of HSW watermark latency values
>       drm/i915: Don't multiply the watermark latency values too early
>       drm/i915: Add SNB/IVB support to intel_read_wm_latency
>       drm/i915: Add ILK support to intel_read_wm_latency
>       drm/i915: Store the watermark latency values in dev_priv
>       drm/i915: Use the stored cursor and plane latencies properly
>       drm/i915: Print the watermark latencies during init
>       drm/i915: Disable specific watermark levels when latency is zero
>       drm/i915: Pull watermark level validity check out
>       drm/i915: Split watermark level computation from the code
>       drm/i915: Kill fbc_enable from hsw_lp_wm_results
>       drm/i915: Rename hsw_data_buf_partitioning to intel_ddb_partitioning
>       drm/i915: Rename hsw_lp_wm_result to intel_wm_level
>       drm/i915: Calculate max watermark levels for ILK+
>       drm/i915; Pull some watermarks state into a separate structure
>       drm/i915: Split plane watermark parameters into a separate struct
>       drm/i915: Pass crtc to our update/disable_plane hooks
>       drm/i915: Don't try to disable plane if it's already disabled
>       drm/i915: Pass plane and crtc to intel_update_sprite_watermarks
>       drm/i915: Always call intel_update_sprite_watermarks() when disabling a plane
>       drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset
>       drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
>       drm/i915: Move HSW linetime watermark handling to modeset code
>       hack: Add debug prints to watermark compute funcs
>       hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB
>       hack: Make fifo underruns DRM_ERROR
>       hack: Print watermark programming duration
>
>  drivers/gpu/drm/i915/i915_drv.h      |   41 +-
>  drivers/gpu/drm/i915/i915_irq.c      |   32 +-
>  drivers/gpu/drm/i915/i915_reg.h      |    2 +
>  drivers/gpu/drm/i915/intel_display.c |   45 +-
>  drivers/gpu/drm/i915/intel_drv.h     |   47 +-
>  drivers/gpu/drm/i915/intel_pm.c      | 1796 +++++++++++++++++-----------------
>  drivers/gpu/drm/i915/intel_sprite.c  |   54 +-
>  7 files changed, 1039 insertions(+), 978 deletions(-)
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 33/35] hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB
  2013-07-05  8:57 ` [PATCH 33/35] hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB ville.syrjala
@ 2013-07-05 17:19   ` Paulo Zanoni
  2013-07-05 17:34     ` Ville Syrjälä
  0 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-05 17:19 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Don't want to lose them in the noise. Just let them happen.

When I was experimenting with this, I noticed that when we get
underruns, we get thousands of underruns per second, until we fix the
condition that is causing the underruns. With this we'll get tons and
tons and tons of interrupts and really flood dmesg.

> ---
>  drivers/gpu/drm/i915/i915_irq.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index ee5127f..10554bf 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -1102,15 +1102,15 @@ static void ivb_err_int_handler(struct drm_device *dev)
>                 DRM_ERROR("Poison interrupt\n");
>
>         if (err_int & ERR_INT_FIFO_UNDERRUN_A)
> -               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false))
> +               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
>                         DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
>
>         if (err_int & ERR_INT_FIFO_UNDERRUN_B)
> -               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false))
> +               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
>                         DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
>
>         if (err_int & ERR_INT_FIFO_UNDERRUN_C)
> -               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, false))
> +               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, true))
>                         DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n");
>
>         I915_WRITE(GEN7_ERR_INT, err_int);
> @@ -1359,11 +1359,11 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
>                 DRM_ERROR("Poison interrupt\n");
>
>         if (de_iir & DE_PIPEA_FIFO_UNDERRUN)
> -               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false))
> +               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
>                         DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
>
>         if (de_iir & DE_PIPEB_FIFO_UNDERRUN)
> -               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false))
> +               if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
>                         DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
>
>         if (de_iir & DE_PLANEA_FLIP_DONE) {
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 34/35] hack: Make fifo underruns DRM_ERROR
  2013-07-05  8:57 ` [PATCH 34/35] hack: Make fifo underruns DRM_ERROR ville.syrjala
@ 2013-07-05 17:19   ` Paulo Zanoni
  2013-07-05 17:39     ` Ville Syrjälä
  0 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-05 17:19 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Want to see them w/ debugs turned off.

And what about PCH FIFO underruns?

> ---
>  drivers/gpu/drm/i915/i915_irq.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 10554bf..a55a231 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -1103,15 +1103,15 @@ static void ivb_err_int_handler(struct drm_device *dev)
>
>         if (err_int & ERR_INT_FIFO_UNDERRUN_A)
>                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
> -                       DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
> +                       DRM_ERROR("Pipe A FIFO underrun\n");
>
>         if (err_int & ERR_INT_FIFO_UNDERRUN_B)
>                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
> -                       DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
> +                       DRM_ERROR("Pipe B FIFO underrun\n");
>
>         if (err_int & ERR_INT_FIFO_UNDERRUN_C)
>                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, true))
> -                       DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n");
> +                       DRM_ERROR("Pipe C FIFO underrun\n");
>
>         I915_WRITE(GEN7_ERR_INT, err_int);
>  }
> @@ -1360,11 +1360,11 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
>
>         if (de_iir & DE_PIPEA_FIFO_UNDERRUN)
>                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
> -                       DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
> +                       DRM_ERROR("Pipe A FIFO underrun\n");
>
>         if (de_iir & DE_PIPEB_FIFO_UNDERRUN)
>                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
> -                       DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
> +                       DRM_ERROR("Pipe B FIFO underrun\n");
>
>         if (de_iir & DE_PLANEA_FLIP_DONE) {
>                 intel_prepare_page_flip(dev, 0);
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 00/35] drm/i915: ILK+ watermark rewrite
  2013-07-05 16:54 ` [PATCH 00/35] drm/i915: ILK+ watermark rewrite Paulo Zanoni
@ 2013-07-05 17:22   ` Ville Syrjälä
  2013-07-05 17:41     ` Paulo Zanoni
  0 siblings, 1 reply; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-05 17:22 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Jul 05, 2013 at 01:54:02PM -0300, Paulo Zanoni wrote:
> 2013/7/5  <ville.syrjala@linux.intel.com>:
> > Here's my big ILK+ watermark rewrite. The main idea of the series is to
> > write the watermark registers at vblank to make the changes (almost) in
> > sync with the plane changes that caused the change in watermarks.
> >
> > I sent a massive RFC patch a while back, and this is now the somewhat
> > split up version.
> >
> > It's still not quite where we need to get wrt. pre-computing and
> > properly checking the LP0 watermarks, but at least it gets us a bit
> > closer to that goal.
> >
> > There's quite a bit of refactoring, small fixes, renaming, and what have you
> > at the beginning of the series, so a lot of it should be mergeable w/o too much
> > risk. Many of the patches only touch codepaths that are used by HSW currently,
> > but by the end of the series, ILK,SNB,IVB,HSW are all using the exact same
> > code.
> >
> > So far I've run this somewhat succesfully on ILK and IVB.
> 
> I booted your series on Haswell, on top of drm-intel-nightly.
> 
> I booted with only an eDP output (1920x1080). After booting, I checked
> dmesg and there's this message:
> [   15.754282] [drm:ilk_update_pipe_wm] *ERROR* pipe A watermark
> programming took 94278 ns

Just diagnostics to measture the overhead. Do you have some drm.debugs
enabled, or why does it take that long? It was ~5 us on my machines w/o
debugs, although it could naturally take a bit longer on HSW due to the
multi-pipe LP1+ watermarks. But I wasn't expecting 20x increase.

> Also, I ran intel_reg_dumper and now WM_PIPE_B and WM_PIPE_C are
> enabled with the maximum values, but the watermarks calculator tells
> me to use 0 on them. The other values are correct.

Not sure where they got the maximum. I was first thinking that it's
caused by "return UINT_MAX" change + the clamping LP0 to max instead
of failing, but the UINT_MAX thing should only happen when there's no
latency value for the level.

> Then I plugged a DP monitor (2560x1440), and right after enabling it I
> see a new message:
> [  323.354641] [drm:ilk_update_pipe_wm] *ERROR* pipe B watermark
> programming took 96015 ns
> 
> Then I ran intel_reg_dumper and WM_PIPE_C is still configured with the
> maximum values. Also, WM_LP2 and WM_LP3 are enabled, but they
> shouldn't be enabled. WM_LP1 has the correct values. Also, when I run
> intel_reg_dumper I see screen corruption, but I guess this may be just
> a consequence of WM_LP2 and WM_LP3 being enabled.
> 
> Then I disabled the eDP output, leaving only DP. The desktop
> environment automagically moved the DP output to pipe A. The WM_PIPE_B
> and PIPE_WM_LINETIME_B registers did not get zeroed.

Leaving the linetime WM not zeroed was expected. I didn't bother with it
since the pipe is off anyway. It should be easy to zero it out if we
want to.

The pipe watermarks probably didn't get cleared since we update them
after turning the pipe off in the disable path. So there won't be any
vblank irqs from which to perform the update. We could fix that if we
set up the new watermarks just before turning the pipe off. Then we
should still get on more vblank irq. But that would need some change
to the way we determine that the pipe will be off (crtc->active is
updated too late). The other option would be to simply call
ilk_update_pipe_wm() from the crtc disable path directly.

> The WM_LP1 values
> are correct, but WM_LP2 and WM_LP3 do not match the spec: the WM
> calculator disabled the LP4 level, but your code enabled it, so the
> value that should be written in WM_LP3 is now in WM_LP2, and WM_LP3 is
> wrong.

IIRC the wm calculator doesn't take into account the number of available
bits in the registeris, so it might give you a larger value than what
you can fit in the register. But that doesn't seem to your issue. I
would problably want to see the parameters that were used to figure out
where things go wrong.

> So three small bugs: (i) stuff not being correctly zeroed and (ii)
> using LP4 as the max level instead of LP3 when using a mode with
> 2560hsrc 2720htotal 241.50MHz and (iii) that dmesg error.
> 
> 
> >
> > ----------------------------------------------------------------
> > Ville Syrjälä (35):
> >       drm/i915: Add scaled paramater to update_sprite_watermarks()
> >       drm/i915: Pass the actual sprite width to watermarks functions
> >       drm/i915: Calculate the sprite WM based on the source width instead of the destination width
> >       drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate
> >       drm/i915: Rename most wm compute functions to ilk_ prefix
> >       drm/i915: Pass the watermark level to primary WM compute functions
> >       drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm
> >       drm/i915: Change the watermark latency type to uint16_t
> >       drm/i915: Split out reading of HSW watermark latency values
> >       drm/i915: Don't multiply the watermark latency values too early
> >       drm/i915: Add SNB/IVB support to intel_read_wm_latency
> >       drm/i915: Add ILK support to intel_read_wm_latency
> >       drm/i915: Store the watermark latency values in dev_priv
> >       drm/i915: Use the stored cursor and plane latencies properly
> >       drm/i915: Print the watermark latencies during init
> >       drm/i915: Disable specific watermark levels when latency is zero
> >       drm/i915: Pull watermark level validity check out
> >       drm/i915: Split watermark level computation from the code
> >       drm/i915: Kill fbc_enable from hsw_lp_wm_results
> >       drm/i915: Rename hsw_data_buf_partitioning to intel_ddb_partitioning
> >       drm/i915: Rename hsw_lp_wm_result to intel_wm_level
> >       drm/i915: Calculate max watermark levels for ILK+
> >       drm/i915; Pull some watermarks state into a separate structure
> >       drm/i915: Split plane watermark parameters into a separate struct
> >       drm/i915: Pass crtc to our update/disable_plane hooks
> >       drm/i915: Don't try to disable plane if it's already disabled
> >       drm/i915: Pass plane and crtc to intel_update_sprite_watermarks
> >       drm/i915: Always call intel_update_sprite_watermarks() when disabling a plane
> >       drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset
> >       drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
> >       drm/i915: Move HSW linetime watermark handling to modeset code
> >       hack: Add debug prints to watermark compute funcs
> >       hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB
> >       hack: Make fifo underruns DRM_ERROR
> >       hack: Print watermark programming duration
> >
> >  drivers/gpu/drm/i915/i915_drv.h      |   41 +-
> >  drivers/gpu/drm/i915/i915_irq.c      |   32 +-
> >  drivers/gpu/drm/i915/i915_reg.h      |    2 +
> >  drivers/gpu/drm/i915/intel_display.c |   45 +-
> >  drivers/gpu/drm/i915/intel_drv.h     |   47 +-
> >  drivers/gpu/drm/i915/intel_pm.c      | 1796 +++++++++++++++++-----------------
> >  drivers/gpu/drm/i915/intel_sprite.c  |   54 +-
> >  7 files changed, 1039 insertions(+), 978 deletions(-)
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 33/35] hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB
  2013-07-05 17:19   ` Paulo Zanoni
@ 2013-07-05 17:34     ` Ville Syrjälä
  0 siblings, 0 replies; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-05 17:34 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Jul 05, 2013 at 02:19:22PM -0300, Paulo Zanoni wrote:
> 2013/7/5  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Don't want to lose them in the noise. Just let them happen.
> 
> When I was experimenting with this, I noticed that when we get
> underruns, we get thousands of underruns per second, until we fix the
> condition that is causing the underruns. With this we'll get tons and
> tons and tons of interrupts and really flood dmesg.

Yeah. It was just a hack to see if the code managed to apply the
watermarks in time before the pipe really starts to demand pixels. If
you actually configure the system so that it constantly underruns
(something we shouldn't allow, but currently we do) your dmesg will be
full of this stuff.

Clearly we can't even being to consider merging a patch like this
before we have much stricter checks to prevent such mode/plane
configurations. I guess even then some ratelimiting might be a
good idea, just in case.

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 34/35] hack: Make fifo underruns DRM_ERROR
  2013-07-05 17:19   ` Paulo Zanoni
@ 2013-07-05 17:39     ` Ville Syrjälä
  0 siblings, 0 replies; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-05 17:39 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Jul 05, 2013 at 02:19:59PM -0300, Paulo Zanoni wrote:
> 2013/7/5  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Want to see them w/ debugs turned off.
> 
> And what about PCH FIFO underruns?

Ideally we'd want this patch, and yes, other underrun types too. But
I'm thinking that we don't want it before we have sufficient pixel
rate/bandwidth/etc. checks in place. I'm sure someone would file a
bug as soon as they see the error.

> > ---
> >  drivers/gpu/drm/i915/i915_irq.c | 10 +++++-----
> >  1 file changed, 5 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index 10554bf..a55a231 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -1103,15 +1103,15 @@ static void ivb_err_int_handler(struct drm_device *dev)
> >
> >         if (err_int & ERR_INT_FIFO_UNDERRUN_A)
> >                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
> > -                       DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
> > +                       DRM_ERROR("Pipe A FIFO underrun\n");
> >
> >         if (err_int & ERR_INT_FIFO_UNDERRUN_B)
> >                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
> > -                       DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
> > +                       DRM_ERROR("Pipe B FIFO underrun\n");
> >
> >         if (err_int & ERR_INT_FIFO_UNDERRUN_C)
> >                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, true))
> > -                       DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n");
> > +                       DRM_ERROR("Pipe C FIFO underrun\n");
> >
> >         I915_WRITE(GEN7_ERR_INT, err_int);
> >  }
> > @@ -1360,11 +1360,11 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
> >
> >         if (de_iir & DE_PIPEA_FIFO_UNDERRUN)
> >                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, true))
> > -                       DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n");
> > +                       DRM_ERROR("Pipe A FIFO underrun\n");
> >
> >         if (de_iir & DE_PIPEB_FIFO_UNDERRUN)
> >                 if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, true))
> > -                       DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n");
> > +                       DRM_ERROR("Pipe B FIFO underrun\n");
> >
> >         if (de_iir & DE_PLANEA_FLIP_DONE) {
> >                 intel_prepare_page_flip(dev, 0);
> > --
> > 1.8.1.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 00/35] drm/i915: ILK+ watermark rewrite
  2013-07-05 17:22   ` Ville Syrjälä
@ 2013-07-05 17:41     ` Paulo Zanoni
  2013-07-05 17:54       ` Ville Syrjälä
  0 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-05 17:41 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

2013/7/5 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> On Fri, Jul 05, 2013 at 01:54:02PM -0300, Paulo Zanoni wrote:
>> 2013/7/5  <ville.syrjala@linux.intel.com>:
>> > Here's my big ILK+ watermark rewrite. The main idea of the series is to
>> > write the watermark registers at vblank to make the changes (almost) in
>> > sync with the plane changes that caused the change in watermarks.
>> >
>> > I sent a massive RFC patch a while back, and this is now the somewhat
>> > split up version.
>> >
>> > It's still not quite where we need to get wrt. pre-computing and
>> > properly checking the LP0 watermarks, but at least it gets us a bit
>> > closer to that goal.
>> >
>> > There's quite a bit of refactoring, small fixes, renaming, and what have you
>> > at the beginning of the series, so a lot of it should be mergeable w/o too much
>> > risk. Many of the patches only touch codepaths that are used by HSW currently,
>> > but by the end of the series, ILK,SNB,IVB,HSW are all using the exact same
>> > code.
>> >
>> > So far I've run this somewhat succesfully on ILK and IVB.
>>
>> I booted your series on Haswell, on top of drm-intel-nightly.
>>
>> I booted with only an eDP output (1920x1080). After booting, I checked
>> dmesg and there's this message:
>> [   15.754282] [drm:ilk_update_pipe_wm] *ERROR* pipe A watermark
>> programming took 94278 ns
>
> Just diagnostics to measture the overhead. Do you have some drm.debugs
> enabled, or why does it take that long? It was ~5 us on my machines w/o
> debugs, although it could naturally take a bit longer on HSW due to the
> multi-pipe LP1+ watermarks. But I wasn't expecting 20x increase.

I constantly have drm.debug=0xe enabled. I imagine QA also uses it,
and will probably open bug reports about it since the message is
DRM_ERROR.

>
>> Also, I ran intel_reg_dumper and now WM_PIPE_B and WM_PIPE_C are
>> enabled with the maximum values, but the watermarks calculator tells
>> me to use 0 on them. The other values are correct.
>
> Not sure where they got the maximum. I was first thinking that it's
> caused by "return UINT_MAX" change + the clamping LP0 to max instead
> of failing, but the UINT_MAX thing should only happen when there's no
> latency value for the level.
>
>> Then I plugged a DP monitor (2560x1440), and right after enabling it I
>> see a new message:
>> [  323.354641] [drm:ilk_update_pipe_wm] *ERROR* pipe B watermark
>> programming took 96015 ns
>>
>> Then I ran intel_reg_dumper and WM_PIPE_C is still configured with the
>> maximum values. Also, WM_LP2 and WM_LP3 are enabled, but they
>> shouldn't be enabled. WM_LP1 has the correct values. Also, when I run
>> intel_reg_dumper I see screen corruption, but I guess this may be just
>> a consequence of WM_LP2 and WM_LP3 being enabled.
>>
>> Then I disabled the eDP output, leaving only DP. The desktop
>> environment automagically moved the DP output to pipe A. The WM_PIPE_B
>> and PIPE_WM_LINETIME_B registers did not get zeroed.
>
> Leaving the linetime WM not zeroed was expected. I didn't bother with it
> since the pipe is off anyway. It should be easy to zero it out if we
> want to.
>
> The pipe watermarks probably didn't get cleared since we update them
> after turning the pipe off in the disable path. So there won't be any
> vblank irqs from which to perform the update. We could fix that if we
> set up the new watermarks just before turning the pipe off. Then we
> should still get on more vblank irq. But that would need some change
> to the way we determine that the pipe will be off (crtc->active is
> updated too late). The other option would be to simply call
> ilk_update_pipe_wm() from the crtc disable path directly.

Don't forget that we didn't even zero the LP levels we needed to
disable when switching from eDP to eDP+DP. I prefer always zeroing
everything we're not using, since that's what the spec says we need to
do.

>
>> The WM_LP1 values
>> are correct, but WM_LP2 and WM_LP3 do not match the spec: the WM
>> calculator disabled the LP4 level, but your code enabled it, so the
>> value that should be written in WM_LP3 is now in WM_LP2, and WM_LP3 is
>> wrong.
>
> IIRC the wm calculator doesn't take into account the number of available
> bits in the registeris, so it might give you a larger value than what
> you can fit in the register. But that doesn't seem to your issue. I
> would problably want to see the parameters that were used to figure out
> where things go wrong.

I already mentioned them:
Only pipe A enabled, 2560 hsrc, 2720 htotal, 241.50 pixel rate, not
interlaced, no downscaling, cursor enabled with 4bpp 64hsrc, primary
enabled with 4bpp, sprite disabled. SSKPD 140000A005A2404F. CDCLK
450MHz.

>
>> So three small bugs: (i) stuff not being correctly zeroed and (ii)
>> using LP4 as the max level instead of LP3 when using a mode with
>> 2560hsrc 2720htotal 241.50MHz and (iii) that dmesg error.
>>
>>
>> >
>> > ----------------------------------------------------------------
>> > Ville Syrjälä (35):
>> >       drm/i915: Add scaled paramater to update_sprite_watermarks()
>> >       drm/i915: Pass the actual sprite width to watermarks functions
>> >       drm/i915: Calculate the sprite WM based on the source width instead of the destination width
>> >       drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate
>> >       drm/i915: Rename most wm compute functions to ilk_ prefix
>> >       drm/i915: Pass the watermark level to primary WM compute functions
>> >       drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm
>> >       drm/i915: Change the watermark latency type to uint16_t
>> >       drm/i915: Split out reading of HSW watermark latency values
>> >       drm/i915: Don't multiply the watermark latency values too early
>> >       drm/i915: Add SNB/IVB support to intel_read_wm_latency
>> >       drm/i915: Add ILK support to intel_read_wm_latency
>> >       drm/i915: Store the watermark latency values in dev_priv
>> >       drm/i915: Use the stored cursor and plane latencies properly
>> >       drm/i915: Print the watermark latencies during init
>> >       drm/i915: Disable specific watermark levels when latency is zero
>> >       drm/i915: Pull watermark level validity check out
>> >       drm/i915: Split watermark level computation from the code
>> >       drm/i915: Kill fbc_enable from hsw_lp_wm_results
>> >       drm/i915: Rename hsw_data_buf_partitioning to intel_ddb_partitioning
>> >       drm/i915: Rename hsw_lp_wm_result to intel_wm_level
>> >       drm/i915: Calculate max watermark levels for ILK+
>> >       drm/i915; Pull some watermarks state into a separate structure
>> >       drm/i915: Split plane watermark parameters into a separate struct
>> >       drm/i915: Pass crtc to our update/disable_plane hooks
>> >       drm/i915: Don't try to disable plane if it's already disabled
>> >       drm/i915: Pass plane and crtc to intel_update_sprite_watermarks
>> >       drm/i915: Always call intel_update_sprite_watermarks() when disabling a plane
>> >       drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset
>> >       drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
>> >       drm/i915: Move HSW linetime watermark handling to modeset code
>> >       hack: Add debug prints to watermark compute funcs
>> >       hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB
>> >       hack: Make fifo underruns DRM_ERROR
>> >       hack: Print watermark programming duration
>> >
>> >  drivers/gpu/drm/i915/i915_drv.h      |   41 +-
>> >  drivers/gpu/drm/i915/i915_irq.c      |   32 +-
>> >  drivers/gpu/drm/i915/i915_reg.h      |    2 +
>> >  drivers/gpu/drm/i915/intel_display.c |   45 +-
>> >  drivers/gpu/drm/i915/intel_drv.h     |   47 +-
>> >  drivers/gpu/drm/i915/intel_pm.c      | 1796 +++++++++++++++++-----------------
>> >  drivers/gpu/drm/i915/intel_sprite.c  |   54 +-
>> >  7 files changed, 1039 insertions(+), 978 deletions(-)
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>>
>>
>> --
>> Paulo Zanoni
>
> --
> Ville Syrjälä
> Intel OTC



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 31/35] drm/i915: Move HSW linetime watermark handling to modeset code
  2013-07-05  8:57 ` [PATCH 31/35] drm/i915: Move HSW linetime watermark handling to modeset code ville.syrjala
@ 2013-07-05 17:44   ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-05 17:44 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The linetime watermarks don't change, except when doing a full modeset,
> so having them as part of the full dynamic watermarks code is pointless.
>
> Just move the linetime watermark setup to occur just before enabling the
> pipe on HSW, and leave it alone after that.

You're kinda reverting a patch I wrote earlier. One of my concerns is
that I wanted to make sure that when we update the linetime watermarks
all WM_LP watermarks are zero. The order in which we write the LP
registers is important, so I wanted to make sure we always did it
correctly. I see hsw_write_wm_values got killed, so now it's harder to
check if we're writing the registers in the right order.


>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |  1 -
>  drivers/gpu/drm/i915/intel_pm.c      | 32 --------------------------------
>  3 files changed, 22 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 54216d1..7ad66de 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3320,6 +3320,26 @@ static void hsw_disable_ips(struct intel_crtc *crtc)
>         intel_wait_for_vblank(dev, crtc->pipe);
>  }
>
> +static void
> +hsw_setup_linetime_wm(struct drm_crtc *crtc)
> +{
> +       struct drm_i915_private *dev_priv = crtc->dev->dev_private;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
> +       u32 linetime, ips_linetime;
> +
> +       /* The WM are computed with base on how long it takes to fill a single
> +        * row at the given clock rate, multiplied by 8.
> +        * */
> +       linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, mode->clock);
> +       ips_linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8,
> +                                        intel_ddi_get_cdclk_freq(dev_priv));
> +
> +       I915_WRITE(PIPE_WM_LINETIME(intel_crtc->pipe),
> +                  PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
> +                  PIPE_WM_LINETIME_TIME(linetime));
> +}
> +
>  static void haswell_crtc_enable(struct drm_crtc *crtc)
>  {
>         struct drm_device *dev = crtc->dev;
> @@ -3360,6 +3380,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>         intel_ddi_set_pipe_settings(crtc);
>         intel_ddi_enable_transcoder_func(crtc);
>
> +       hsw_setup_linetime_wm(crtc);
> +
>         intel_update_watermarks(crtc);
>         intel_enable_pipe(dev_priv, pipe,
>                           intel_crtc->config.has_pch_encoder);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index a5c15ab..d7996e0 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -297,7 +297,6 @@ struct intel_pipe_wm {
>         bool sprites_enabled;
>         bool sprites_scaled;
>         bool fbc_wm_enabled;
> -       uint32_t linetime;
>         struct intel_wm_level wm[5];
>  };
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 7fd922dc..d2cbc94 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2342,10 +2342,6 @@ static void ilk_program_watermarks(struct drm_device *dev)
>                            wm->spr_val << WM0_PIPE_SPRITE_SHIFT |
>                            wm->cur_val);
>
> -               if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev))
> -                       I915_WRITE(PIPE_WM_LINETIME(intel_crtc->pipe),
> -                                  pipe_wm->linetime);
> -
>                 intel_crtc->wm.hw = *wm;
>         }
>
> @@ -2437,9 +2433,6 @@ static void ilk_program_watermarks(struct drm_device *dev)
>         }
>  }
>
> -static uint32_t
> -hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc);
> -
>  static int ilk_max_wm_level(const struct drm_device *dev,
>                             const struct intel_pipe_wm *pipe_wm)
>  {
> @@ -2512,9 +2505,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         for (level = 0; level <= max_level; level++)
>                 ilk_compute_wm_level(dev_priv, level, &p, &pipe_wm->wm[level]);
>
> -       if (IS_HASWELL(dev))
> -               pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
> -
>         ilk_wm_max(dev, 0, &config, false, &max);
>
>         /* At least LP0 must be valid */
> @@ -2597,28 +2587,6 @@ void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe)
>         spin_unlock_irqrestore(&dev_priv->wm.lock, flags);
>  }
>
> -static uint32_t
> -hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
> -{
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -       struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
> -       u32 linetime, ips_linetime;
> -
> -       if (!intel_crtc_active(crtc))
> -               return 0;
> -
> -       /* The WM are computed with base on how long it takes to fill a single
> -        * row at the given clock rate, multiplied by 8.
> -        * */
> -       linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, mode->clock);
> -       ips_linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8,
> -                                        intel_ddi_get_cdclk_freq(dev_priv));
> -
> -       return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
> -              PIPE_WM_LINETIME_TIME(linetime);
> -}
> -
>  static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
  2013-07-05 10:49     ` Ville Syrjälä
@ 2013-07-05 17:46       ` Paulo Zanoni
  2013-07-05 18:00         ` Ville Syrjälä
  0 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-05 17:46 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

2013/7/5 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> On Fri, Jul 05, 2013 at 10:37:08AM +0100, Chris Wilson wrote:
>> On Fri, Jul 05, 2013 at 11:57:42AM +0300, ville.syrjala@linux.intel.com wrote:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > There is a major problem with the watermark registers; they're not
>> > double buffered. So we need to make sure we update them at the correct
>> > time when messing about with planes. The correct time is the beginning
>> > of vblank.
>> >
>> > So when we determine that the watermarks need to updated hand in hand
>> > with the next vblank, we store the pre-computed watermarks under
>> > intel_crtc, and when the vblank happens, we promote the pending
>> > watermarks to active status.
>> >
>> > on HSW when the watermarks for any pipe change, we must merge the
>> > watermarks from all pipes so that we can determine the correct LP1+
>> > watermark levels. For simplicity we follow the same codepaths for
>> > pre-HSW hardware as well, but there all the LP1+ watermarks will be
>> > disabled when multiple pipes are enabled. Once the watermarks are
>> > merged we check them for validity, disabling any invalid levels.
>> >
>> > Touching the watermark registers causes the hardware to re-evaluate the
>> > watermarks, which expeds some power. So after merging the watermarks
>> > we check which watermark registers actually need to be changed. And
>> > finally we write the watermarks registers in the correct order.
>>
>> Yet you do not justify doing so from interrupt context. A simple way
>> would be to set safe WM (min of current vs next) before the config
>> change, then schedule an update outside of interrupt context after the
>> vblank.
>>
>> I really want an explanation for why doing so in interrupt context is
>> the only sane way. Real power numbers vs complexity please.
>
> One problem is that there might not be a safe set of values that satisfy
> both current and future constraints.

How about: disable all the LP watermarks and set the maximum values to
all non-LP WMs?


> One example could be a "low bpp/no
> primary + sprite -> high bpp primary + no sprite" case. I guess we could
> just reject such changes, but that feels a bit wrong. It would introduce
> a weird restriction that would propably baffle userspace (doing a->c fails
> but doing a->b->wait_for_vbl->c works), or we'd need to block for one frame
> which is a big no-no these days.
>
> Also we would still need to track how the current hardware state
> changes across vblanks, so it would still end up doing some extra
> stuff at irq time.
>
> My hope was that the current approach wouldn't turn out to be too
> expensive. Whether people consider 5 usec excessive, I don't know.
> And maybe we could shave some of that off still.
>
> Not that I'm 100% attached to the current design. We could certainly
> try other ways, if people think that's worthwile.
>
> --
> Ville Syrjälä
> Intel OTC
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
  2013-07-05  8:57 ` [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code ville.syrjala
  2013-07-05  9:37   ` Chris Wilson
@ 2013-07-05 17:51   ` Paulo Zanoni
  2013-07-05 18:11     ` Ville Syrjälä
  1 sibling, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-05 17:51 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> There is a major problem with the watermark registers; they're not
> double buffered. So we need to make sure we update them at the correct
> time when messing about with planes. The correct time is the beginning
> of vblank.
>
> So when we determine that the watermarks need to updated hand in hand
> with the next vblank, we store the pre-computed watermarks under
> intel_crtc, and when the vblank happens, we promote the pending
> watermarks to active status.
>
> on HSW when the watermarks for any pipe change, we must merge the
> watermarks from all pipes so that we can determine the correct LP1+
> watermark levels. For simplicity we follow the same codepaths for
> pre-HSW hardware as well, but there all the LP1+ watermarks will be
> disabled when multiple pipes are enabled. Once the watermarks are
> merged we check them for validity, disabling any invalid levels.
>
> Touching the watermark registers causes the hardware to re-evaluate the
> watermarks, which expeds some power. So after merging the watermarks
> we check which watermark registers actually need to be changed. And
> finally we write the watermarks registers in the correct order.

This patch is way too big for us, poor reviewers. Can you split this
into many many many tiny patches? I see *a lot* of different changes
here.


>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h  |   12 +
>  drivers/gpu/drm/i915/i915_irq.c  |   12 +-
>  drivers/gpu/drm/i915/i915_reg.h  |    2 +
>  drivers/gpu/drm/i915/intel_drv.h |   22 +
>  drivers/gpu/drm/i915/intel_pm.c  | 1546 ++++++++++++++++----------------------
>  5 files changed, 686 insertions(+), 908 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index fd57bed..446be9a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1198,6 +1198,7 @@ typedef struct drm_i915_private {
>
>         struct i915_suspend_saved_registers regfile;
>
> +       /* per-device watermark state */
>         struct {
>                 /* watermark latency values for primary */
>                 uint16_t pri_latency[5];
> @@ -1205,6 +1206,17 @@ typedef struct drm_i915_private {
>                 uint16_t spr_latency[5];
>                 /* watermark latency values for cursor */
>                 uint16_t cur_latency[5];
> +               /* protects all watermark state */
> +               spinlock_t lock;
> +               /* current state of FBC_WM */
> +               bool fbc_wm_enabled;
> +               /* current state of DDB partitioning */
> +               enum intel_ddb_partitioning ddb_partitioning;
> +               /*
> +                * LP1+ values currently programmed into the hardware
> +                * [0] = LP1, [1] = LP2, [2] = LP3
> +                */
> +               struct intel_wm_level hw[3];
>         } wm;
>
>         /* Old dri1 support infrastructure, beware the dragons ya fools entering
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 4c1b1e3..ee5127f 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -1240,8 +1240,10 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
>                         intel_opregion_asle_intr(dev);
>
>                 for (i = 0; i < 3; i++) {
> -                       if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
> +                       if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i))) {
> +                               ilk_update_pipe_wm(dev, i);
>                                 drm_handle_vblank(dev, i);
> +                       }
>                         if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
>                                 intel_prepare_page_flip(dev, i);
>                                 intel_finish_page_flip_plane(dev, i);
> @@ -1343,11 +1345,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
>         if (de_iir & DE_GSE)
>                 intel_opregion_asle_intr(dev);
>
> -       if (de_iir & DE_PIPEA_VBLANK)
> +       if (de_iir & DE_PIPEA_VBLANK) {
> +               ilk_update_pipe_wm(dev, 0);
>                 drm_handle_vblank(dev, 0);
> +       }
>
> -       if (de_iir & DE_PIPEB_VBLANK)
> +       if (de_iir & DE_PIPEB_VBLANK) {
> +               ilk_update_pipe_wm(dev, 1);
>                 drm_handle_vblank(dev, 1);
> +       }
>
>         if (de_iir & DE_POISON)
>                 DRM_ERROR("Poison interrupt\n");
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 9b51be8..e595f54 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3762,6 +3762,8 @@
>  #define DISP_ARB_CTL   0x45000
>  #define  DISP_TILE_SURFACE_SWIZZLING   (1<<13)
>  #define  DISP_FBC_WM_DIS               (1<<15)
> +#define DISP_ARB_CTL2  0x45004
> +#define  DISP_DATA_PARTITION_5_6       (1<<6)
>  #define GEN7_MSG_CTL   0x45010
>  #define  WAIT_FOR_PCH_RESET_ACK                (1<<1)
>  #define  WAIT_FOR_PCH_FLR_ACK          (1<<0)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 4afaeb2..a5c15ab 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -292,6 +292,15 @@ struct intel_crtc_config {
>         bool ips_enabled;
>  };
>
> +struct intel_pipe_wm {
> +       bool pipe_enabled;
> +       bool sprites_enabled;
> +       bool sprites_scaled;
> +       bool fbc_wm_enabled;
> +       uint32_t linetime;
> +       struct intel_wm_level wm[5];
> +};
> +
>  struct intel_crtc {
>         struct drm_crtc base;
>         enum pipe pipe;
> @@ -332,6 +341,18 @@ struct intel_crtc {
>         /* Access to these should be protected by dev_priv->irq_lock. */
>         bool cpu_fifo_underrun_disabled;
>         bool pch_fifo_underrun_disabled;
> +
> +       /* per-pipe watermark state */
> +       struct {
> +               /* watermarks queued for next vblank */
> +               struct intel_pipe_wm pending;
> +               /* watermarks currently being used  */
> +               struct intel_pipe_wm active;
> +               /* LP0 values currently programmed into the hardware */
> +               struct intel_wm_level hw;
> +               /* indicates that 'pending' contains changed watermarks */
> +               bool dirty;
> +       } wm;
>  };
>
>  struct intel_plane_wm_parameters {
> @@ -838,5 +859,6 @@ extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
>  extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
>                                                  enum transcoder pch_transcoder,
>                                                  bool enable);
> +extern void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe);
>
>  #endif /* __INTEL_DRV_H__ */
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c4e94bb..7fd922dc 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -32,6 +32,11 @@
>  #include <linux/module.h>
>  #include <drm/i915_powerwell.h>
>
> +static const char *yesno(int v)
> +{
> +       return v ? "yes" : "no";
> +}
> +
>  #define FORCEWAKE_ACK_TIMEOUT_MS 2
>
>  /* FBC, or Frame Buffer Compression, is a technique employed to compress the
> @@ -1668,424 +1673,6 @@ static void i830_update_wm(struct drm_crtc *crtc)
>         I915_WRITE(FW_BLC, fwater_lo);
>  }
>
> -#define ILK_LP0_PLANE_LATENCY          700
> -#define ILK_LP0_CURSOR_LATENCY         1300
> -
> -/*
> - * Check the wm result.
> - *
> - * If any calculated watermark values is larger than the maximum value that
> - * can be programmed into the associated watermark register, that watermark
> - * must be disabled.
> - */
> -static bool ironlake_check_srwm(struct drm_device *dev, int level,
> -                               int fbc_wm, int display_wm, int cursor_wm,
> -                               const struct intel_watermark_params *display,
> -                               const struct intel_watermark_params *cursor)
> -{
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -
> -       DRM_DEBUG_KMS("watermark %d: display plane %d, fbc lines %d,"
> -                     " cursor %d\n", level, display_wm, fbc_wm, cursor_wm);
> -
> -       if (fbc_wm > SNB_FBC_MAX_SRWM) {
> -               DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n",
> -                             fbc_wm, SNB_FBC_MAX_SRWM, level);
> -
> -               /* fbc has it's own way to disable FBC WM */
> -               I915_WRITE(DISP_ARB_CTL,
> -                          I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS);
> -               return false;
> -       } else if (INTEL_INFO(dev)->gen >= 6) {
> -               /* enable FBC WM (except on ILK, where it must remain off) */
> -               I915_WRITE(DISP_ARB_CTL,
> -                          I915_READ(DISP_ARB_CTL) & ~DISP_FBC_WM_DIS);
> -       }
> -
> -       if (display_wm > display->max_wm) {
> -               DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n",
> -                             display_wm, SNB_DISPLAY_MAX_SRWM, level);
> -               return false;
> -       }
> -
> -       if (cursor_wm > cursor->max_wm) {
> -               DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n",
> -                             cursor_wm, SNB_CURSOR_MAX_SRWM, level);
> -               return false;
> -       }
> -
> -       if (!(fbc_wm || display_wm || cursor_wm)) {
> -               DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level);
> -               return false;
> -       }
> -
> -       return true;
> -}
> -
> -/*
> - * Compute watermark values of WM[1-3],
> - */
> -static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
> -                                 int latency_ns,
> -                                 const struct intel_watermark_params *display,
> -                                 const struct intel_watermark_params *cursor,
> -                                 int *fbc_wm, int *display_wm, int *cursor_wm)
> -{
> -       struct drm_crtc *crtc;
> -       unsigned long line_time_us;
> -       int hdisplay, htotal, pixel_size, clock;
> -       int line_count, line_size;
> -       int small, large;
> -       int entries;
> -
> -       if (!latency_ns) {
> -               *fbc_wm = *display_wm = *cursor_wm = 0;
> -               return false;
> -       }
> -
> -       crtc = intel_get_crtc_for_plane(dev, plane);
> -       hdisplay = crtc->mode.hdisplay;
> -       htotal = crtc->mode.htotal;
> -       clock = crtc->mode.clock;
> -       pixel_size = crtc->fb->bits_per_pixel / 8;
> -
> -       line_time_us = (htotal * 1000) / clock;
> -       line_count = (latency_ns / line_time_us + 1000) / 1000;
> -       line_size = hdisplay * pixel_size;
> -
> -       /* Use the minimum of the small and large buffer method for primary */
> -       small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
> -       large = line_count * line_size;
> -
> -       entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
> -       *display_wm = entries + display->guard_size;
> -
> -       /*
> -        * Spec says:
> -        * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2
> -        */
> -       *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2;
> -
> -       /* calculate the self-refresh watermark for display cursor */
> -       entries = line_count * pixel_size * 64;
> -       entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
> -       *cursor_wm = entries + cursor->guard_size;
> -
> -       return ironlake_check_srwm(dev, level,
> -                                  *fbc_wm, *display_wm, *cursor_wm,
> -                                  display, cursor);
> -}
> -
> -static void ironlake_update_wm(struct drm_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->dev;
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       int fbc_wm, plane_wm, cursor_wm;
> -       unsigned int enabled;
> -
> -       enabled = 0;
> -       if (g4x_compute_wm0(dev, PIPE_A,
> -                           &ironlake_display_wm_info,
> -                           ILK_LP0_PLANE_LATENCY,
> -                           &ironlake_cursor_wm_info,
> -                           ILK_LP0_CURSOR_LATENCY,
> -                           &plane_wm, &cursor_wm)) {
> -               I915_WRITE(WM0_PIPEA_ILK,
> -                          (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
> -               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
> -                             " plane %d, " "cursor: %d\n",
> -                             plane_wm, cursor_wm);
> -               enabled |= 1 << PIPE_A;
> -       }
> -
> -       if (g4x_compute_wm0(dev, PIPE_B,
> -                           &ironlake_display_wm_info,
> -                           ILK_LP0_PLANE_LATENCY,
> -                           &ironlake_cursor_wm_info,
> -                           ILK_LP0_CURSOR_LATENCY,
> -                           &plane_wm, &cursor_wm)) {
> -               I915_WRITE(WM0_PIPEB_ILK,
> -                          (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
> -               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
> -                             " plane %d, cursor: %d\n",
> -                             plane_wm, cursor_wm);
> -               enabled |= 1 << PIPE_B;
> -       }
> -
> -       /*
> -        * Calculate and update the self-refresh watermark only when one
> -        * display plane is used.
> -        */
> -       I915_WRITE(WM3_LP_ILK, 0);
> -       I915_WRITE(WM2_LP_ILK, 0);
> -       I915_WRITE(WM1_LP_ILK, 0);
> -
> -       if (!single_plane_enabled(enabled))
> -               return;
> -       enabled = ffs(enabled) - 1;
> -
> -       /* WM1 */
> -       if (!ironlake_compute_srwm(dev, 1, enabled,
> -                                  ILK_READ_WM1_LATENCY() * 500,
> -                                  &ironlake_display_srwm_info,
> -                                  &ironlake_cursor_srwm_info,
> -                                  &fbc_wm, &plane_wm, &cursor_wm))
> -               return;
> -
> -       I915_WRITE(WM1_LP_ILK,
> -                  WM1_LP_SR_EN |
> -                  (ILK_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> -                  (fbc_wm << WM1_LP_FBC_SHIFT) |
> -                  (plane_wm << WM1_LP_SR_SHIFT) |
> -                  cursor_wm);
> -
> -       /* WM2 */
> -       if (!ironlake_compute_srwm(dev, 2, enabled,
> -                                  ILK_READ_WM2_LATENCY() * 500,
> -                                  &ironlake_display_srwm_info,
> -                                  &ironlake_cursor_srwm_info,
> -                                  &fbc_wm, &plane_wm, &cursor_wm))
> -               return;
> -
> -       I915_WRITE(WM2_LP_ILK,
> -                  WM2_LP_EN |
> -                  (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> -                  (fbc_wm << WM1_LP_FBC_SHIFT) |
> -                  (plane_wm << WM1_LP_SR_SHIFT) |
> -                  cursor_wm);
> -
> -       /*
> -        * WM3 is unsupported on ILK, probably because we don't have latency
> -        * data for that power state
> -        */
> -}
> -
> -static void sandybridge_update_wm(struct drm_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->dev;
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
> -       u32 val;
> -       int fbc_wm, plane_wm, cursor_wm;
> -       unsigned int enabled;
> -
> -       enabled = 0;
> -       if (g4x_compute_wm0(dev, PIPE_A,
> -                           &sandybridge_display_wm_info, latency,
> -                           &sandybridge_cursor_wm_info, latency,
> -                           &plane_wm, &cursor_wm)) {
> -               val = I915_READ(WM0_PIPEA_ILK);
> -               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
> -               I915_WRITE(WM0_PIPEA_ILK, val |
> -                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
> -               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
> -                             " plane %d, " "cursor: %d\n",
> -                             plane_wm, cursor_wm);
> -               enabled |= 1 << PIPE_A;
> -       }
> -
> -       if (g4x_compute_wm0(dev, PIPE_B,
> -                           &sandybridge_display_wm_info, latency,
> -                           &sandybridge_cursor_wm_info, latency,
> -                           &plane_wm, &cursor_wm)) {
> -               val = I915_READ(WM0_PIPEB_ILK);
> -               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
> -               I915_WRITE(WM0_PIPEB_ILK, val |
> -                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
> -               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
> -                             " plane %d, cursor: %d\n",
> -                             plane_wm, cursor_wm);
> -               enabled |= 1 << PIPE_B;
> -       }
> -
> -       /*
> -        * Calculate and update the self-refresh watermark only when one
> -        * display plane is used.
> -        *
> -        * SNB support 3 levels of watermark.
> -        *
> -        * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
> -        * and disabled in the descending order
> -        *
> -        */
> -       I915_WRITE(WM3_LP_ILK, 0);
> -       I915_WRITE(WM2_LP_ILK, 0);
> -       I915_WRITE(WM1_LP_ILK, 0);
> -
> -       if (!single_plane_enabled(enabled) ||
> -           dev_priv->sprite_scaling_enabled)
> -               return;
> -       enabled = ffs(enabled) - 1;
> -
> -       /* WM1 */
> -       if (!ironlake_compute_srwm(dev, 1, enabled,
> -                                  SNB_READ_WM1_LATENCY() * 500,
> -                                  &sandybridge_display_srwm_info,
> -                                  &sandybridge_cursor_srwm_info,
> -                                  &fbc_wm, &plane_wm, &cursor_wm))
> -               return;
> -
> -       I915_WRITE(WM1_LP_ILK,
> -                  WM1_LP_SR_EN |
> -                  (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> -                  (fbc_wm << WM1_LP_FBC_SHIFT) |
> -                  (plane_wm << WM1_LP_SR_SHIFT) |
> -                  cursor_wm);
> -
> -       /* WM2 */
> -       if (!ironlake_compute_srwm(dev, 2, enabled,
> -                                  SNB_READ_WM2_LATENCY() * 500,
> -                                  &sandybridge_display_srwm_info,
> -                                  &sandybridge_cursor_srwm_info,
> -                                  &fbc_wm, &plane_wm, &cursor_wm))
> -               return;
> -
> -       I915_WRITE(WM2_LP_ILK,
> -                  WM2_LP_EN |
> -                  (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> -                  (fbc_wm << WM1_LP_FBC_SHIFT) |
> -                  (plane_wm << WM1_LP_SR_SHIFT) |
> -                  cursor_wm);
> -
> -       /* WM3 */
> -       if (!ironlake_compute_srwm(dev, 3, enabled,
> -                                  SNB_READ_WM3_LATENCY() * 500,
> -                                  &sandybridge_display_srwm_info,
> -                                  &sandybridge_cursor_srwm_info,
> -                                  &fbc_wm, &plane_wm, &cursor_wm))
> -               return;
> -
> -       I915_WRITE(WM3_LP_ILK,
> -                  WM3_LP_EN |
> -                  (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> -                  (fbc_wm << WM1_LP_FBC_SHIFT) |
> -                  (plane_wm << WM1_LP_SR_SHIFT) |
> -                  cursor_wm);
> -}
> -
> -static void ivybridge_update_wm(struct drm_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->dev;
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
> -       u32 val;
> -       int fbc_wm, plane_wm, cursor_wm;
> -       int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm;
> -       unsigned int enabled;
> -
> -       enabled = 0;
> -       if (g4x_compute_wm0(dev, PIPE_A,
> -                           &sandybridge_display_wm_info, latency,
> -                           &sandybridge_cursor_wm_info, latency,
> -                           &plane_wm, &cursor_wm)) {
> -               val = I915_READ(WM0_PIPEA_ILK);
> -               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
> -               I915_WRITE(WM0_PIPEA_ILK, val |
> -                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
> -               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
> -                             " plane %d, " "cursor: %d\n",
> -                             plane_wm, cursor_wm);
> -               enabled |= 1 << PIPE_A;
> -       }
> -
> -       if (g4x_compute_wm0(dev, PIPE_B,
> -                           &sandybridge_display_wm_info, latency,
> -                           &sandybridge_cursor_wm_info, latency,
> -                           &plane_wm, &cursor_wm)) {
> -               val = I915_READ(WM0_PIPEB_ILK);
> -               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
> -               I915_WRITE(WM0_PIPEB_ILK, val |
> -                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
> -               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
> -                             " plane %d, cursor: %d\n",
> -                             plane_wm, cursor_wm);
> -               enabled |= 1 << PIPE_B;
> -       }
> -
> -       if (g4x_compute_wm0(dev, PIPE_C,
> -                           &sandybridge_display_wm_info, latency,
> -                           &sandybridge_cursor_wm_info, latency,
> -                           &plane_wm, &cursor_wm)) {
> -               val = I915_READ(WM0_PIPEC_IVB);
> -               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
> -               I915_WRITE(WM0_PIPEC_IVB, val |
> -                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
> -               DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
> -                             " plane %d, cursor: %d\n",
> -                             plane_wm, cursor_wm);
> -               enabled |= 1 << PIPE_C;
> -       }
> -
> -       /*
> -        * Calculate and update the self-refresh watermark only when one
> -        * display plane is used.
> -        *
> -        * SNB support 3 levels of watermark.
> -        *
> -        * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
> -        * and disabled in the descending order
> -        *
> -        */
> -       I915_WRITE(WM3_LP_ILK, 0);
> -       I915_WRITE(WM2_LP_ILK, 0);
> -       I915_WRITE(WM1_LP_ILK, 0);
> -
> -       if (!single_plane_enabled(enabled) ||
> -           dev_priv->sprite_scaling_enabled)
> -               return;
> -       enabled = ffs(enabled) - 1;
> -
> -       /* WM1 */
> -       if (!ironlake_compute_srwm(dev, 1, enabled,
> -                                  SNB_READ_WM1_LATENCY() * 500,
> -                                  &sandybridge_display_srwm_info,
> -                                  &sandybridge_cursor_srwm_info,
> -                                  &fbc_wm, &plane_wm, &cursor_wm))
> -               return;
> -
> -       I915_WRITE(WM1_LP_ILK,
> -                  WM1_LP_SR_EN |
> -                  (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> -                  (fbc_wm << WM1_LP_FBC_SHIFT) |
> -                  (plane_wm << WM1_LP_SR_SHIFT) |
> -                  cursor_wm);
> -
> -       /* WM2 */
> -       if (!ironlake_compute_srwm(dev, 2, enabled,
> -                                  SNB_READ_WM2_LATENCY() * 500,
> -                                  &sandybridge_display_srwm_info,
> -                                  &sandybridge_cursor_srwm_info,
> -                                  &fbc_wm, &plane_wm, &cursor_wm))
> -               return;
> -
> -       I915_WRITE(WM2_LP_ILK,
> -                  WM2_LP_EN |
> -                  (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> -                  (fbc_wm << WM1_LP_FBC_SHIFT) |
> -                  (plane_wm << WM1_LP_SR_SHIFT) |
> -                  cursor_wm);
> -
> -       /* WM3, note we have to correct the cursor latency */
> -       if (!ironlake_compute_srwm(dev, 3, enabled,
> -                                  SNB_READ_WM3_LATENCY() * 500,
> -                                  &sandybridge_display_srwm_info,
> -                                  &sandybridge_cursor_srwm_info,
> -                                  &fbc_wm, &plane_wm, &ignore_cursor_wm) ||
> -           !ironlake_compute_srwm(dev, 3, enabled,
> -                                  2 * SNB_READ_WM3_LATENCY() * 500,
> -                                  &sandybridge_display_srwm_info,
> -                                  &sandybridge_cursor_srwm_info,
> -                                  &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm))
> -               return;
> -
> -       I915_WRITE(WM3_LP_ILK,
> -                  WM3_LP_EN |
> -                  (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> -                  (fbc_wm << WM1_LP_FBC_SHIFT) |
> -                  (plane_wm << WM1_LP_SR_SHIFT) |
> -                  cursor_wm);
> -}
> -
>  static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
>                                     struct drm_crtc *crtc)
>  {
> @@ -2168,14 +1755,6 @@ struct hsw_wm_maximums {
>         uint16_t fbc;
>  };
>
> -struct hsw_wm_values {
> -       uint32_t wm_pipe[3];
> -       uint32_t wm_lp[3];
> -       uint32_t wm_lp_spr[3];
> -       uint32_t wm_linetime[3];
> -       bool enable_fbc_wm;
> -};
> -
>  /* used in computing the new watermarks state */
>  struct intel_wm_config {
>         unsigned int pipes_active;
> @@ -2351,6 +1930,16 @@ static void ilk_wm_max(struct drm_device *dev,
>         max->fbc = ilk_fbc_wm_max();
>  }
>
> +/*
> + * We use memcmp() to determine if watermarks need updating,
> + * so keeping all disabled watermark levels consistently
> + * zeroed avoids false positives.
> + */
> +static void ilk_disable_wm_level(struct intel_wm_level *wm)
> +{
> +       memset(wm, 0, sizeof(*wm));
> +}
> +
>  static bool ilk_check_wm(int level,
>                          const struct hsw_wm_maximums *max,
>                          struct intel_wm_level *result)
> @@ -2381,6 +1970,9 @@ static bool ilk_check_wm(int level,
>
>         DRM_DEBUG_KMS("WM%d: %sabled\n", level, result->enable ? "en" : "dis");
>
> +       if (!result->enable)
> +               ilk_disable_wm_level(result);
> +
>         return ret;
>  }
>
> @@ -2406,52 +1998,603 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
>         result->enable = true;
>  }
>
> -static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
> -                             int level, struct hsw_wm_maximums *max,
> -                             struct hsw_pipe_wm_parameters *params,
> -                             struct intel_wm_level *result)
> -{
> -       enum pipe pipe;
> -       struct intel_wm_level res[3];
> -
> -       for (pipe = PIPE_A; pipe <= PIPE_C; pipe++)
> -               ilk_compute_wm_level(dev_priv, level, &params[pipe], &res[pipe]);
> -
> -       result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val);
> -       result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val);
> -       result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val);
> -       result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val);
> -       result->enable = true;
> -
> -       return ilk_check_wm(level, max, result);
> -}
> -
> -static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
> -                                   enum pipe pipe,
> -                                   struct hsw_pipe_wm_parameters *params)
> -{
> -       uint32_t pri_val, cur_val, spr_val;
> -       uint16_t pri_latency = dev_priv->wm.pri_latency[0];
> -       uint16_t spr_latency = dev_priv->wm.spr_latency[0];
> -       uint16_t cur_latency = dev_priv->wm.cur_latency[0];
> -
> -       pri_val = ilk_compute_pri_wm(params, pri_latency, 0);
> -       spr_val = ilk_compute_spr_wm(params, spr_latency);
> -       cur_val = ilk_compute_cur_wm(params, cur_latency);
> -
> -       WARN(pri_val > 127,
> -            "Primary WM error, mode not supported for pipe %c\n",
> -            pipe_name(pipe));
> -       WARN(spr_val > 127,
> -            "Sprite WM error, mode not supported for pipe %c\n",
> -            pipe_name(pipe));
> -       WARN(cur_val > 63,
> -            "Cursor WM error, mode not supported for pipe %c\n",
> -            pipe_name(pipe));
> -
> -       return (pri_val << WM0_PIPE_PLANE_SHIFT) |
> -              (spr_val << WM0_PIPE_SPRITE_SHIFT) |
> -              cur_val;
> +/* The value we need to program into the WM_LPx latency field */
> +static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev))
> +               return 2 * level;
> +       else
> +               return dev_priv->wm.pri_latency[level];
> +}
> +
> +/*
> + * Merge the watermarks from all active pipes for a specific level.
> + */
> +static void ilk_merge_wm_level(struct drm_device *dev,
> +                              int level,
> +                              struct intel_wm_level *ret_wm)
> +{
> +       struct intel_crtc *intel_crtc;
> +
> +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
> +               const struct intel_pipe_wm *pipe_wm = &intel_crtc->wm.active;
> +               const struct intel_wm_level *wm = &pipe_wm->wm[level];
> +
> +               if (!pipe_wm->pipe_enabled)
> +                       continue;
> +
> +               if (!wm->enable)
> +                       break;
> +
> +               ret_wm->enable = true;
> +               ret_wm->pri_val = max(ret_wm->pri_val, wm->pri_val);
> +               ret_wm->spr_val = max(ret_wm->spr_val, wm->spr_val);
> +               ret_wm->cur_val = max(ret_wm->cur_val, wm->cur_val);
> +               ret_wm->fbc_val = max(ret_wm->fbc_val, wm->fbc_val);
> +       }
> +}
> +
> +/*
> + * Merge all low power watermarks for all active pipes.
> + */
> +static void ilk_wm_merge(struct drm_device *dev,
> +                        struct intel_wm_config *config,
> +                        struct intel_pipe_wm *merged)
> +{
> +       int level;
> +
> +       /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
> +       if (config->pipes_active > 1 &&
> +           (INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)))
> +               return;
> +
> +       /* ILK: FBC WM must remain disabled */
> +       merged->fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6;
> +
> +       /* merge each level */
> +       for (level = 1; level <= 4; level++) {
> +               struct intel_wm_level *wm = &merged->wm[level];
> +
> +               ilk_merge_wm_level(dev, level, wm);
> +       }
> +}
> +
> +static void ilk_wm_limit(struct drm_device *dev,
> +                        const struct intel_wm_config *config,
> +                        const struct hsw_wm_maximums *max,
> +                        struct intel_pipe_wm *merged)
> +{
> +       int level;
> +
> +       for (level = 1; level <= 4; level++) {
> +               struct intel_wm_level *wm = &merged->wm[level];
> +
> +               if (!ilk_check_wm(level, max, wm))
> +                       break;
> +
> +               /*
> +                * If FBC WM is exceeded, disable just FBC WM
> +                * instead if the whole level.
> +                */
> +               if (wm->fbc_val > max->fbc)
> +                       merged->fbc_wm_enabled = false;
> +       }
> +
> +       if (merged->fbc_wm_enabled)
> +               return;
> +
> +       /* Make sure we don't write garbage to the registers, */
> +       for (level = 1; level <= 4; level++) {
> +               struct intel_wm_level *wm = &merged->wm[level];
> +
> +               wm->fbc_val = 0;
> +       }
> +
> +       /*
> +        * LP2+ watermarks must be disabled when FBC watermark is disabled on ILK
> +        * In practice this is always happens since we always disable FBC WM on ILK.
> +        */
> +       if (INTEL_INFO(dev)->gen == 5 && intel_fbc_enabled(dev)) {
> +               for (level = 2; level <= 4; level++) {
> +                       struct intel_wm_level *wm = &merged->wm[level];
> +
> +                       ilk_disable_wm_level(wm);
> +               }
> +       }
> +}
> +
> +static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *merged)
> +{
> +       /* LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4  */
> +       return wm_lp + (wm_lp >= 2 && merged->wm[4].enable);
> +}
> +
> +/* dirty bits used to track which watermarks need changes */
> +#define WM_DIRTY_PIPE(pipe) (1 << (pipe))
> +#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp)))
> +#define WM_DIRTY_FBC (1 << 24)
> +#define WM_DIRTY_DDB (1 << 25)
> +
> +/* Determine which watermarks registers need reprogramming. */
> +static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
> +                                        const struct intel_wm_config *config,
> +                                        enum intel_ddb_partitioning ddb_partitioning,
> +                                        const struct intel_pipe_wm *merged)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct intel_crtc *intel_crtc;
> +       unsigned int dirty = 0;
> +       int wm_lp;
> +
> +       /* Do LP0 watermarks need updates? */
> +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
> +               const struct intel_wm_level *wm = &intel_crtc->wm.active.wm[0];
> +
> +               if (memcmp(&intel_crtc->wm.hw, wm, sizeof(*wm)))
> +                       dirty |= WM_DIRTY_PIPE(intel_crtc->pipe);
> +       }
> +
> +       if (config->fbc_wm_enabled != dev_priv->wm.fbc_wm_enabled)
> +               dirty |= WM_DIRTY_FBC;
> +
> +       if (ddb_partitioning != dev_priv->wm.ddb_partitioning)
> +               dirty |= WM_DIRTY_DDB;
> +
> +       /* Need to disable LP1+ watermarks when changing DDB/FBC WM */
> +       if (dirty & (WM_DIRTY_FBC | WM_DIRTY_DDB)) {
> +               dirty |= WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3);
> +
> +               /* LP1+ watermarks already deemed dirty, no need to continue */
> +               return dirty;
> +       }
> +
> +       /* Find the lowest numbered LP1+ watermark in need of an update... */
> +       for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
> +               int level = ilk_wm_lp_to_level(wm_lp, merged);
> +               const struct intel_wm_level *wm = &merged->wm[level];
> +
> +               if (memcmp(&dev_priv->wm.hw[wm_lp - 1], wm, sizeof(*wm)))
> +                       break;
> +       }
> +
> +       /* ...and mark it and all higher numbered LP1+ watermarks as dirty */
> +       for (; wm_lp <= 3; wm_lp++)
> +               dirty |= WM_DIRTY_LP(wm_lp);
> +
> +       return dirty;
> +}
> +
> +/* Disable LP1+ watermarks */
> +static void ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
> +                             unsigned int dirty)
> +{
> +       int wm_lp;
> +
> +       for (wm_lp = 3; wm_lp >= 1; wm_lp--) {
> +               static const unsigned int ilk_wm_lp_reg[] = {
> +                       [1] = WM1_LP_ILK,
> +                       [2] = WM2_LP_ILK,
> +                       [3] = WM3_LP_ILK,
> +               };
> +               struct intel_wm_level *hw = &dev_priv->wm.hw[wm_lp - 1];
> +
> +               if (!(dirty & WM_DIRTY_LP(wm_lp))) {
> +                       /* all lower dirty bits must be set when a higher bit is set */
> +                       WARN_ON(wm_lp > 1 && dirty & WM_DIRTY_LP(wm_lp - 1));
> +                       WARN_ON(wm_lp > 2 && dirty & WM_DIRTY_LP(wm_lp - 2));
> +                       break;
> +               }
> +
> +               /* This LP watermark already disabled? */
> +               if (!hw->enable)
> +                       continue;
> +
> +               DRM_DEBUG_KMS("disabling LP%d watermark\n", wm_lp);
> +
> +               /*
> +                * Simply writing 0 to the register in the middle of the frame
> +                * can cause immediate underruns on ILK. Instead we must clear
> +                * only the enable bit. I assume the hardware will take a while
> +                * to get out of low power mode, during which time it still
> +                * consults the watermarks levels.
> +                */
> +               I915_WRITE(ilk_wm_lp_reg[wm_lp],
> +                          I915_READ(ilk_wm_lp_reg[wm_lp]) & ~WM1_LP_SR_EN);
> +
> +               /* ILK/SNB have a separate enable bit for sprite LP1 watermark */
> +               if (hw->spr_val && INTEL_INFO(dev_priv->dev)->gen <= 6) {
> +                       WARN_ON(wm_lp != 1);
> +                       I915_WRITE(WM1S_LP_ILK, I915_READ(WM1S_LP_ILK) & ~WM1S_LP_EN);
> +               }
> +
> +               ilk_disable_wm_level(hw);
> +       }
> +}
> +
> +struct intel_pipe_wm *ivb_find_best_wm(struct intel_pipe_wm *r1,
> +                                      struct intel_pipe_wm *r2)
> +{
> +       int level, level1 = 0, level2 = 0;
> +
> +       for (level = 1; level <= 4; level++) {
> +               if (r1->wm[level].enable)
> +                       level1 = level;
> +               if (r2->wm[level].enable)
> +                       level2 = level;
> +       }
> +
> +       if (level1 == level2) {
> +               if (r2->fbc_wm_enabled && !r1->fbc_wm_enabled)
> +                       return r2;
> +               else
> +                       return r1;
> +       } else if (level1 > level2) {
> +               return r1;
> +       } else {
> +               return r2;
> +       }
> +}
> +
> +/* Program the watermark registers */
> +static void ilk_program_watermarks(struct drm_device *dev)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct drm_crtc *crtc;
> +       struct intel_pipe_wm merged_1_2 = {}, merged_5_6 = {}, *merged;
> +       struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
> +       int wm_lp;
> +       unsigned int dirty;
> +       struct intel_wm_config config = {};
> +       struct intel_crtc *intel_crtc;
> +       enum intel_ddb_partitioning ddb_partitioning;
> +
> +       /* ILK: FBC WM must remain disabled */
> +       config.fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6 && intel_fbc_enabled(dev);
> +
> +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
> +               const struct intel_pipe_wm *wm = &intel_crtc->wm.active;
> +
> +               if (!wm->pipe_enabled)
> +                       continue;
> +
> +               config.sprites_enabled |= wm->sprites_enabled;
> +               config.sprites_scaled |= wm->sprites_scaled;
> +               config.pipes_active++;
> +       }
> +
> +       ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &lp_max_1_2);
> +
> +       ilk_wm_merge(dev, &config, &merged_1_2);
> +
> +       /* 5/6 DDB partitioning only in single pipe config on IVB+ */
> +       if (INTEL_INFO(dev)->gen >= 7 && config.pipes_active <= 1) {
> +               ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &lp_max_5_6);
> +
> +               merged_5_6 = merged_1_2;
> +
> +               ilk_wm_limit(dev, &config, &lp_max_1_2, &merged_1_2);
> +               ilk_wm_limit(dev, &config, &lp_max_5_6, &merged_5_6);
> +
> +               merged = ivb_find_best_wm(&merged_1_2, &merged_5_6);
> +       } else {
> +               ilk_wm_limit(dev, &config, &lp_max_1_2, &merged_1_2);
> +               merged = &merged_1_2;
> +       }
> +
> +       ddb_partitioning = merged == &merged_1_2 ?
> +               INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
> +
> +       DRM_DEBUG_KMS("WM: pipes  active=%u, sprites enabled=%s, "
> +                     "sprites scaled=%s, FBC WM enabled=%s, "
> +                     "DDB partitioning=%s\n",
> +                     config.pipes_active,
> +                     yesno(config.sprites_enabled),
> +                     yesno(config.sprites_scaled),
> +                     yesno(config.fbc_wm_enabled),
> +                     ddb_partitioning == INTEL_DDB_PART_1_2 ? "1/2" : "5/6");
> +
> +       dirty = ilk_compute_wm_dirty(dev, &config, ddb_partitioning, merged);
> +       if (!dirty) {
> +               DRM_DEBUG_KMS("WM: all clean\n");
> +               return;
> +       }
> +
> +       DRM_DEBUG_KMS("WM: dirty %s%s%s%s%s%s%s%s\n",
> +                     dirty & WM_DIRTY_DDB ? "DDB," : "",
> +                     dirty & WM_DIRTY_FBC ? "FBC," : "",
> +                     dirty & WM_DIRTY_LP(3) ? "LP3," : "",
> +                     dirty & WM_DIRTY_LP(2) ? "LP2," : "",
> +                     dirty & WM_DIRTY_LP(1) ? "LP1," : "",
> +                     dirty & WM_DIRTY_PIPE(PIPE_A) ? "LP0(A)," : "",
> +                     dirty & WM_DIRTY_PIPE(PIPE_B) ? "LP0(B)," : "",
> +                     dirty & WM_DIRTY_PIPE(PIPE_C) ? "LP0(C)," : "");
> +
> +       /*
> +        * LP1+ watermarks need to be disabled prior to
> +        * changing DDB partitioning, FBC watermark disable,
> +        * or lower numbered LP1+ watermarks. "dirty" knows
> +        * which watermarks need disabling.
> +        */
> +       ilk_disable_lp_wm(dev_priv, dirty);
> +
> +       /* program LP0 watermarks */
> +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> +               static const unsigned int ilk_wm0_pipe_reg[] = {
> +                       [PIPE_A] = WM0_PIPEA_ILK,
> +                       [PIPE_B] = WM0_PIPEB_ILK,
> +                       [PIPE_C] = WM0_PIPEC_IVB,
> +               };
> +               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +               const struct intel_pipe_wm *pipe_wm = &intel_crtc->wm.active;
> +               const struct intel_wm_level *wm = &pipe_wm->wm[0];
> +
> +               if (!(dirty & WM_DIRTY_PIPE(intel_crtc->pipe)))
> +                       continue;
> +
> +               DRM_DEBUG_KMS("Pipe %c LP0: pri=%u, spr=%u, cur=%u\n",
> +                             pipe_name(intel_crtc->pipe),
> +                             wm->pri_val, wm->spr_val, wm->cur_val);
> +
> +               I915_WRITE(ilk_wm0_pipe_reg[intel_crtc->pipe],
> +                          wm->pri_val << WM0_PIPE_PLANE_SHIFT |
> +                          wm->spr_val << WM0_PIPE_SPRITE_SHIFT |
> +                          wm->cur_val);
> +
> +               if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev))
> +                       I915_WRITE(PIPE_WM_LINETIME(intel_crtc->pipe),
> +                                  pipe_wm->linetime);
> +
> +               intel_crtc->wm.hw = *wm;
> +       }
> +
> +       /* configure FBC watermark */
> +       if (dirty & WM_DIRTY_FBC) {
> +               uint32_t tmp = I915_READ(DISP_ARB_CTL);
> +
> +               DRM_DEBUG_KMS("WM: FBC watermark = %s\n", yesno(config.fbc_wm_enabled));
> +
> +               if (config.fbc_wm_enabled)
> +                       tmp &= ~DISP_FBC_WM_DIS;
> +               else
> +                       tmp |= DISP_FBC_WM_DIS;
> +
> +               I915_WRITE(DISP_ARB_CTL, tmp);
> +
> +               dev_priv->wm.fbc_wm_enabled = config.fbc_wm_enabled;
> +       }
> +
> +       /* configure DDB partitioning */
> +       if (dirty & WM_DIRTY_DDB) {
> +               DRM_DEBUG_KMS("WM: DDB partitioning = %s\n",
> +                             ddb_partitioning == INTEL_DDB_PART_1_2 ? "1/2" : "5/6");
> +
> +               if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev)) {
> +                       uint32_t tmp = I915_READ(WM_MISC);
> +
> +                       if (ddb_partitioning == INTEL_DDB_PART_5_6)
> +                               tmp |= WM_MISC_DATA_PARTITION_5_6;
> +                       else
> +                               tmp &= ~WM_MISC_DATA_PARTITION_5_6;
> +
> +                       I915_WRITE(DISP_ARB_CTL, tmp);
> +               } else {
> +                       uint32_t tmp = I915_READ(DISP_ARB_CTL2);
> +
> +                       if (ddb_partitioning == INTEL_DDB_PART_5_6)
> +                               tmp |= DISP_DATA_PARTITION_5_6;
> +                       else
> +                               tmp &= ~DISP_DATA_PARTITION_5_6;
> +
> +                       I915_WRITE(DISP_ARB_CTL2, tmp);
> +               }
> +
> +               dev_priv->wm.ddb_partitioning = ddb_partitioning;
> +       }
> +
> +       /* program LP1+ watermarks */
> +       for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
> +               static const unsigned int wm_lp_reg[] = {
> +                       [1] = WM1_LP_ILK,
> +                       [2] = WM2_LP_ILK,
> +                       [3] = WM3_LP_ILK,
> +               };
> +               static const unsigned int wm_spr_lp_reg[] = {
> +                       [1] = WM1S_LP_ILK,
> +                       [2] = WM2S_LP_IVB,
> +                       [3] = WM3S_LP_IVB,
> +               };
> +               int level = ilk_wm_lp_to_level(wm_lp, merged);
> +               const struct intel_wm_level *wm = &merged->wm[level];
> +
> +               if (!wm->enable)
> +                       break;
> +
> +               if (!(dirty & WM_DIRTY_LP(wm_lp)))
> +                       continue;
> +
> +               DRM_DEBUG_KMS("LP%d (level %d): pri=%u, spr=%u, cur=%u, fbc=%u, latency=%u\n",
> +                             wm_lp, level, wm->pri_val, wm->spr_val,
> +                             wm->cur_val, wm->fbc_val, ilk_wm_lp_latency(dev, level));
> +
> +               if (wm->spr_val) {
> +                       if (INTEL_INFO(dev)->gen <= 6) {
> +                               WARN_ON(wm_lp != 1);
> +                               I915_WRITE(WM1S_LP_ILK, WM1S_LP_EN | wm->spr_val);
> +                       } else {
> +                               I915_WRITE(wm_spr_lp_reg[wm_lp], wm->spr_val);
> +                       }
> +               }
> +
> +               I915_WRITE(wm_lp_reg[wm_lp], WM1_LP_SR_EN |
> +                          ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT |
> +                          wm->fbc_val << WM1_LP_FBC_SHIFT |
> +                          wm->pri_val << WM1_LP_SR_SHIFT |
> +                          wm->cur_val);
> +
> +               dev_priv->wm.hw[wm_lp - 1] = *wm;
> +       }
> +}
> +
> +static uint32_t
> +hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc);
> +
> +static int ilk_max_wm_level(const struct drm_device *dev,
> +                           const struct intel_pipe_wm *pipe_wm)
> +{
> +       /* HSW: LP1+ watermarks allowed even with multiple pipes */
> +       if (INTEL_INFO(dev)->gen > 7 || IS_HASWELL(dev)) {
> +               WARN_ON(pipe_wm->sprites_scaled);
> +               return 4;
> +       }
> +
> +       /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
> +       if (pipe_wm->sprites_scaled)
> +               return 0;
> +
> +       /* ILK/SNB: LP2+ watermarks only w/o sprites */
> +       if (INTEL_INFO(dev)->gen <= 6 && pipe_wm->sprites_enabled)
> +               return 1;
> +
> +       return 3;
> +}
> +
> +/* Compute new watermarks for the pipe */
> +static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
> +                                 struct intel_pipe_wm *pipe_wm)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       struct hsw_wm_maximums max;
> +       struct drm_plane *plane;
> +       struct hsw_pipe_wm_parameters p = {};
> +       struct intel_wm_config config = {};
> +       int level, max_level;
> +
> +       p.active = intel_crtc_active(crtc);
> +
> +       if (p.active) {
> +               p.pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
> +               p.pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
> +
> +               /* TODO: for now, assume primary and cursor planes are always enabled. */
> +               p.pri.enabled = true;
> +               p.pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
> +               p.pri.horiz_pixels = intel_crtc->config.requested_mode.hdisplay;
> +
> +               p.cur.enabled = true;
> +               p.cur.bytes_per_pixel = 4;
> +               p.cur.horiz_pixels = 64;
> +
> +               config.pipes_active = 1;
> +       }
> +
> +       list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
> +               struct intel_plane *intel_plane = to_intel_plane(plane);
> +
> +               if (intel_plane->pipe != intel_crtc->pipe)
> +                       continue;
> +
> +               p.spr = intel_plane->wm;
> +
> +               config.sprites_enabled |= p.spr.enabled;
> +               config.sprites_scaled |= p.spr.scaled;
> +       }
> +
> +       pipe_wm->pipe_enabled = p.active;
> +       pipe_wm->sprites_enabled = config.sprites_enabled;
> +       pipe_wm->sprites_scaled = config.sprites_scaled;
> +
> +       max_level = ilk_max_wm_level(dev, pipe_wm);
> +
> +       for (level = 0; level <= max_level; level++)
> +               ilk_compute_wm_level(dev_priv, level, &p, &pipe_wm->wm[level]);
> +
> +       if (IS_HASWELL(dev))
> +               pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
> +
> +       ilk_wm_max(dev, 0, &config, false, &max);
> +
> +       /* At least LP0 must be valid */
> +       return ilk_check_wm(0, &max, &pipe_wm->wm[0]);
> +}
> +
> +/* Prepare the pipe to update the its watermarks on the next vblank */
> +static void intel_setup_pipe_wm(struct intel_crtc *intel_crtc,
> +                               const struct intel_pipe_wm *pipe_wm)
> +{
> +       struct drm_device *dev = intel_crtc->base.dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       int pipe = intel_crtc->pipe;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&dev_priv->wm.lock, flags);
> +
> +       /* do the watermarks actually need changing? */
> +       if (!memcmp(&intel_crtc->wm.pending, pipe_wm, sizeof(*pipe_wm)))
> +               goto out;
> +
> +       /*
> +        * We might already have a pending watermark update, in
> +        * which case we shouldn't grab another vblank reference.
> +        */
> +       if (!intel_crtc->wm.dirty && drm_vblank_get(dev, pipe)) {
> +               if (intel_crtc->active)
> +                       DRM_ERROR("can't setup watermarks for pipe %c\n", pipe_name(pipe));
> +               /* copy the new stuff over anyway. */
> +               intel_crtc->wm.pending = *pipe_wm;
> +               goto out;
> +       }
> +
> +       /*
> +        * When going from no-scaling to scaling, disable LP1+
> +        * watermarks ahead of time.
> +        *
> +        * WaCxSRDisabledForSpriteScaling:ivb
> +        */
> +       /*
> +        * FIXME is this sufficient of do we need extra vbl waits?
> +        * Something like this is needed on IVB. Do we need this on ILK/SNB too?
> +        */
> +       if (!intel_crtc->wm.active.sprites_scaled && pipe_wm->sprites_scaled) {
> +               DRM_DEBUG_KMS("going to enable scaling, disabling LP1+ watermarks\n");
> +               ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP(1) |
> +                                 WM_DIRTY_LP(2) | WM_DIRTY_LP(3));
> +       }
> +
> +       intel_crtc->wm.pending = *pipe_wm;
> +       intel_crtc->wm.dirty = true;
> +       DRM_DEBUG_KMS("pipe %c new watermarks are pending\n", pipe_name(pipe));
> +
> + out:
> +       spin_unlock_irqrestore(&dev_priv->wm.lock, flags);
> +}
> +
> +/* Call from vblank irq */
> +void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&dev_priv->wm.lock, flags);
> +
> +       if (intel_crtc->wm.dirty) {
> +               DRM_DEBUG_KMS("pipe %c vblank, programming new watermarks\n",
> +                             pipe_name(pipe));
> +
> +               drm_vblank_put(dev, pipe);
> +
> +               intel_crtc->wm.active = intel_crtc->wm.pending;
> +               intel_crtc->wm.dirty = false;
> +
> +               ilk_program_watermarks(dev);
> +       }
> +
> +       spin_unlock_irqrestore(&dev_priv->wm.lock, flags);
>  }
>
>  static uint32_t
> @@ -2565,271 +2708,24 @@ static void intel_setup_wm_latency(struct drm_device *dev)
>         intel_print_wm_latency(dev, dev_priv->wm.cur_latency);
>  }
>
> -static void hsw_compute_wm_parameters(struct drm_device *dev,
> -                                     struct hsw_pipe_wm_parameters *params,
> -                                     struct hsw_wm_maximums *lp_max_1_2,
> -                                     struct hsw_wm_maximums *lp_max_5_6)
> +static void ilk_update_wm(struct drm_crtc *crtc)
>  {
> -       struct drm_crtc *crtc;
> -       struct drm_plane *plane;
> -       enum pipe pipe;
> -       struct intel_wm_config config = {};
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       struct intel_pipe_wm pipe_wm = {};
> +       bool ret;
>
> -       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> -               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -               struct hsw_pipe_wm_parameters *p;
> +       ret = intel_compute_pipe_wm(crtc, &pipe_wm);
> +       if (!ret)
> +               DRM_ERROR("crtc %u (pipe %c) LP0 watermarks invalid\n",
> +                         crtc->base.id, pipe_name(intel_crtc->pipe));
>
> -               pipe = intel_crtc->pipe;
> -               p = &params[pipe];
> -
> -               p->active = intel_crtc_active(crtc);
> -               if (!p->active)
> -                       continue;
> -
> -               config.pipes_active++;
> -
> -               p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
> -               p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
> -               p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
> -               p->cur.bytes_per_pixel = 4;
> -               p->pri.horiz_pixels =
> -                       intel_crtc->config.requested_mode.hdisplay;
> -               p->cur.horiz_pixels = 64;
> -               /* TODO: for now, assume primary and cursor planes are always enabled. */
> -               p->pri.enabled = true;
> -               p->cur.enabled = true;
> -       }
> -
> -       list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
> -               struct intel_plane *intel_plane = to_intel_plane(plane);
> -               struct hsw_pipe_wm_parameters *p;
> -
> -               pipe = intel_plane->pipe;
> -               p = &params[pipe];
> -
> -               p->spr = intel_plane->wm;
> -
> -               config.sprites_enabled |= p->spr.enabled;
> -               config.sprites_scaled |= p->spr.scaled;
> -       }
> -
> -       ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
> -
> -       /* 5/6 split only in single pipe config on IVB+ */
> -       if (INTEL_INFO(dev)->gen >= 7 && config.pipes_active <= 1)
> -               ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6);
> -       else
> -               *lp_max_5_6 = *lp_max_1_2;
> -}
> -
> -static void hsw_compute_wm_results(struct drm_device *dev,
> -                                  struct hsw_pipe_wm_parameters *params,
> -                                  struct hsw_wm_maximums *lp_maximums,
> -                                  struct hsw_wm_values *results)
> -{
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct drm_crtc *crtc;
> -       struct intel_wm_level lp_results[4] = {};
> -       enum pipe pipe;
> -       int level, max_level, wm_lp;
> -
> -       for (level = 1; level <= 4; level++)
> -               if (!hsw_compute_lp_wm(dev_priv, level,
> -                                      lp_maximums, params,
> -                                      &lp_results[level - 1]))
> -                       break;
> -       max_level = level - 1;
> -
> -       /* The spec says it is preferred to disable FBC WMs instead of disabling
> -        * a WM level. */
> -       results->enable_fbc_wm = true;
> -       for (level = 1; level <= max_level; level++) {
> -               if (!lp_results[level - 1].fbc_val > lp_maximums->fbc) {
> -                       results->enable_fbc_wm = false;
> -                       lp_results[level - 1].fbc_val = 0;
> -               }
> -       }
> -
> -       memset(results, 0, sizeof(*results));
> -       for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
> -               const struct intel_wm_level *r;
> -
> -               level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp;
> -               if (level > max_level)
> -                       break;
> -
> -               r = &lp_results[level - 1];
> -               results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2,
> -                                                         r->fbc_val,
> -                                                         r->pri_val,
> -                                                         r->cur_val);
> -               results->wm_lp_spr[wm_lp - 1] = r->spr_val;
> -       }
> -
> -       for_each_pipe(pipe)
> -               results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev_priv, pipe,
> -                                                            &params[pipe]);
> -
> -       for_each_pipe(pipe) {
> -               crtc = dev_priv->pipe_to_crtc_mapping[pipe];
> -               results->wm_linetime[pipe] = hsw_compute_linetime_wm(dev, crtc);
> -       }
> -}
> -
> -/* Find the result with the highest level enabled. Check for enable_fbc_wm in
> - * case both are at the same level. Prefer r1 in case they're the same. */
> -static struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1,
> -                                                 struct hsw_wm_values *r2)
> -{
> -       int i, val_r1 = 0, val_r2 = 0;
> -
> -       for (i = 0; i < 3; i++) {
> -               if (r1->wm_lp[i] & WM3_LP_EN)
> -                       val_r1 = r1->wm_lp[i] & WM1_LP_LATENCY_MASK;
> -               if (r2->wm_lp[i] & WM3_LP_EN)
> -                       val_r2 = r2->wm_lp[i] & WM1_LP_LATENCY_MASK;
> -       }
> -
> -       if (val_r1 == val_r2) {
> -               if (r2->enable_fbc_wm && !r1->enable_fbc_wm)
> -                       return r2;
> -               else
> -                       return r1;
> -       } else if (val_r1 > val_r2) {
> -               return r1;
> -       } else {
> -               return r2;
> -       }
> -}
> -
> -/*
> - * The spec says we shouldn't write when we don't need, because every write
> - * causes WMs to be re-evaluated, expending some power.
> - */
> -static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> -                               struct hsw_wm_values *results,
> -                               enum intel_ddb_partitioning partitioning)
> -{
> -       struct hsw_wm_values previous;
> -       uint32_t val;
> -       enum intel_ddb_partitioning prev_partitioning;
> -       bool prev_enable_fbc_wm;
> -
> -       previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
> -       previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
> -       previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
> -       previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
> -       previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
> -       previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
> -       previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> -       previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> -       previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> -       previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
> -       previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
> -       previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
> -
> -       prev_partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> -                               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> -
> -       prev_enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> -
> -       if (memcmp(results->wm_pipe, previous.wm_pipe,
> -                  sizeof(results->wm_pipe)) == 0 &&
> -           memcmp(results->wm_lp, previous.wm_lp,
> -                  sizeof(results->wm_lp)) == 0 &&
> -           memcmp(results->wm_lp_spr, previous.wm_lp_spr,
> -                  sizeof(results->wm_lp_spr)) == 0 &&
> -           memcmp(results->wm_linetime, previous.wm_linetime,
> -                  sizeof(results->wm_linetime)) == 0 &&
> -           partitioning == prev_partitioning &&
> -           results->enable_fbc_wm == prev_enable_fbc_wm)
> -               return;
> -
> -       if (previous.wm_lp[2] != 0)
> -               I915_WRITE(WM3_LP_ILK, 0);
> -       if (previous.wm_lp[1] != 0)
> -               I915_WRITE(WM2_LP_ILK, 0);
> -       if (previous.wm_lp[0] != 0)
> -               I915_WRITE(WM1_LP_ILK, 0);
> -
> -       if (previous.wm_pipe[0] != results->wm_pipe[0])
> -               I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
> -       if (previous.wm_pipe[1] != results->wm_pipe[1])
> -               I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]);
> -       if (previous.wm_pipe[2] != results->wm_pipe[2])
> -               I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]);
> -
> -       if (previous.wm_linetime[0] != results->wm_linetime[0])
> -               I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]);
> -       if (previous.wm_linetime[1] != results->wm_linetime[1])
> -               I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]);
> -       if (previous.wm_linetime[2] != results->wm_linetime[2])
> -               I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
> -
> -       if (prev_partitioning != partitioning) {
> -               val = I915_READ(WM_MISC);
> -               if (partitioning == INTEL_DDB_PART_1_2)
> -                       val &= ~WM_MISC_DATA_PARTITION_5_6;
> -               else
> -                       val |= WM_MISC_DATA_PARTITION_5_6;
> -               I915_WRITE(WM_MISC, val);
> -       }
> -
> -       if (prev_enable_fbc_wm != results->enable_fbc_wm) {
> -               val = I915_READ(DISP_ARB_CTL);
> -               if (results->enable_fbc_wm)
> -                       val &= ~DISP_FBC_WM_DIS;
> -               else
> -                       val |= DISP_FBC_WM_DIS;
> -               I915_WRITE(DISP_ARB_CTL, val);
> -       }
> -
> -       if (previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> -               I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
> -       if (previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> -               I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
> -       if (previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> -               I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
> -
> -       if (results->wm_lp[0] != 0)
> -               I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
> -       if (results->wm_lp[1] != 0)
> -               I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
> -       if (results->wm_lp[2] != 0)
> -               I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
> -}
> -
> -static void haswell_update_wm(struct drm_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->dev;
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
> -       struct hsw_pipe_wm_parameters params[3];
> -       struct hsw_wm_values results_1_2, results_5_6, *best_results;
> -       enum intel_ddb_partitioning partitioning;
> -
> -       hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
> -
> -       hsw_compute_wm_results(dev, params,
> -                              &lp_max_1_2, &results_1_2);
> -       if (lp_max_1_2.pri != lp_max_5_6.pri) {
> -               hsw_compute_wm_results(dev, params,
> -                                      &lp_max_5_6, &results_5_6);
> -               best_results = hsw_find_best_result(&results_1_2, &results_5_6);
> -       } else {
> -               best_results = &results_1_2;
> -       }
> -
> -       partitioning = (best_results == &results_1_2) ?
> -                      INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
> -
> -       hsw_write_wm_values(dev_priv, best_results, partitioning);
> +       intel_setup_pipe_wm(intel_crtc, &pipe_wm);
>  }
>
> -static void haswell_update_sprite_wm(struct drm_plane *plane,
> -                                    struct drm_crtc *crtc,
> -                                    uint32_t sprite_width, int pixel_size,
> -                                    bool enabled, bool scaled)
> +static void ilk_update_sprite_wm(struct drm_plane *plane,
> +                                struct drm_crtc *crtc,
> +                                uint32_t sprite_width, int pixel_size,
> +                                bool enabled, bool scaled)
>  {
>         struct intel_plane *intel_plane = to_intel_plane(plane);
>
> @@ -2838,169 +2734,7 @@ static void haswell_update_sprite_wm(struct drm_plane *plane,
>         intel_plane->wm.horiz_pixels = sprite_width;
>         intel_plane->wm.bytes_per_pixel = pixel_size;
>
> -       haswell_update_wm(crtc);
> -}
> -
> -static bool
> -sandybridge_compute_sprite_wm(struct drm_device *dev, int plane,
> -                             uint32_t sprite_width, int pixel_size,
> -                             const struct intel_watermark_params *display,
> -                             int display_latency_ns, int *sprite_wm)
> -{
> -       struct drm_crtc *crtc;
> -       int clock;
> -       int entries, tlb_miss;
> -
> -       crtc = intel_get_crtc_for_plane(dev, plane);
> -       if (!intel_crtc_active(crtc)) {
> -               *sprite_wm = display->guard_size;
> -               return false;
> -       }
> -
> -       clock = crtc->mode.clock;
> -
> -       /* Use the small buffer method to calculate the sprite watermark */
> -       entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
> -       tlb_miss = display->fifo_size*display->cacheline_size -
> -               sprite_width * 8;
> -       if (tlb_miss > 0)
> -               entries += tlb_miss;
> -       entries = DIV_ROUND_UP(entries, display->cacheline_size);
> -       *sprite_wm = entries + display->guard_size;
> -       if (*sprite_wm > (int)display->max_wm)
> -               *sprite_wm = display->max_wm;
> -
> -       return true;
> -}
> -
> -static bool
> -sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
> -                               uint32_t sprite_width, int pixel_size,
> -                               const struct intel_watermark_params *display,
> -                               int latency_ns, int *sprite_wm)
> -{
> -       struct drm_crtc *crtc;
> -       unsigned long line_time_us;
> -       int clock;
> -       int line_count, line_size;
> -       int small, large;
> -       int entries;
> -
> -       if (!latency_ns) {
> -               *sprite_wm = 0;
> -               return false;
> -       }
> -
> -       crtc = intel_get_crtc_for_plane(dev, plane);
> -       clock = crtc->mode.clock;
> -       if (!clock) {
> -               *sprite_wm = 0;
> -               return false;
> -       }
> -
> -       line_time_us = (sprite_width * 1000) / clock;
> -       if (!line_time_us) {
> -               *sprite_wm = 0;
> -               return false;
> -       }
> -
> -       line_count = (latency_ns / line_time_us + 1000) / 1000;
> -       line_size = sprite_width * pixel_size;
> -
> -       /* Use the minimum of the small and large buffer method for primary */
> -       small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
> -       large = line_count * line_size;
> -
> -       entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
> -       *sprite_wm = entries + display->guard_size;
> -
> -       return *sprite_wm > 0x3ff ? false : true;
> -}
> -
> -static void sandybridge_update_sprite_wm(struct drm_plane *plane,
> -                                        struct drm_crtc *crtc,
> -                                        uint32_t sprite_width, int pixel_size,
> -                                        bool enable, bool scaled)
> -{
> -       struct drm_device *dev = plane->dev;
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       int pipe = to_intel_plane(plane)->pipe;
> -       int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
> -       u32 val;
> -       int sprite_wm, reg;
> -       int ret;
> -
> -       if (!enable)
> -               return;
> -
> -       switch (pipe) {
> -       case 0:
> -               reg = WM0_PIPEA_ILK;
> -               break;
> -       case 1:
> -               reg = WM0_PIPEB_ILK;
> -               break;
> -       case 2:
> -               reg = WM0_PIPEC_IVB;
> -               break;
> -       default:
> -               return; /* bad pipe */
> -       }
> -
> -       ret = sandybridge_compute_sprite_wm(dev, pipe, sprite_width, pixel_size,
> -                                           &sandybridge_display_wm_info,
> -                                           latency, &sprite_wm);
> -       if (!ret) {
> -               DRM_DEBUG_KMS("failed to compute sprite wm for pipe %c\n",
> -                             pipe_name(pipe));
> -               return;
> -       }
> -
> -       val = I915_READ(reg);
> -       val &= ~WM0_PIPE_SPRITE_MASK;
> -       I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));
> -       DRM_DEBUG_KMS("sprite watermarks For pipe %c - %d\n", pipe_name(pipe), sprite_wm);
> -
> -
> -       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
> -                                             pixel_size,
> -                                             &sandybridge_display_srwm_info,
> -                                             SNB_READ_WM1_LATENCY() * 500,
> -                                             &sprite_wm);
> -       if (!ret) {
> -               DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %c\n",
> -                             pipe_name(pipe));
> -               return;
> -       }
> -       I915_WRITE(WM1S_LP_ILK, sprite_wm);
> -
> -       /* Only IVB has two more LP watermarks for sprite */
> -       if (!IS_IVYBRIDGE(dev))
> -               return;
> -
> -       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
> -                                             pixel_size,
> -                                             &sandybridge_display_srwm_info,
> -                                             SNB_READ_WM2_LATENCY() * 500,
> -                                             &sprite_wm);
> -       if (!ret) {
> -               DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %c\n",
> -                             pipe_name(pipe));
> -               return;
> -       }
> -       I915_WRITE(WM2S_LP_IVB, sprite_wm);
> -
> -       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
> -                                             pixel_size,
> -                                             &sandybridge_display_srwm_info,
> -                                             SNB_READ_WM3_LATENCY() * 500,
> -                                             &sprite_wm);
> -       if (!ret) {
> -               DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %c\n",
> -                             pipe_name(pipe));
> -               return;
> -       }
> -       I915_WRITE(WM3S_LP_IVB, sprite_wm);
> +       ilk_update_wm(crtc);
>  }
>
>  /**
> @@ -5372,6 +5106,8 @@ void intel_init_pm(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
>
> +       spin_lock_init(&dev_priv->wm.lock);
> +
>         if (I915_HAS_FBC(dev)) {
>                 if (HAS_PCH_SPLIT(dev)) {
>                         dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
> @@ -5407,9 +5143,10 @@ void intel_init_pm(struct drm_device *dev)
>                 if (IS_GEN5(dev)) {
>                         if (dev_priv->wm.pri_latency[1] &&
>                             dev_priv->wm.spr_latency[1] &&
> -                           dev_priv->wm.cur_latency[1])
> -                               dev_priv->display.update_wm = ironlake_update_wm;
> -                       else {
> +                           dev_priv->wm.cur_latency[1]) {
> +                               dev_priv->display.update_wm = ilk_update_wm;
> +                               dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
> +                       } else {
>                                 DRM_DEBUG_KMS("Failed to get proper latency. "
>                                               "Disable CxSR\n");
>                                 dev_priv->display.update_wm = NULL;
> @@ -5419,8 +5156,8 @@ void intel_init_pm(struct drm_device *dev)
>                         if (dev_priv->wm.pri_latency[0] &&
>                             dev_priv->wm.spr_latency[0] &&
>                             dev_priv->wm.cur_latency[0]) {
> -                               dev_priv->display.update_wm = sandybridge_update_wm;
> -                               dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
> +                               dev_priv->display.update_wm = ilk_update_wm;
> +                               dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
>                         } else {
>                                 DRM_DEBUG_KMS("Failed to read display plane latency. "
>                                               "Disable CxSR\n");
> @@ -5431,8 +5168,8 @@ void intel_init_pm(struct drm_device *dev)
>                         if (dev_priv->wm.pri_latency[0] &&
>                             dev_priv->wm.spr_latency[0] &&
>                             dev_priv->wm.cur_latency[0]) {
> -                               dev_priv->display.update_wm = ivybridge_update_wm;
> -                               dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
> +                               dev_priv->display.update_wm = ilk_update_wm;
> +                               dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
>                         } else {
>                                 DRM_DEBUG_KMS("Failed to read display plane latency. "
>                                               "Disable CxSR\n");
> @@ -5443,9 +5180,8 @@ void intel_init_pm(struct drm_device *dev)
>                         if (dev_priv->wm.pri_latency[0] &&
>                             dev_priv->wm.spr_latency[0] &&
>                             dev_priv->wm.cur_latency[0]) {
> -                               dev_priv->display.update_wm = haswell_update_wm;
> -                               dev_priv->display.update_sprite_wm =
> -                                       haswell_update_sprite_wm;
> +                               dev_priv->display.update_wm = ilk_update_wm;
> +                               dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
>                         } else {
>                                 DRM_DEBUG_KMS("Failed to read display plane latency. "
>                                               "Disable CxSR\n");
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 00/35] drm/i915: ILK+ watermark rewrite
  2013-07-05 17:41     ` Paulo Zanoni
@ 2013-07-05 17:54       ` Ville Syrjälä
  0 siblings, 0 replies; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-05 17:54 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Jul 05, 2013 at 02:41:02PM -0300, Paulo Zanoni wrote:
> 2013/7/5 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> > On Fri, Jul 05, 2013 at 01:54:02PM -0300, Paulo Zanoni wrote:
> >> 2013/7/5  <ville.syrjala@linux.intel.com>:
> >> > Here's my big ILK+ watermark rewrite. The main idea of the series is to
> >> > write the watermark registers at vblank to make the changes (almost) in
> >> > sync with the plane changes that caused the change in watermarks.
> >> >
> >> > I sent a massive RFC patch a while back, and this is now the somewhat
> >> > split up version.
> >> >
> >> > It's still not quite where we need to get wrt. pre-computing and
> >> > properly checking the LP0 watermarks, but at least it gets us a bit
> >> > closer to that goal.
> >> >
> >> > There's quite a bit of refactoring, small fixes, renaming, and what have you
> >> > at the beginning of the series, so a lot of it should be mergeable w/o too much
> >> > risk. Many of the patches only touch codepaths that are used by HSW currently,
> >> > but by the end of the series, ILK,SNB,IVB,HSW are all using the exact same
> >> > code.
> >> >
> >> > So far I've run this somewhat succesfully on ILK and IVB.
> >>
> >> I booted your series on Haswell, on top of drm-intel-nightly.
> >>
> >> I booted with only an eDP output (1920x1080). After booting, I checked
> >> dmesg and there's this message:
> >> [   15.754282] [drm:ilk_update_pipe_wm] *ERROR* pipe A watermark
> >> programming took 94278 ns
> >
> > Just diagnostics to measture the overhead. Do you have some drm.debugs
> > enabled, or why does it take that long? It was ~5 us on my machines w/o
> > debugs, although it could naturally take a bit longer on HSW due to the
> > multi-pipe LP1+ watermarks. But I wasn't expecting 20x increase.
> 
> I constantly have drm.debug=0xe enabled. I imagine QA also uses it,
> and will probably open bug reports about it since the message is
> DRM_ERROR.

Obviosuly we wouldn't merge that thing upstream. It's just a development
aid.

> >> Also, I ran intel_reg_dumper and now WM_PIPE_B and WM_PIPE_C are
> >> enabled with the maximum values, but the watermarks calculator tells
> >> me to use 0 on them. The other values are correct.
> >
> > Not sure where they got the maximum. I was first thinking that it's
> > caused by "return UINT_MAX" change + the clamping LP0 to max instead
> > of failing, but the UINT_MAX thing should only happen when there's no
> > latency value for the level.
> >
> >> Then I plugged a DP monitor (2560x1440), and right after enabling it I
> >> see a new message:
> >> [  323.354641] [drm:ilk_update_pipe_wm] *ERROR* pipe B watermark
> >> programming took 96015 ns
> >>
> >> Then I ran intel_reg_dumper and WM_PIPE_C is still configured with the
> >> maximum values. Also, WM_LP2 and WM_LP3 are enabled, but they
> >> shouldn't be enabled. WM_LP1 has the correct values. Also, when I run
> >> intel_reg_dumper I see screen corruption, but I guess this may be just
> >> a consequence of WM_LP2 and WM_LP3 being enabled.
> >>
> >> Then I disabled the eDP output, leaving only DP. The desktop
> >> environment automagically moved the DP output to pipe A. The WM_PIPE_B
> >> and PIPE_WM_LINETIME_B registers did not get zeroed.
> >
> > Leaving the linetime WM not zeroed was expected. I didn't bother with it
> > since the pipe is off anyway. It should be easy to zero it out if we
> > want to.
> >
> > The pipe watermarks probably didn't get cleared since we update them
> > after turning the pipe off in the disable path. So there won't be any
> > vblank irqs from which to perform the update. We could fix that if we
> > set up the new watermarks just before turning the pipe off. Then we
> > should still get on more vblank irq. But that would need some change
> > to the way we determine that the pipe will be off (crtc->active is
> > updated too late). The other option would be to simply call
> > ilk_update_pipe_wm() from the crtc disable path directly.
> 
> Don't forget that we didn't even zero the LP levels we needed to
> disable when switching from eDP to eDP+DP. I prefer always zeroing
> everything we're not using, since that's what the spec says we need to
> do.

Actually, zeroing the LP watermark registers mid screen causes ILK to
underrun immediately. There's a comment in the code about it. So
instead of zeroing I just opted to flip the enable bit, which works
fine on ILK.

> >> The WM_LP1 values
> >> are correct, but WM_LP2 and WM_LP3 do not match the spec: the WM
> >> calculator disabled the LP4 level, but your code enabled it, so the
> >> value that should be written in WM_LP3 is now in WM_LP2, and WM_LP3 is
> >> wrong.
> >
> > IIRC the wm calculator doesn't take into account the number of available
> > bits in the registeris, so it might give you a larger value than what
> > you can fit in the register. But that doesn't seem to your issue. I
> > would problably want to see the parameters that were used to figure out
> > where things go wrong.
> 
> I already mentioned them:
> Only pipe A enabled, 2560 hsrc, 2720 htotal, 241.50 pixel rate, not
> interlaced, no downscaling, cursor enabled with 4bpp 64hsrc, primary
> enabled with 4bpp, sprite disabled. SSKPD 140000A005A2404F. CDCLK
> 450MHz.

Ah OK. Well, further analysis will have to wait until I get back from my
summer vacation.

> 
> >
> >> So three small bugs: (i) stuff not being correctly zeroed and (ii)
> >> using LP4 as the max level instead of LP3 when using a mode with
> >> 2560hsrc 2720htotal 241.50MHz and (iii) that dmesg error.
> >>
> >>
> >> >
> >> > ----------------------------------------------------------------
> >> > Ville Syrjälä (35):
> >> >       drm/i915: Add scaled paramater to update_sprite_watermarks()
> >> >       drm/i915: Pass the actual sprite width to watermarks functions
> >> >       drm/i915: Calculate the sprite WM based on the source width instead of the destination width
> >> >       drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate
> >> >       drm/i915: Rename most wm compute functions to ilk_ prefix
> >> >       drm/i915: Pass the watermark level to primary WM compute functions
> >> >       drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm
> >> >       drm/i915: Change the watermark latency type to uint16_t
> >> >       drm/i915: Split out reading of HSW watermark latency values
> >> >       drm/i915: Don't multiply the watermark latency values too early
> >> >       drm/i915: Add SNB/IVB support to intel_read_wm_latency
> >> >       drm/i915: Add ILK support to intel_read_wm_latency
> >> >       drm/i915: Store the watermark latency values in dev_priv
> >> >       drm/i915: Use the stored cursor and plane latencies properly
> >> >       drm/i915: Print the watermark latencies during init
> >> >       drm/i915: Disable specific watermark levels when latency is zero
> >> >       drm/i915: Pull watermark level validity check out
> >> >       drm/i915: Split watermark level computation from the code
> >> >       drm/i915: Kill fbc_enable from hsw_lp_wm_results
> >> >       drm/i915: Rename hsw_data_buf_partitioning to intel_ddb_partitioning
> >> >       drm/i915: Rename hsw_lp_wm_result to intel_wm_level
> >> >       drm/i915: Calculate max watermark levels for ILK+
> >> >       drm/i915; Pull some watermarks state into a separate structure
> >> >       drm/i915: Split plane watermark parameters into a separate struct
> >> >       drm/i915: Pass crtc to our update/disable_plane hooks
> >> >       drm/i915: Don't try to disable plane if it's already disabled
> >> >       drm/i915: Pass plane and crtc to intel_update_sprite_watermarks
> >> >       drm/i915: Always call intel_update_sprite_watermarks() when disabling a plane
> >> >       drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset
> >> >       drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
> >> >       drm/i915: Move HSW linetime watermark handling to modeset code
> >> >       hack: Add debug prints to watermark compute funcs
> >> >       hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB
> >> >       hack: Make fifo underruns DRM_ERROR
> >> >       hack: Print watermark programming duration
> >> >
> >> >  drivers/gpu/drm/i915/i915_drv.h      |   41 +-
> >> >  drivers/gpu/drm/i915/i915_irq.c      |   32 +-
> >> >  drivers/gpu/drm/i915/i915_reg.h      |    2 +
> >> >  drivers/gpu/drm/i915/intel_display.c |   45 +-
> >> >  drivers/gpu/drm/i915/intel_drv.h     |   47 +-
> >> >  drivers/gpu/drm/i915/intel_pm.c      | 1796 +++++++++++++++++-----------------
> >> >  drivers/gpu/drm/i915/intel_sprite.c  |   54 +-
> >> >  7 files changed, 1039 insertions(+), 978 deletions(-)
> >> > _______________________________________________
> >> > Intel-gfx mailing list
> >> > Intel-gfx@lists.freedesktop.org
> >> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> >>
> >>
> >>
> >> --
> >> Paulo Zanoni
> >
> > --
> > Ville Syrjälä
> > Intel OTC
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
  2013-07-05 17:46       ` Paulo Zanoni
@ 2013-07-05 18:00         ` Ville Syrjälä
  0 siblings, 0 replies; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-05 18:00 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Jul 05, 2013 at 02:46:44PM -0300, Paulo Zanoni wrote:
> 2013/7/5 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> > On Fri, Jul 05, 2013 at 10:37:08AM +0100, Chris Wilson wrote:
> >> On Fri, Jul 05, 2013 at 11:57:42AM +0300, ville.syrjala@linux.intel.com wrote:
> >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >
> >> > There is a major problem with the watermark registers; they're not
> >> > double buffered. So we need to make sure we update them at the correct
> >> > time when messing about with planes. The correct time is the beginning
> >> > of vblank.
> >> >
> >> > So when we determine that the watermarks need to updated hand in hand
> >> > with the next vblank, we store the pre-computed watermarks under
> >> > intel_crtc, and when the vblank happens, we promote the pending
> >> > watermarks to active status.
> >> >
> >> > on HSW when the watermarks for any pipe change, we must merge the
> >> > watermarks from all pipes so that we can determine the correct LP1+
> >> > watermark levels. For simplicity we follow the same codepaths for
> >> > pre-HSW hardware as well, but there all the LP1+ watermarks will be
> >> > disabled when multiple pipes are enabled. Once the watermarks are
> >> > merged we check them for validity, disabling any invalid levels.
> >> >
> >> > Touching the watermark registers causes the hardware to re-evaluate the
> >> > watermarks, which expeds some power. So after merging the watermarks
> >> > we check which watermark registers actually need to be changed. And
> >> > finally we write the watermarks registers in the correct order.
> >>
> >> Yet you do not justify doing so from interrupt context. A simple way
> >> would be to set safe WM (min of current vs next) before the config
> >> change, then schedule an update outside of interrupt context after the
> >> vblank.
> >>
> >> I really want an explanation for why doing so in interrupt context is
> >> the only sane way. Real power numbers vs complexity please.
> >
> > One problem is that there might not be a safe set of values that satisfy
> > both current and future constraints.
> 
> How about: disable all the LP watermarks and set the maximum values to
> all non-LP WMs?

If we have a sprite enabled the FIFO gets cut in half, so the the
current maximums with sprite enabled might not be enough for the
future config with sprite disabled.

> > One example could be a "low bpp/no
> > primary + sprite -> high bpp primary + no sprite" case. I guess we could
> > just reject such changes, but that feels a bit wrong. It would introduce
> > a weird restriction that would propably baffle userspace (doing a->c fails
> > but doing a->b->wait_for_vbl->c works), or we'd need to block for one frame
> > which is a big no-no these days.
> >
> > Also we would still need to track how the current hardware state
> > changes across vblanks, so it would still end up doing some extra
> > stuff at irq time.
> >
> > My hope was that the current approach wouldn't turn out to be too
> > expensive. Whether people consider 5 usec excessive, I don't know.
> > And maybe we could shave some of that off still.
> >
> > Not that I'm 100% attached to the current design. We could certainly
> > try other ways, if people think that's worthwile.
> >
> > --
> > Ville Syrjälä
> > Intel OTC
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code
  2013-07-05 17:51   ` Paulo Zanoni
@ 2013-07-05 18:11     ` Ville Syrjälä
  0 siblings, 0 replies; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-05 18:11 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Jul 05, 2013 at 02:51:36PM -0300, Paulo Zanoni wrote:
> 2013/7/5  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > There is a major problem with the watermark registers; they're not
> > double buffered. So we need to make sure we update them at the correct
> > time when messing about with planes. The correct time is the beginning
> > of vblank.
> >
> > So when we determine that the watermarks need to updated hand in hand
> > with the next vblank, we store the pre-computed watermarks under
> > intel_crtc, and when the vblank happens, we promote the pending
> > watermarks to active status.
> >
> > on HSW when the watermarks for any pipe change, we must merge the
> > watermarks from all pipes so that we can determine the correct LP1+
> > watermark levels. For simplicity we follow the same codepaths for
> > pre-HSW hardware as well, but there all the LP1+ watermarks will be
> > disabled when multiple pipes are enabled. Once the watermarks are
> > merged we check them for validity, disabling any invalid levels.
> >
> > Touching the watermark registers causes the hardware to re-evaluate the
> > watermarks, which expeds some power. So after merging the watermarks
> > we check which watermark registers actually need to be changed. And
> > finally we write the watermarks registers in the correct order.
> 
> This patch is way too big for us, poor reviewers. Can you split this
> into many many many tiny patches? I see *a lot* of different changes
> here.

Well, it's one change "rip out the old, bring in the new", or is that
two changes? :P

One problem with more splitting is that the intermediate steps might
not end up making much sense at some point if it's just churning code
around, or adding new bits that do nothing until the full system
is in place.

But I did actaully want to split it up a bit more at least. But I ran
out of time, so it will need to wait until I get back from vacation.

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 01/35] drm/i915: Add scaled paramater to update_sprite_watermarks()
  2013-07-05  8:57 ` [PATCH 01/35] drm/i915: Add scaled paramater to update_sprite_watermarks() ville.syrjala
@ 2013-07-30 18:26   ` Paulo Zanoni
  2013-07-30 18:30     ` Ville Syrjälä
  0 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 18:26 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Fro calculating watermarks we want to know whether sprites are

"Fro"

> scaled. Pass that information to update_sprite_watermarks() so that
> eventually we may do some watermark pre-computing.

On this patch you're also renaming some variables from "enable" to
"enabled", but not all of them. You should probably either rename them
all, or none. Example: intel_update_sprite_watermarks definition at
intel_drv.h says "bool enabled", but the implementation inside
intel_pm.c says "bool enable", but there are also other examples.

Besides the styling detail the patch looks correct, so if Daniel/Ville
consider my suggestion is just a bikeshed, Reviewed-by: Paulo Zanoni
<paulo.r.zanoni@intel.com>.

And another bikeshed would be to create variables called "scaled"
inside the update_plane funcs :)

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h     |  2 +-
>  drivers/gpu/drm/i915/intel_drv.h    |  7 ++++---
>  drivers/gpu/drm/i915/intel_pm.c     | 13 +++++++------
>  drivers/gpu/drm/i915/intel_sprite.c | 11 +++++++----
>  4 files changed, 19 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index fd0f589..99eb980 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -361,7 +361,7 @@ struct drm_i915_display_funcs {
>         void (*update_wm)(struct drm_device *dev);
>         void (*update_sprite_wm)(struct drm_device *dev, int pipe,
>                                  uint32_t sprite_width, int pixel_size,
> -                                bool enable);
> +                                bool enable, bool scaled);
>         void (*modeset_global_resources)(struct drm_device *dev);
>         /* Returns the active state of the crtc, and if the crtc is active,
>          * fills out the pipe-config with the hw state. */
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 5dfc1a0..3371ecc 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -353,7 +353,8 @@ struct intel_plane {
>          * for the watermark calculations. Currently only Haswell uses this.
>          */
>         struct {
> -               bool enable;
> +               bool enabled;
> +               bool scaled;
>                 uint8_t bytes_per_pixel;
>                 uint32_t horiz_pixels;
>         } wm;
> @@ -772,8 +773,8 @@ extern void intel_ddi_init(struct drm_device *dev, enum port port);
>  /* For use by IVB LP watermark workaround in intel_sprite.c */
>  extern void intel_update_watermarks(struct drm_device *dev);
>  extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
> -                                          uint32_t sprite_width,
> -                                          int pixel_size, bool enable);
> +                                          uint32_t sprite_width, int pixel_size,
> +                                          bool enabled, bool scaled);
>
>  extern unsigned long intel_gen4_compute_page_offset(int *x, int *y,
>                                                     unsigned int tiling_mode,
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 7cfd3b7..beca186 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2388,7 +2388,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
>                 pipe = intel_plane->pipe;
>                 p = &params[pipe];
>
> -               p->sprite_enabled = intel_plane->wm.enable;
> +               p->sprite_enabled = intel_plane->wm.enabled;
>                 p->spr_bytes_per_pixel = intel_plane->wm.bytes_per_pixel;
>                 p->spr_horiz_pixels = intel_plane->wm.horiz_pixels;
>
> @@ -2616,7 +2616,7 @@ static void haswell_update_wm(struct drm_device *dev)
>
>  static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
>                                      uint32_t sprite_width, int pixel_size,
> -                                    bool enable)
> +                                    bool enabled, bool scaled)
>  {
>         struct drm_plane *plane;
>
> @@ -2624,7 +2624,8 @@ static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
>                 struct intel_plane *intel_plane = to_intel_plane(plane);
>
>                 if (intel_plane->pipe == pipe) {
> -                       intel_plane->wm.enable = enable;
> +                       intel_plane->wm.enabled = enabled;
> +                       intel_plane->wm.scaled = scaled;
>                         intel_plane->wm.horiz_pixels = sprite_width + 1;
>                         intel_plane->wm.bytes_per_pixel = pixel_size;
>                         break;
> @@ -2712,7 +2713,7 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
>
>  static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
>                                          uint32_t sprite_width, int pixel_size,
> -                                        bool enable)
> +                                        bool enable, bool scaled)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
>         int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
> @@ -2835,13 +2836,13 @@ void intel_update_watermarks(struct drm_device *dev)
>
>  void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
>                                     uint32_t sprite_width, int pixel_size,
> -                                   bool enable)
> +                                   bool enable, bool scaled)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
>
>         if (dev_priv->display.update_sprite_wm)
>                 dev_priv->display.update_sprite_wm(dev, pipe, sprite_width,
> -                                                  pixel_size, enable);
> +                                                  pixel_size, enable, scaled);
>  }
>
>  static struct drm_i915_gem_object *
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 1fa5612..5a1f3fd 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -114,7 +114,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
>         crtc_w--;
>         crtc_h--;
>
> -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
> +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> +                                      src_w != crtc_w || src_h != crtc_h);
>
>         I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
>         I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
> @@ -268,7 +269,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
>         crtc_w--;
>         crtc_h--;
>
> -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
> +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> +                                      src_w != crtc_w || src_h != crtc_h);
>
>         /*
>          * IVB workaround: must disable low power watermarks for at least
> @@ -335,7 +337,7 @@ ivb_disable_plane(struct drm_plane *plane)
>
>         dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
>
> -       intel_update_sprite_watermarks(dev, pipe, 0, 0, false);
> +       intel_update_sprite_watermarks(dev, pipe, 0, 0, false, false);
>
>         /* potentially re-enable LP watermarks */
>         if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
> @@ -455,7 +457,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
>         crtc_w--;
>         crtc_h--;
>
> -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
> +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> +                                      src_w != crtc_w || src_h != crtc_h);
>
>         dvsscale = 0;
>         if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 01/35] drm/i915: Add scaled paramater to update_sprite_watermarks()
  2013-07-30 18:26   ` Paulo Zanoni
@ 2013-07-30 18:30     ` Ville Syrjälä
  2013-07-30 18:49       ` Paulo Zanoni
  0 siblings, 1 reply; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-30 18:30 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Tue, Jul 30, 2013 at 03:26:12PM -0300, Paulo Zanoni wrote:
> 2013/7/5  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Fro calculating watermarks we want to know whether sprites are
> 
> "Fro"
> 
> > scaled. Pass that information to update_sprite_watermarks() so that
> > eventually we may do some watermark pre-computing.
> 
> On this patch you're also renaming some variables from "enable" to
> "enabled", but not all of them. You should probably either rename them
> all, or none. Example: intel_update_sprite_watermarks definition at
> intel_drv.h says "bool enabled", but the implementation inside
> intel_pm.c says "bool enable", but there are also other examples.

The idea was to use "enabled" consistently, but it seems I messed up.
I can fix that up.

> 
> Besides the styling detail the patch looks correct, so if Daniel/Ville
> consider my suggestion is just a bikeshed, Reviewed-by: Paulo Zanoni
> <paulo.r.zanoni@intel.com>.
> 
> And another bikeshed would be to create variables called "scaled"
> inside the update_plane funcs :)

You mean "bool scaled = crtc_w != src_w || crtc_h != src_h;" or so?

Yeah I suppose could make the code a bit easier to parse.

> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h     |  2 +-
> >  drivers/gpu/drm/i915/intel_drv.h    |  7 ++++---
> >  drivers/gpu/drm/i915/intel_pm.c     | 13 +++++++------
> >  drivers/gpu/drm/i915/intel_sprite.c | 11 +++++++----
> >  4 files changed, 19 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index fd0f589..99eb980 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -361,7 +361,7 @@ struct drm_i915_display_funcs {
> >         void (*update_wm)(struct drm_device *dev);
> >         void (*update_sprite_wm)(struct drm_device *dev, int pipe,
> >                                  uint32_t sprite_width, int pixel_size,
> > -                                bool enable);
> > +                                bool enable, bool scaled);
> >         void (*modeset_global_resources)(struct drm_device *dev);
> >         /* Returns the active state of the crtc, and if the crtc is active,
> >          * fills out the pipe-config with the hw state. */
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 5dfc1a0..3371ecc 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -353,7 +353,8 @@ struct intel_plane {
> >          * for the watermark calculations. Currently only Haswell uses this.
> >          */
> >         struct {
> > -               bool enable;
> > +               bool enabled;
> > +               bool scaled;
> >                 uint8_t bytes_per_pixel;
> >                 uint32_t horiz_pixels;
> >         } wm;
> > @@ -772,8 +773,8 @@ extern void intel_ddi_init(struct drm_device *dev, enum port port);
> >  /* For use by IVB LP watermark workaround in intel_sprite.c */
> >  extern void intel_update_watermarks(struct drm_device *dev);
> >  extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
> > -                                          uint32_t sprite_width,
> > -                                          int pixel_size, bool enable);
> > +                                          uint32_t sprite_width, int pixel_size,
> > +                                          bool enabled, bool scaled);
> >
> >  extern unsigned long intel_gen4_compute_page_offset(int *x, int *y,
> >                                                     unsigned int tiling_mode,
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 7cfd3b7..beca186 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2388,7 +2388,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
> >                 pipe = intel_plane->pipe;
> >                 p = &params[pipe];
> >
> > -               p->sprite_enabled = intel_plane->wm.enable;
> > +               p->sprite_enabled = intel_plane->wm.enabled;
> >                 p->spr_bytes_per_pixel = intel_plane->wm.bytes_per_pixel;
> >                 p->spr_horiz_pixels = intel_plane->wm.horiz_pixels;
> >
> > @@ -2616,7 +2616,7 @@ static void haswell_update_wm(struct drm_device *dev)
> >
> >  static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
> >                                      uint32_t sprite_width, int pixel_size,
> > -                                    bool enable)
> > +                                    bool enabled, bool scaled)
> >  {
> >         struct drm_plane *plane;
> >
> > @@ -2624,7 +2624,8 @@ static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
> >                 struct intel_plane *intel_plane = to_intel_plane(plane);
> >
> >                 if (intel_plane->pipe == pipe) {
> > -                       intel_plane->wm.enable = enable;
> > +                       intel_plane->wm.enabled = enabled;
> > +                       intel_plane->wm.scaled = scaled;
> >                         intel_plane->wm.horiz_pixels = sprite_width + 1;
> >                         intel_plane->wm.bytes_per_pixel = pixel_size;
> >                         break;
> > @@ -2712,7 +2713,7 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
> >
> >  static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
> >                                          uint32_t sprite_width, int pixel_size,
> > -                                        bool enable)
> > +                                        bool enable, bool scaled)
> >  {
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> >         int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
> > @@ -2835,13 +2836,13 @@ void intel_update_watermarks(struct drm_device *dev)
> >
> >  void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
> >                                     uint32_t sprite_width, int pixel_size,
> > -                                   bool enable)
> > +                                   bool enable, bool scaled)
> >  {
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> >
> >         if (dev_priv->display.update_sprite_wm)
> >                 dev_priv->display.update_sprite_wm(dev, pipe, sprite_width,
> > -                                                  pixel_size, enable);
> > +                                                  pixel_size, enable, scaled);
> >  }
> >
> >  static struct drm_i915_gem_object *
> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> > index 1fa5612..5a1f3fd 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -114,7 +114,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
> >         crtc_w--;
> >         crtc_h--;
> >
> > -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
> > +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> > +                                      src_w != crtc_w || src_h != crtc_h);
> >
> >         I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
> >         I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
> > @@ -268,7 +269,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
> >         crtc_w--;
> >         crtc_h--;
> >
> > -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
> > +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> > +                                      src_w != crtc_w || src_h != crtc_h);
> >
> >         /*
> >          * IVB workaround: must disable low power watermarks for at least
> > @@ -335,7 +337,7 @@ ivb_disable_plane(struct drm_plane *plane)
> >
> >         dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
> >
> > -       intel_update_sprite_watermarks(dev, pipe, 0, 0, false);
> > +       intel_update_sprite_watermarks(dev, pipe, 0, 0, false, false);
> >
> >         /* potentially re-enable LP watermarks */
> >         if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
> > @@ -455,7 +457,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
> >         crtc_w--;
> >         crtc_h--;
> >
> > -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
> > +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> > +                                      src_w != crtc_w || src_h != crtc_h);
> >
> >         dvsscale = 0;
> >         if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
> > --
> > 1.8.1.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 02/35] drm/i915: Pass the actual sprite width to watermarks functions
  2013-07-05  8:57 ` [PATCH 02/35] drm/i915: Pass the actual sprite width to watermarks functions ville.syrjala
@ 2013-07-30 18:32   ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 18:32 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Don't subtract one from the sprite width before watermark calculations.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Looks like the bikeshed I just gave about the "scaled" variable would
cause the need to rebase this patch. So just forget it :)

> ---
>  drivers/gpu/drm/i915/intel_pm.c     |  2 +-
>  drivers/gpu/drm/i915/intel_sprite.c | 18 +++++++++---------
>  2 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index beca186..db548a1 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2626,7 +2626,7 @@ static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
>                 if (intel_plane->pipe == pipe) {
>                         intel_plane->wm.enabled = enabled;
>                         intel_plane->wm.scaled = scaled;
> -                       intel_plane->wm.horiz_pixels = sprite_width + 1;
> +                       intel_plane->wm.horiz_pixels = sprite_width;
>                         intel_plane->wm.bytes_per_pixel = pixel_size;
>                         break;
>                 }
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 5a1f3fd..d7fca56 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -108,15 +108,15 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
>
>         sprctl |= SP_ENABLE;
>
> +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> +                                      src_w != crtc_w || src_h != crtc_h);
> +
>         /* Sizes are 0 based */
>         src_w--;
>         src_h--;
>         crtc_w--;
>         crtc_h--;
>
> -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> -                                      src_w != crtc_w || src_h != crtc_h);
> -
>         I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
>         I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
>
> @@ -263,15 +263,15 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
>         if (IS_HASWELL(dev))
>                 sprctl |= SPRITE_PIPE_CSC_ENABLE;
>
> +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> +                                      src_w != crtc_w || src_h != crtc_h);
> +
>         /* Sizes are 0 based */
>         src_w--;
>         src_h--;
>         crtc_w--;
>         crtc_h--;
>
> -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> -                                      src_w != crtc_w || src_h != crtc_h);
> -
>         /*
>          * IVB workaround: must disable low power watermarks for at least
>          * one frame before enabling scaling.  LP watermarks can be re-enabled
> @@ -451,15 +451,15 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
>                 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
>         dvscntr |= DVS_ENABLE;
>
> +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> +                                      src_w != crtc_w || src_h != crtc_h);
> +
>         /* Sizes are 0 based */
>         src_w--;
>         src_h--;
>         crtc_w--;
>         crtc_h--;
>
> -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> -                                      src_w != crtc_w || src_h != crtc_h);
> -
>         dvsscale = 0;
>         if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
>                 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 01/35] drm/i915: Add scaled paramater to update_sprite_watermarks()
  2013-07-30 18:30     ` Ville Syrjälä
@ 2013-07-30 18:49       ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 18:49 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

2013/7/30 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> On Tue, Jul 30, 2013 at 03:26:12PM -0300, Paulo Zanoni wrote:
>> 2013/7/5  <ville.syrjala@linux.intel.com>:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > Fro calculating watermarks we want to know whether sprites are
>>
>> "Fro"
>>
>> > scaled. Pass that information to update_sprite_watermarks() so that
>> > eventually we may do some watermark pre-computing.
>>
>> On this patch you're also renaming some variables from "enable" to
>> "enabled", but not all of them. You should probably either rename them
>> all, or none. Example: intel_update_sprite_watermarks definition at
>> intel_drv.h says "bool enabled", but the implementation inside
>> intel_pm.c says "bool enable", but there are also other examples.
>
> The idea was to use "enabled" consistently, but it seems I messed up.
> I can fix that up.
>
>>
>> Besides the styling detail the patch looks correct, so if Daniel/Ville
>> consider my suggestion is just a bikeshed, Reviewed-by: Paulo Zanoni
>> <paulo.r.zanoni@intel.com>.
>>
>> And another bikeshed would be to create variables called "scaled"
>> inside the update_plane funcs :)
>
> You mean "bool scaled = crtc_w != src_w || crtc_h != src_h;" or so?

Yes, but I just realized that will trigger a rebase of many other
patches of your series... So you may skip it if you want. Maybe do it
in the end, or not at all.

>
> Yeah I suppose could make the code a bit easier to parse.
>
>>
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/i915_drv.h     |  2 +-
>> >  drivers/gpu/drm/i915/intel_drv.h    |  7 ++++---
>> >  drivers/gpu/drm/i915/intel_pm.c     | 13 +++++++------
>> >  drivers/gpu/drm/i915/intel_sprite.c | 11 +++++++----
>> >  4 files changed, 19 insertions(+), 14 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> > index fd0f589..99eb980 100644
>> > --- a/drivers/gpu/drm/i915/i915_drv.h
>> > +++ b/drivers/gpu/drm/i915/i915_drv.h
>> > @@ -361,7 +361,7 @@ struct drm_i915_display_funcs {
>> >         void (*update_wm)(struct drm_device *dev);
>> >         void (*update_sprite_wm)(struct drm_device *dev, int pipe,
>> >                                  uint32_t sprite_width, int pixel_size,
>> > -                                bool enable);
>> > +                                bool enable, bool scaled);
>> >         void (*modeset_global_resources)(struct drm_device *dev);
>> >         /* Returns the active state of the crtc, and if the crtc is active,
>> >          * fills out the pipe-config with the hw state. */
>> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> > index 5dfc1a0..3371ecc 100644
>> > --- a/drivers/gpu/drm/i915/intel_drv.h
>> > +++ b/drivers/gpu/drm/i915/intel_drv.h
>> > @@ -353,7 +353,8 @@ struct intel_plane {
>> >          * for the watermark calculations. Currently only Haswell uses this.
>> >          */
>> >         struct {
>> > -               bool enable;
>> > +               bool enabled;
>> > +               bool scaled;
>> >                 uint8_t bytes_per_pixel;
>> >                 uint32_t horiz_pixels;
>> >         } wm;
>> > @@ -772,8 +773,8 @@ extern void intel_ddi_init(struct drm_device *dev, enum port port);
>> >  /* For use by IVB LP watermark workaround in intel_sprite.c */
>> >  extern void intel_update_watermarks(struct drm_device *dev);
>> >  extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
>> > -                                          uint32_t sprite_width,
>> > -                                          int pixel_size, bool enable);
>> > +                                          uint32_t sprite_width, int pixel_size,
>> > +                                          bool enabled, bool scaled);
>> >
>> >  extern unsigned long intel_gen4_compute_page_offset(int *x, int *y,
>> >                                                     unsigned int tiling_mode,
>> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> > index 7cfd3b7..beca186 100644
>> > --- a/drivers/gpu/drm/i915/intel_pm.c
>> > +++ b/drivers/gpu/drm/i915/intel_pm.c
>> > @@ -2388,7 +2388,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
>> >                 pipe = intel_plane->pipe;
>> >                 p = &params[pipe];
>> >
>> > -               p->sprite_enabled = intel_plane->wm.enable;
>> > +               p->sprite_enabled = intel_plane->wm.enabled;
>> >                 p->spr_bytes_per_pixel = intel_plane->wm.bytes_per_pixel;
>> >                 p->spr_horiz_pixels = intel_plane->wm.horiz_pixels;
>> >
>> > @@ -2616,7 +2616,7 @@ static void haswell_update_wm(struct drm_device *dev)
>> >
>> >  static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
>> >                                      uint32_t sprite_width, int pixel_size,
>> > -                                    bool enable)
>> > +                                    bool enabled, bool scaled)
>> >  {
>> >         struct drm_plane *plane;
>> >
>> > @@ -2624,7 +2624,8 @@ static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,
>> >                 struct intel_plane *intel_plane = to_intel_plane(plane);
>> >
>> >                 if (intel_plane->pipe == pipe) {
>> > -                       intel_plane->wm.enable = enable;
>> > +                       intel_plane->wm.enabled = enabled;
>> > +                       intel_plane->wm.scaled = scaled;
>> >                         intel_plane->wm.horiz_pixels = sprite_width + 1;
>> >                         intel_plane->wm.bytes_per_pixel = pixel_size;
>> >                         break;
>> > @@ -2712,7 +2713,7 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
>> >
>> >  static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
>> >                                          uint32_t sprite_width, int pixel_size,
>> > -                                        bool enable)
>> > +                                        bool enable, bool scaled)
>> >  {
>> >         struct drm_i915_private *dev_priv = dev->dev_private;
>> >         int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
>> > @@ -2835,13 +2836,13 @@ void intel_update_watermarks(struct drm_device *dev)
>> >
>> >  void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
>> >                                     uint32_t sprite_width, int pixel_size,
>> > -                                   bool enable)
>> > +                                   bool enable, bool scaled)
>> >  {
>> >         struct drm_i915_private *dev_priv = dev->dev_private;
>> >
>> >         if (dev_priv->display.update_sprite_wm)
>> >                 dev_priv->display.update_sprite_wm(dev, pipe, sprite_width,
>> > -                                                  pixel_size, enable);
>> > +                                                  pixel_size, enable, scaled);
>> >  }
>> >
>> >  static struct drm_i915_gem_object *
>> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
>> > index 1fa5612..5a1f3fd 100644
>> > --- a/drivers/gpu/drm/i915/intel_sprite.c
>> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
>> > @@ -114,7 +114,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
>> >         crtc_w--;
>> >         crtc_h--;
>> >
>> > -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
>> > +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
>> > +                                      src_w != crtc_w || src_h != crtc_h);
>> >
>> >         I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
>> >         I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
>> > @@ -268,7 +269,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
>> >         crtc_w--;
>> >         crtc_h--;
>> >
>> > -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
>> > +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
>> > +                                      src_w != crtc_w || src_h != crtc_h);
>> >
>> >         /*
>> >          * IVB workaround: must disable low power watermarks for at least
>> > @@ -335,7 +337,7 @@ ivb_disable_plane(struct drm_plane *plane)
>> >
>> >         dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
>> >
>> > -       intel_update_sprite_watermarks(dev, pipe, 0, 0, false);
>> > +       intel_update_sprite_watermarks(dev, pipe, 0, 0, false, false);
>> >
>> >         /* potentially re-enable LP watermarks */
>> >         if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
>> > @@ -455,7 +457,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
>> >         crtc_w--;
>> >         crtc_h--;
>> >
>> > -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
>> > +       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
>> > +                                      src_w != crtc_w || src_h != crtc_h);
>> >
>> >         dvsscale = 0;
>> >         if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
>> > --
>> > 1.8.1.5
>> >
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>>
>>
>> --
>> Paulo Zanoni
>
> --
> Ville Syrjälä
> Intel OTC



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 03/35] drm/i915: Calculate the sprite WM based on the source width instead of the destination width
  2013-07-05  8:57 ` [PATCH 03/35] drm/i915: Calculate the sprite WM based on the source width instead of the destination width ville.syrjala
@ 2013-07-30 19:01   ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 19:01 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Using the destination width in the sprite WM calculations isn't correct.
> We should be using the source width.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Seems correct according to the IVB WM calculator. It is also worth
mentioning that this doesn't affect HSW watermarks since HSW doesn't
support sprite scaling.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_sprite.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index d7fca56..7c6cce7 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -108,7 +108,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
>
>         sprctl |= SP_ENABLE;
>
> -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> +       intel_update_sprite_watermarks(dev, pipe, src_w, pixel_size, true,
>                                        src_w != crtc_w || src_h != crtc_h);
>
>         /* Sizes are 0 based */
> @@ -263,7 +263,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
>         if (IS_HASWELL(dev))
>                 sprctl |= SPRITE_PIPE_CSC_ENABLE;
>
> -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> +       intel_update_sprite_watermarks(dev, pipe, src_w, pixel_size, true,
>                                        src_w != crtc_w || src_h != crtc_h);
>
>         /* Sizes are 0 based */
> @@ -451,7 +451,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
>                 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
>         dvscntr |= DVS_ENABLE;
>
> -       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true,
> +       intel_update_sprite_watermarks(dev, pipe, src_w, pixel_size, true,
>                                        src_w != crtc_w || src_h != crtc_h);
>
>         /* Sizes are 0 based */
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 04/35] drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate
  2013-07-05  8:57 ` [PATCH 04/35] drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate ville.syrjala
@ 2013-07-30 19:20   ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 19:20 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> hsw_wm_get_pixel_rate() isn't specific to HSW. In fact it should be made
> to handle all gens, but for now it depends on the PCH panel fitter
> state, so give it an ilk_ prefix.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

I couldn't find the ILK docs to check this, but SNB/IVB seems correct.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index db548a1..b8fde13 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2080,8 +2080,8 @@ static void ivybridge_update_wm(struct drm_device *dev)
>                    cursor_wm);
>  }
>
> -static uint32_t hsw_wm_get_pixel_rate(struct drm_device *dev,
> -                                     struct drm_crtc *crtc)
> +static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
> +                                   struct drm_crtc *crtc)
>  {
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>         uint32_t pixel_rate, pfit_size;
> @@ -2373,7 +2373,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
>                 pipes_active++;
>
>                 p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
> -               p->pixel_rate = hsw_wm_get_pixel_rate(dev, crtc);
> +               p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
>                 p->pri_bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
>                 p->cur_bytes_per_pixel = 4;
>                 p->pri_horiz_pixels =
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 05/35] drm/i915: Rename most wm compute functions to ilk_ prefix
  2013-07-05  8:57 ` [PATCH 05/35] drm/i915: Rename most wm compute functions to ilk_ prefix ville.syrjala
@ 2013-07-30 19:37   ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 19:37 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> These functions are appropriate for everything since ILK.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Again, I don't have the ILK docs, so this is just reviewed for SNB/IVB:

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (SNB/IVB only)

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 40 ++++++++++++++++++++--------------------
>  1 file changed, 20 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index b8fde13..6b820c4 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2111,7 +2111,7 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
>         return pixel_rate;
>  }
>
> -static uint32_t hsw_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
> +static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
>                                uint32_t latency)
>  {
>         uint64_t ret;
> @@ -2122,7 +2122,7 @@ static uint32_t hsw_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
>         return ret;
>  }
>
> -static uint32_t hsw_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
> +static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
>                                uint32_t horiz_pixels, uint8_t bytes_per_pixel,
>                                uint32_t latency)
>  {
> @@ -2134,7 +2134,7 @@ static uint32_t hsw_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
>         return ret;
>  }
>
> -static uint32_t hsw_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
> +static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
>                            uint8_t bytes_per_pixel)
>  {
>         return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
> @@ -2183,7 +2183,7 @@ enum hsw_data_buf_partitioning {
>  };
>
>  /* For both WM_PIPE and WM_LP. */
> -static uint32_t hsw_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
> +static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
>                                    uint32_t mem_value,
>                                    bool is_lp)
>  {
> @@ -2193,14 +2193,14 @@ static uint32_t hsw_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
>         if (!params->active)
>                 return 0;
>
> -       method1 = hsw_wm_method1(params->pixel_rate,
> +       method1 = ilk_wm_method1(params->pixel_rate,
>                                  params->pri_bytes_per_pixel,
>                                  mem_value);
>
>         if (!is_lp)
>                 return method1;
>
> -       method2 = hsw_wm_method2(params->pixel_rate,
> +       method2 = ilk_wm_method2(params->pixel_rate,
>                                  params->pipe_htotal,
>                                  params->pri_horiz_pixels,
>                                  params->pri_bytes_per_pixel,
> @@ -2210,7 +2210,7 @@ static uint32_t hsw_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
>  }
>
>  /* For both WM_PIPE and WM_LP. */
> -static uint32_t hsw_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
> +static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
>                                    uint32_t mem_value)
>  {
>         uint32_t method1, method2;
> @@ -2218,10 +2218,10 @@ static uint32_t hsw_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
>         if (!params->active || !params->sprite_enabled)
>                 return 0;
>
> -       method1 = hsw_wm_method1(params->pixel_rate,
> +       method1 = ilk_wm_method1(params->pixel_rate,
>                                  params->spr_bytes_per_pixel,
>                                  mem_value);
> -       method2 = hsw_wm_method2(params->pixel_rate,
> +       method2 = ilk_wm_method2(params->pixel_rate,
>                                  params->pipe_htotal,
>                                  params->spr_horiz_pixels,
>                                  params->spr_bytes_per_pixel,
> @@ -2230,13 +2230,13 @@ static uint32_t hsw_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
>  }
>
>  /* For both WM_PIPE and WM_LP. */
> -static uint32_t hsw_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
> +static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
>                                    uint32_t mem_value)
>  {
>         if (!params->active)
>                 return 0;
>
> -       return hsw_wm_method2(params->pixel_rate,
> +       return ilk_wm_method2(params->pixel_rate,
>                               params->pipe_htotal,
>                               params->cur_horiz_pixels,
>                               params->cur_bytes_per_pixel,
> @@ -2244,14 +2244,14 @@ static uint32_t hsw_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
>  }
>
>  /* Only for WM_LP. */
> -static uint32_t hsw_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
> +static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
>                                    uint32_t pri_val,
>                                    uint32_t mem_value)
>  {
>         if (!params->active)
>                 return 0;
>
> -       return hsw_wm_fbc(pri_val,
> +       return ilk_wm_fbc(pri_val,
>                           params->pri_horiz_pixels,
>                           params->pri_bytes_per_pixel);
>  }
> @@ -2266,10 +2266,10 @@ static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
>         for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) {
>                 struct hsw_pipe_wm_parameters *p = &params[pipe];
>
> -               pri_val[pipe] = hsw_compute_pri_wm(p, mem_value, true);
> -               spr_val[pipe] = hsw_compute_spr_wm(p, mem_value);
> -               cur_val[pipe] = hsw_compute_cur_wm(p, mem_value);
> -               fbc_val[pipe] = hsw_compute_fbc_wm(p, pri_val[pipe], mem_value);
> +               pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, true);
> +               spr_val[pipe] = ilk_compute_spr_wm(p, mem_value);
> +               cur_val[pipe] = ilk_compute_cur_wm(p, mem_value);
> +               fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe], mem_value);
>         }
>
>         result->pri_val = max3(pri_val[0], pri_val[1], pri_val[2]);
> @@ -2296,9 +2296,9 @@ static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
>  {
>         uint32_t pri_val, cur_val, spr_val;
>
> -       pri_val = hsw_compute_pri_wm(params, mem_value, false);
> -       spr_val = hsw_compute_spr_wm(params, mem_value);
> -       cur_val = hsw_compute_cur_wm(params, mem_value);
> +       pri_val = ilk_compute_pri_wm(params, mem_value, false);
> +       spr_val = ilk_compute_spr_wm(params, mem_value);
> +       cur_val = ilk_compute_cur_wm(params, mem_value);
>
>         WARN(pri_val > 127,
>              "Primary WM error, mode not supported for pipe %c\n",
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 06/35] drm/i915: Pass the watermark level to primary WM compute functions
  2013-07-05  8:57 ` [PATCH 06/35] drm/i915: Pass the watermark level to primary WM compute functions ville.syrjala
@ 2013-07-30 19:49   ` Paulo Zanoni
  2013-08-01  8:01     ` Ville Syrjälä
  0 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 19:49 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Passing the level insted of "is_lp" seems easier. The end result is the
> same though.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 6b820c4..f178e26 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2185,7 +2185,7 @@ enum hsw_data_buf_partitioning {
>  /* For both WM_PIPE and WM_LP. */
>  static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
>                                    uint32_t mem_value,
> -                                  bool is_lp)
> +                                  int level)
>  {
>         uint32_t method1, method2;
>
> @@ -2197,7 +2197,7 @@ static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
>                                  params->pri_bytes_per_pixel,
>                                  mem_value);
>
> -       if (!is_lp)
> +       if (level == 0)
>                 return method1;
>
>         method2 = ilk_wm_method2(params->pixel_rate,
> @@ -2266,7 +2266,7 @@ static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
>         for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) {
>                 struct hsw_pipe_wm_parameters *p = &params[pipe];
>
> -               pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, true);
> +               pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, 1);

But now even when you're processing levels 2/3/4 you're telling the
function that you're doing level 1, which is not true. We don't know
what kind of code changes we'll be doing in January 2023, so we may
use that incorrect "level" variable to do something wrong. IMHO,
either we keep the current code or we pass the actual level.


>                 spr_val[pipe] = ilk_compute_spr_wm(p, mem_value);
>                 cur_val[pipe] = ilk_compute_cur_wm(p, mem_value);
>                 fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe], mem_value);
> @@ -2296,7 +2296,7 @@ static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
>  {
>         uint32_t pri_val, cur_val, spr_val;
>
> -       pri_val = ilk_compute_pri_wm(params, mem_value, false);
> +       pri_val = ilk_compute_pri_wm(params, mem_value, 0);
>         spr_val = ilk_compute_spr_wm(params, mem_value);
>         cur_val = ilk_compute_cur_wm(params, mem_value);
>
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 07/35] drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm
  2013-07-05  8:57 ` [PATCH 07/35] drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm ville.syrjala
@ 2013-07-30 19:54   ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 19:54 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The FBC watermark doesn't depend on the latency value, so no point in
> passing it in.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

/me hides from the git blame

It does depend, but indirectly, through pri_val :P

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index f178e26..981416c 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2245,8 +2245,7 @@ static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
>
>  /* Only for WM_LP. */
>  static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
> -                                  uint32_t pri_val,
> -                                  uint32_t mem_value)
> +                                  uint32_t pri_val)
>  {
>         if (!params->active)
>                 return 0;
> @@ -2269,7 +2268,7 @@ static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
>                 pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, 1);
>                 spr_val[pipe] = ilk_compute_spr_wm(p, mem_value);
>                 cur_val[pipe] = ilk_compute_cur_wm(p, mem_value);
> -               fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe], mem_value);
> +               fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe]);
>         }
>
>         result->pri_val = max3(pri_val[0], pri_val[1], pri_val[2]);
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 08/35] drm/i915: Change the watermark latency type to uint16_t
  2013-07-05  8:57 ` [PATCH 08/35] drm/i915: Change the watermark latency type to uint16_t ville.syrjala
@ 2013-07-30 20:01   ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 20:01 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The latency values fit in uint16_t, so let's save a few bytes.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>


> ---
>  drivers/gpu/drm/i915/intel_pm.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 981416c..2239cdb 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2338,7 +2338,7 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
>
>  static void hsw_compute_wm_parameters(struct drm_device *dev,
>                                       struct hsw_pipe_wm_parameters *params,
> -                                     uint32_t *wm,
> +                                     uint16_t *wm,
>                                       struct hsw_wm_maximums *lp_max_1_2,
>                                       struct hsw_wm_maximums *lp_max_5_6)
>  {
> @@ -2411,7 +2411,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
>
>  static void hsw_compute_wm_results(struct drm_device *dev,
>                                    struct hsw_pipe_wm_parameters *params,
> -                                  uint32_t *wm,
> +                                  uint16_t *wm,
>                                    struct hsw_wm_maximums *lp_maximums,
>                                    struct hsw_wm_values *results)
>  {
> @@ -2593,7 +2593,7 @@ static void haswell_update_wm(struct drm_device *dev)
>         struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
>         struct hsw_pipe_wm_parameters params[3];
>         struct hsw_wm_values results_1_2, results_5_6, *best_results;
> -       uint32_t wm[5];
> +       uint16_t wm[5];
>         enum hsw_data_buf_partitioning partitioning;
>
>         hsw_compute_wm_parameters(dev, params, wm, &lp_max_1_2, &lp_max_5_6);
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 09/35] drm/i915: Split out reading of HSW watermark latency values
  2013-07-05  8:57 ` [PATCH 09/35] drm/i915: Split out reading of HSW watermark latency values ville.syrjala
  2013-07-05  9:19   ` Chris Wilson
@ 2013-07-30 20:09   ` Paulo Zanoni
  1 sibling, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 20:09 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Move parsing of MCH_SSKPD to a separate function, we'll add other
> platforms there later.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 34 ++++++++++++++++++++--------------
>  1 file changed, 20 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 2239cdb..c266e47 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2336,28 +2336,33 @@ 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])
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       if (IS_HASWELL(dev)) {
> +               uint64_t sskpd = I915_READ64(MCH_SSKPD);
> +
> +               wm[0] = (sskpd >> 56) & 0xFF;
> +               if (wm[0] == 0)
> +                       wm[0] = sskpd & 0xF;
> +               wm[1] = ((sskpd >> 4) & 0xFF) * 5;
> +               wm[2] = ((sskpd >> 12) & 0xFF) * 5;
> +               wm[3] = ((sskpd >> 20) & 0x1FF) * 5;
> +               wm[4] = ((sskpd >> 32) & 0x1FF) * 5;
> +       }
> +}
> +
>  static void hsw_compute_wm_parameters(struct drm_device *dev,
>                                       struct hsw_pipe_wm_parameters *params,
> -                                     uint16_t *wm,
>                                       struct hsw_wm_maximums *lp_max_1_2,
>                                       struct hsw_wm_maximums *lp_max_5_6)
>  {
> -       struct drm_i915_private *dev_priv = dev->dev_private;
>         struct drm_crtc *crtc;
>         struct drm_plane *plane;
> -       uint64_t sskpd = I915_READ64(MCH_SSKPD);
>         enum pipe pipe;
>         int pipes_active = 0, sprites_enabled = 0;
>
> -       if ((sskpd >> 56) & 0xFF)
> -               wm[0] = (sskpd >> 56) & 0xFF;
> -       else
> -               wm[0] = sskpd & 0xF;
> -       wm[1] = ((sskpd >> 4) & 0xFF) * 5;
> -       wm[2] = ((sskpd >> 12) & 0xFF) * 5;
> -       wm[3] = ((sskpd >> 20) & 0x1FF) * 5;
> -       wm[4] = ((sskpd >> 32) & 0x1FF) * 5;
> -
>         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
>                 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>                 struct hsw_pipe_wm_parameters *p;
> @@ -2593,10 +2598,11 @@ static void haswell_update_wm(struct drm_device *dev)
>         struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
>         struct hsw_pipe_wm_parameters params[3];
>         struct hsw_wm_values results_1_2, results_5_6, *best_results;
> -       uint16_t wm[5];
> +       uint16_t wm[5] = {};

Maybe we could make the "wm" array be part of "struct
hsw_pipe_wm_parameters"? Then we could move the call to
intel_read_wm_latency back to hsw_compute_wm_parameters. But that
would be material for a separate patch.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>


>         enum hsw_data_buf_partitioning partitioning;
>
> -       hsw_compute_wm_parameters(dev, params, wm, &lp_max_1_2, &lp_max_5_6);
> +       intel_read_wm_latency(dev, wm);
> +       hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
>
>         hsw_compute_wm_results(dev, params, wm, &lp_max_1_2, &results_1_2);
>         if (lp_max_1_2.pri != lp_max_5_6.pri) {
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 10/35] drm/i915: Don't multiply the watermark latency values too early
  2013-07-05  8:57 ` [PATCH 10/35] drm/i915: Don't multiply the watermark latency values too early ville.syrjala
@ 2013-07-30 20:21   ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 20:21 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The LP1+ watermark latency values need to be multiplied by 5 to
> make the suitable for watermark calculations. However on pre-HSW
> platforms we're going to need the raw value later when we have to
> write it to the WM_LPn registers' latency field. So delay the
> multiplication until it's needed.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

My only worry is that now we're hiding even more the measurement units
used for mem_value. Perhaps we could also patch hsw_compute_wm_pipe
and hsw_compute_lp_wm explaining that a mem_value of 1 means "100ns"?
Maybe a comment?

Anyway, the patch is correct, so: Reviewed-by: Paulo Zanoni
<paulo.r.zanonI@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c266e47..a2ca018 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2346,10 +2346,10 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
>                 wm[0] = (sskpd >> 56) & 0xFF;
>                 if (wm[0] == 0)
>                         wm[0] = sskpd & 0xF;
> -               wm[1] = ((sskpd >> 4) & 0xFF) * 5;
> -               wm[2] = ((sskpd >> 12) & 0xFF) * 5;
> -               wm[3] = ((sskpd >> 20) & 0x1FF) * 5;
> -               wm[4] = ((sskpd >> 32) & 0x1FF) * 5;
> +               wm[1] = (sskpd >> 4) & 0xFF;
> +               wm[2] = (sskpd >> 12) & 0xFF;
> +               wm[3] = (sskpd >> 20) & 0x1FF;
> +               wm[4] = (sskpd >> 32) & 0x1FF;
>         }
>  }
>
> @@ -2427,7 +2427,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
>         int level, max_level, wm_lp;
>
>         for (level = 1; level <= 4; level++)
> -               if (!hsw_compute_lp_wm(wm[level], lp_maximums, params,
> +               if (!hsw_compute_lp_wm(wm[level] * 5, lp_maximums, params,
>                                        &lp_results[level - 1]))
>                         break;
>         max_level = level - 1;
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 11/35] drm/i915: Add SNB/IVB support to intel_read_wm_latency
  2013-07-05  8:57 ` [PATCH 11/35] drm/i915: Add SNB/IVB support to intel_read_wm_latency ville.syrjala
@ 2013-07-30 21:01   ` Paulo Zanoni
  2013-08-05  5:23     ` Daniel Vetter
  0 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 21:01 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> SNB and IVB have slightly a different way to read out the
> watermark latency values.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index a2ca018..6ff89c6 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2350,6 +2350,13 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
>                 wm[2] = (sskpd >> 12) & 0xFF;
>                 wm[3] = (sskpd >> 20) & 0x1FF;
>                 wm[4] = (sskpd >> 32) & 0x1FF;
> +       } else if (INTEL_INFO(dev)->gen >= 6) {
> +               uint32_t sskpd = I915_READ(MCH_SSKPD);
> +
> +               wm[0] = (sskpd >> SSKPD_WM0_SHIFT) & SSKPD_WM_MASK;
> +               wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK;
> +               wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK;
> +               wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK;

My documentation is limited, but this seems at least consistent with
our current definitions.

I'd also vote to transform this into a "switch (INTEL_INFO(dev))" and
add a WARN in case Gen is not 6 or 7.

Anyway, the patch looks correct: Reviewed-by: Paulo Zanoni
<paulo.r.zanoni@intel.com>

>         }
>  }
>
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 13/35] drm/i915: Store the watermark latency values in dev_priv
       [not found]   ` <CA+gsUGQ0JqEZiEUsONJh7nr6rPYRfTxJM79oc5tGcexEudB2Og@mail.gmail.com>
@ 2013-07-30 21:42     ` Paulo Zanoni
  2013-07-31  9:43       ` Ville Syrjälä
  0 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 21:42 UTC (permalink / raw)
  To: ville.syrjala, Intel Graphics Development

I forgot to add intel-gfx in the review email...

2013/7/30 Paulo Zanoni <przanoni@gmail.com>:
> 2013/7/5  <ville.syrjala@linux.intel.com>:
>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>
>> Rather than having to read the latency values out every time, just
>> store them in dev_priv.
>>
>> On ILK and IVB there is a difference between some of the latency
>> values for different planes, so store the latency values for each
>> plane type separately, and apply the necesary fixups during init.
>>
>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_drv.h |  9 ++++++
>>  drivers/gpu/drm/i915/intel_pm.c | 62 +++++++++++++++++++++++++++++++++++------
>>  2 files changed, 62 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 99eb980..60f9437 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -1184,6 +1184,15 @@ typedef struct drm_i915_private {
>>
>>         struct i915_suspend_saved_registers regfile;
>>
>> +       struct {
>> +               /* watermark latency values for primary */
>> +               uint16_t pri_latency[5];
>> +               /* watermark latency values for sprite */
>> +               uint16_t spr_latency[5];
>> +               /* watermark latency values for cursor */
>> +               uint16_t cur_latency[5];
>> +       } wm;
>> +
>>         /* Old dri1 support infrastructure, beware the dragons ya fools entering
>>          * here! */
>>         struct i915_dri1_state dri1;
>> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> index e4d2477..68a1de4 100644
>> --- a/drivers/gpu/drm/i915/intel_pm.c
>> +++ b/drivers/gpu/drm/i915/intel_pm.c
>> @@ -2367,6 +2367,39 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
>>         }
>>  }
>>
>> +static void intel_fixup_spr_wm_latency(struct drm_device *dev, uint16_t wm[5])
>> +{
>> +       /* ILK sprite LP0 latency is 1300 ns */
>> +       if (INTEL_INFO(dev)->gen == 5)
>> +               wm[0] = 13;
>> +}
>> +
>> +static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
>> +{
>> +       /* ILK cursor LP0 latency is 1300 ns */
>> +       if (INTEL_INFO(dev)->gen == 5)
>> +               wm[0] = 13;
>> +
>> +       /* WaDoubleCursorLP3Latency:ivb */
>> +       if (IS_IVYBRIDGE(dev))
>> +               wm[3] *= 2;
>
> Doesn't this WA apply only to pre-production steppings?
>
>
>> +}
>> +
>> +static void intel_setup_wm_latency(struct drm_device *dev)
>> +{
>> +       struct drm_i915_private *dev_priv = dev->dev_private;
>> +
>> +       intel_read_wm_latency(dev, 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,
>> +              sizeof dev_priv->wm.pri_latency);
>
> Checkpatch.pl complains about these sizeof without parens.
>
>
>> +
>> +       intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency);
>> +       intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency);
>> +}
>> +
>>  static void hsw_compute_wm_parameters(struct drm_device *dev,
>>                                       struct hsw_pipe_wm_parameters *params,
>>                                       struct hsw_wm_maximums *lp_max_1_2,
>> @@ -2612,16 +2645,17 @@ static void haswell_update_wm(struct drm_device *dev)
>>         struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
>>         struct hsw_pipe_wm_parameters params[3];
>>         struct hsw_wm_values results_1_2, results_5_6, *best_results;
>> -       uint16_t wm[5] = {};
>>         enum hsw_data_buf_partitioning partitioning;
>>
>> -       intel_read_wm_latency(dev, wm);
>>         hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
>>
>> -       hsw_compute_wm_results(dev, params, wm, &lp_max_1_2, &results_1_2);
>> +       hsw_compute_wm_results(dev, params,
>> +                              dev_priv->wm.pri_latency,
>> +                              &lp_max_1_2, &results_1_2);
>>         if (lp_max_1_2.pri != lp_max_5_6.pri) {
>> -               hsw_compute_wm_results(dev, params, wm, &lp_max_5_6,
>> -                                      &results_5_6);
>> +               hsw_compute_wm_results(dev, params,
>> +                                      dev_priv->wm.pri_latency,
>> +                                      &lp_max_5_6, &results_5_6);
>
> My vote would be to just not pass dev_priv->wm.pri_latency here, it's
> useless since we're already passing dev. And in the place where we
> actually use dev_priv->wm.pri_latency we should add a comment saying
> that on Haswell pri_latency should be the same as the others,
> otherwise people will start wondering why you're using pri_latency and
> not the others.
>
>
>>                 best_results = hsw_find_best_result(&results_1_2, &results_5_6);
>>         } else {
>>                 best_results = &results_1_2;
>> @@ -5211,8 +5245,12 @@ void intel_init_pm(struct drm_device *dev)
>>
>>         /* For FIFO watermark updates */
>>         if (HAS_PCH_SPLIT(dev)) {
>> +               intel_setup_wm_latency(dev);
>> +
>>                 if (IS_GEN5(dev)) {
>> -                       if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
>> +                       if (dev_priv->wm.pri_latency[1] &&
>> +                           dev_priv->wm.spr_latency[1] &&
>> +                           dev_priv->wm.cur_latency[1])
>
> I always wondered why do we have these checks. Do we ever see real
> machines that have zero values in the latency fields? On some gens we
> only check wm[0] and not the others, but on ILK we check wm[1] and not
> the others... Anyway, this is not a problem that should be solved by
> this patch, but I'd love answers :)
>
>
>>                                 dev_priv->display.update_wm = ironlake_update_wm;
>>                         else {
>>                                 DRM_DEBUG_KMS("Failed to get proper latency. "
>> @@ -5221,7 +5259,9 @@ void intel_init_pm(struct drm_device *dev)
>>                         }
>>                         dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
>>                 } else if (IS_GEN6(dev)) {
>> -                       if (SNB_READ_WM0_LATENCY()) {
>> +                       if (dev_priv->wm.pri_latency[0] &&
>> +                           dev_priv->wm.spr_latency[0] &&
>> +                           dev_priv->wm.cur_latency[0]) {
>>                                 dev_priv->display.update_wm = sandybridge_update_wm;
>>                                 dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
>>                         } else {
>> @@ -5231,7 +5271,9 @@ void intel_init_pm(struct drm_device *dev)
>>                         }
>>                         dev_priv->display.init_clock_gating = gen6_init_clock_gating;
>>                 } else if (IS_IVYBRIDGE(dev)) {
>> -                       if (SNB_READ_WM0_LATENCY()) {
>> +                       if (dev_priv->wm.pri_latency[0] &&
>> +                           dev_priv->wm.spr_latency[0] &&
>> +                           dev_priv->wm.cur_latency[0]) {
>>                                 dev_priv->display.update_wm = ivybridge_update_wm;
>>                                 dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
>>                         } else {
>> @@ -5241,7 +5283,9 @@ void intel_init_pm(struct drm_device *dev)
>>                         }
>>                         dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
>>                 } else if (IS_HASWELL(dev)) {
>> -                       if (I915_READ64(MCH_SSKPD)) {
>> +                       if (dev_priv->wm.pri_latency[0] &&
>> +                           dev_priv->wm.spr_latency[0] &&
>> +                           dev_priv->wm.cur_latency[0]) {
>>                                 dev_priv->display.update_wm = haswell_update_wm;
>>                                 dev_priv->display.update_sprite_wm =
>>                                         haswell_update_sprite_wm;
>> --
>> 1.8.1.5
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>
> --
> Paulo Zanoni



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 15/35] drm/i915: Print the watermark latencies during init
  2013-07-05  8:57 ` [PATCH 15/35] drm/i915: Print the watermark latencies during init ville.syrjala
@ 2013-07-30 21:49   ` Paulo Zanoni
  2013-07-31  9:47     ` Ville Syrjälä
  0 siblings, 1 reply; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 21:49 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Seeing the watermark latency values in dmesg might help sometimes.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 37919df..5687957 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2392,6 +2392,24 @@ static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
>                 wm[3] *= 2;
>  }
>
> +static void intel_print_wm_latency(struct drm_device *dev, const uint16_t wm[5])
> +{
> +       int level;
> +
> +       for (level = 0; level <= 4; level++) {
> +               unsigned int latency = wm[level];
> +
> +               if (latency == 0)
> +                       continue;

One of the cases that should be interesting to print is exactly when a
latency we expect to be non-zero is zero. Maybe you should do a simple
"switch" statement to get max_level depending on Gen number and print
everything from level 0 to max_level? Then if "latency == 0" we could
even promote the message to a DRM_ERROR?

> +
> +               if (level > 0)
> +                       latency *= 5;
> +
> +               DRM_DEBUG_KMS(" WM%d latency %u (%u.%u usec)\n",
> +                             level, wm[level], latency / 10, latency % 10);
> +       }
> +}
> +
>  static void intel_setup_wm_latency(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -2405,6 +2423,13 @@ static void intel_setup_wm_latency(struct drm_device *dev)
>
>         intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency);
>         intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency);
> +
> +       DRM_DEBUG_KMS("Primary watermark latencies:\n");
> +       intel_print_wm_latency(dev, dev_priv->wm.pri_latency);
> +       DRM_DEBUG_KMS("Sprite watermark latencies:\n");
> +       intel_print_wm_latency(dev, dev_priv->wm.spr_latency);
> +       DRM_DEBUG_KMS("Cursor watermark latencies:\n");
> +       intel_print_wm_latency(dev, dev_priv->wm.cur_latency);
>  }
>
>  static void hsw_compute_wm_parameters(struct drm_device *dev,
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 16/35] drm/i915: Disable specific watermark levels when latency is zero
  2013-07-05  8:57 ` [PATCH 16/35] drm/i915: Disable specific watermark levels when latency is zero ville.syrjala
@ 2013-07-30 21:51   ` Paulo Zanoni
  0 siblings, 0 replies; 74+ messages in thread
From: Paulo Zanoni @ 2013-07-30 21:51 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

2013/7/5  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Return UINT_MAX for the calculated WM level if the latency is zero.
> This will lead to marking the WM level as disabled.
>
> I'm not sure if latency==0 should mean that we want to disable the
> level. But that's the implication I got from the fact that we don't
> even enable the watermark code of the SSKDP register is 0.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 5687957..a919445 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2116,6 +2116,9 @@ static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
>  {
>         uint64_t ret;
>
> +       if (latency == 0)
> +               return UINT_MAX;

IMHO we should scream loud.

> +
>         ret = (uint64_t) pixel_rate * bytes_per_pixel * latency;
>         ret = DIV_ROUND_UP_ULL(ret, 64 * 10000) + 2;
>
> @@ -2128,6 +2131,9 @@ static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
>  {
>         uint32_t ret;
>
> +       if (latency == 0)
> +               return UINT_MAX;
> +
>         ret = (latency * pixel_rate) / (pipe_htotal * 10000);
>         ret = (ret + 1) * horiz_pixels * bytes_per_pixel;
>         ret = DIV_ROUND_UP(ret, 64) + 2;
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 13/35] drm/i915: Store the watermark latency values in dev_priv
  2013-07-30 21:42     ` Paulo Zanoni
@ 2013-07-31  9:43       ` Ville Syrjälä
  0 siblings, 0 replies; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-31  9:43 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Tue, Jul 30, 2013 at 06:42:45PM -0300, Paulo Zanoni wrote:
> I forgot to add intel-gfx in the review email...
> 
> 2013/7/30 Paulo Zanoni <przanoni@gmail.com>:
> > 2013/7/5  <ville.syrjala@linux.intel.com>:
> >> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>
> >> Rather than having to read the latency values out every time, just
> >> store them in dev_priv.
> >>
> >> On ILK and IVB there is a difference between some of the latency
> >> values for different planes, so store the latency values for each
> >> plane type separately, and apply the necesary fixups during init.
> >>
> >> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> ---
> >>  drivers/gpu/drm/i915/i915_drv.h |  9 ++++++
> >>  drivers/gpu/drm/i915/intel_pm.c | 62 +++++++++++++++++++++++++++++++++++------
> >>  2 files changed, 62 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> >> index 99eb980..60f9437 100644
> >> --- a/drivers/gpu/drm/i915/i915_drv.h
> >> +++ b/drivers/gpu/drm/i915/i915_drv.h
> >> @@ -1184,6 +1184,15 @@ typedef struct drm_i915_private {
> >>
> >>         struct i915_suspend_saved_registers regfile;
> >>
> >> +       struct {
> >> +               /* watermark latency values for primary */
> >> +               uint16_t pri_latency[5];
> >> +               /* watermark latency values for sprite */
> >> +               uint16_t spr_latency[5];
> >> +               /* watermark latency values for cursor */
> >> +               uint16_t cur_latency[5];
> >> +       } wm;
> >> +
> >>         /* Old dri1 support infrastructure, beware the dragons ya fools entering
> >>          * here! */
> >>         struct i915_dri1_state dri1;
> >> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> >> index e4d2477..68a1de4 100644
> >> --- a/drivers/gpu/drm/i915/intel_pm.c
> >> +++ b/drivers/gpu/drm/i915/intel_pm.c
> >> @@ -2367,6 +2367,39 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
> >>         }
> >>  }
> >>
> >> +static void intel_fixup_spr_wm_latency(struct drm_device *dev, uint16_t wm[5])
> >> +{
> >> +       /* ILK sprite LP0 latency is 1300 ns */
> >> +       if (INTEL_INFO(dev)->gen == 5)
> >> +               wm[0] = 13;
> >> +}
> >> +
> >> +static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
> >> +{
> >> +       /* ILK cursor LP0 latency is 1300 ns */
> >> +       if (INTEL_INFO(dev)->gen == 5)
> >> +               wm[0] = 13;
> >> +
> >> +       /* WaDoubleCursorLP3Latency:ivb */
> >> +       if (IS_IVYBRIDGE(dev))
> >> +               wm[3] *= 2;
> >
> > Doesn't this WA apply only to pre-production steppings?

Hmm. Possibly. We have it in the current code, but both W/A database
and BSpec do indicate that it's perhaps not needed.

> >
> >
> >> +}
> >> +
> >> +static void intel_setup_wm_latency(struct drm_device *dev)
> >> +{
> >> +       struct drm_i915_private *dev_priv = dev->dev_private;
> >> +
> >> +       intel_read_wm_latency(dev, 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,
> >> +              sizeof dev_priv->wm.pri_latency);
> >
> > Checkpatch.pl complains about these sizeof without parens.

I hate checkpatch for that. Complaining about perfectly valid C. But I
can "fix" it up to reduce checkpatch warnings.

> >
> >
> >> +
> >> +       intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency);
> >> +       intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency);
> >> +}
> >> +
> >>  static void hsw_compute_wm_parameters(struct drm_device *dev,
> >>                                       struct hsw_pipe_wm_parameters *params,
> >>                                       struct hsw_wm_maximums *lp_max_1_2,
> >> @@ -2612,16 +2645,17 @@ static void haswell_update_wm(struct drm_device *dev)
> >>         struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
> >>         struct hsw_pipe_wm_parameters params[3];
> >>         struct hsw_wm_values results_1_2, results_5_6, *best_results;
> >> -       uint16_t wm[5] = {};
> >>         enum hsw_data_buf_partitioning partitioning;
> >>
> >> -       intel_read_wm_latency(dev, wm);
> >>         hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
> >>
> >> -       hsw_compute_wm_results(dev, params, wm, &lp_max_1_2, &results_1_2);
> >> +       hsw_compute_wm_results(dev, params,
> >> +                              dev_priv->wm.pri_latency,
> >> +                              &lp_max_1_2, &results_1_2);
> >>         if (lp_max_1_2.pri != lp_max_5_6.pri) {
> >> -               hsw_compute_wm_results(dev, params, wm, &lp_max_5_6,
> >> -                                      &results_5_6);
> >> +               hsw_compute_wm_results(dev, params,
> >> +                                      dev_priv->wm.pri_latency,
> >> +                                      &lp_max_5_6, &results_5_6);
> >
> > My vote would be to just not pass dev_priv->wm.pri_latency here, it's
> > useless since we're already passing dev. And in the place where we
> > actually use dev_priv->wm.pri_latency we should add a comment saying
> > that on Haswell pri_latency should be the same as the others,
> > otherwise people will start wondering why you're using pri_latency and
> > not the others.

I think I changed it in a later patch to grab the latency values from
the correct place for each plane. I could see about squashing those
changes into this patch if you think it's better.

> >
> >
> >>                 best_results = hsw_find_best_result(&results_1_2, &results_5_6);
> >>         } else {
> >>                 best_results = &results_1_2;
> >> @@ -5211,8 +5245,12 @@ void intel_init_pm(struct drm_device *dev)
> >>
> >>         /* For FIFO watermark updates */
> >>         if (HAS_PCH_SPLIT(dev)) {
> >> +               intel_setup_wm_latency(dev);
> >> +
> >>                 if (IS_GEN5(dev)) {
> >> -                       if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
> >> +                       if (dev_priv->wm.pri_latency[1] &&
> >> +                           dev_priv->wm.spr_latency[1] &&
> >> +                           dev_priv->wm.cur_latency[1])
> >
> > I always wondered why do we have these checks. Do we ever see real
> > machines that have zero values in the latency fields? On some gens we
> > only check wm[0] and not the others, but on ILK we check wm[1] and not
> > the others... Anyway, this is not a problem that should be solved by
> > this patch, but I'd love answers :)

Yeah, I have no idea if these checks make any sense. The reason I'm
checking just wm[1] on ILK is that wm[0] is hardcoded, but wm[1] comes
from the MLTR register, so the new code matches the old code a bit
better. Although since the old code just checks that there is something
in the register, it might plug in the watermark funcs even if not some
of the pri, spr and cur latency values are zero.

> >
> >
> >>                                 dev_priv->display.update_wm = ironlake_update_wm;
> >>                         else {
> >>                                 DRM_DEBUG_KMS("Failed to get proper latency. "
> >> @@ -5221,7 +5259,9 @@ void intel_init_pm(struct drm_device *dev)
> >>                         }
> >>                         dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
> >>                 } else if (IS_GEN6(dev)) {
> >> -                       if (SNB_READ_WM0_LATENCY()) {
> >> +                       if (dev_priv->wm.pri_latency[0] &&
> >> +                           dev_priv->wm.spr_latency[0] &&
> >> +                           dev_priv->wm.cur_latency[0]) {
> >>                                 dev_priv->display.update_wm = sandybridge_update_wm;
> >>                                 dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
> >>                         } else {
> >> @@ -5231,7 +5271,9 @@ void intel_init_pm(struct drm_device *dev)
> >>                         }
> >>                         dev_priv->display.init_clock_gating = gen6_init_clock_gating;
> >>                 } else if (IS_IVYBRIDGE(dev)) {
> >> -                       if (SNB_READ_WM0_LATENCY()) {
> >> +                       if (dev_priv->wm.pri_latency[0] &&
> >> +                           dev_priv->wm.spr_latency[0] &&
> >> +                           dev_priv->wm.cur_latency[0]) {
> >>                                 dev_priv->display.update_wm = ivybridge_update_wm;
> >>                                 dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
> >>                         } else {
> >> @@ -5241,7 +5283,9 @@ void intel_init_pm(struct drm_device *dev)
> >>                         }
> >>                         dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
> >>                 } else if (IS_HASWELL(dev)) {
> >> -                       if (I915_READ64(MCH_SSKPD)) {
> >> +                       if (dev_priv->wm.pri_latency[0] &&
> >> +                           dev_priv->wm.spr_latency[0] &&
> >> +                           dev_priv->wm.cur_latency[0]) {
> >>                                 dev_priv->display.update_wm = haswell_update_wm;
> >>                                 dev_priv->display.update_sprite_wm =
> >>                                         haswell_update_sprite_wm;
> >> --
> >> 1.8.1.5
> >>
> >> _______________________________________________
> >> Intel-gfx mailing list
> >> Intel-gfx@lists.freedesktop.org
> >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> >
> >
> >
> > --
> > Paulo Zanoni
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 15/35] drm/i915: Print the watermark latencies during init
  2013-07-30 21:49   ` Paulo Zanoni
@ 2013-07-31  9:47     ` Ville Syrjälä
  0 siblings, 0 replies; 74+ messages in thread
From: Ville Syrjälä @ 2013-07-31  9:47 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Tue, Jul 30, 2013 at 06:49:27PM -0300, Paulo Zanoni wrote:
> 2013/7/5  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Seeing the watermark latency values in dmesg might help sometimes.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 25 +++++++++++++++++++++++++
> >  1 file changed, 25 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 37919df..5687957 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2392,6 +2392,24 @@ static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
> >                 wm[3] *= 2;
> >  }
> >
> > +static void intel_print_wm_latency(struct drm_device *dev, const uint16_t wm[5])
> > +{
> > +       int level;
> > +
> > +       for (level = 0; level <= 4; level++) {
> > +               unsigned int latency = wm[level];
> > +
> > +               if (latency == 0)
> > +                       continue;
> 
> One of the cases that should be interesting to print is exactly when a
> latency we expect to be non-zero is zero. Maybe you should do a simple
> "switch" statement to get max_level depending on Gen number and print
> everything from level 0 to max_level? Then if "latency == 0" we could
> even promote the message to a DRM_ERROR?

Yeah could be done. OTOH if it really happens in the wild, we'd probably
be looking at a bunch of new bug reports that we can't do anything
about.

> > +
> > +               if (level > 0)
> > +                       latency *= 5;
> > +
> > +               DRM_DEBUG_KMS(" WM%d latency %u (%u.%u usec)\n",
> > +                             level, wm[level], latency / 10, latency % 10);
> > +       }
> > +}
> > +
> >  static void intel_setup_wm_latency(struct drm_device *dev)
> >  {
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> > @@ -2405,6 +2423,13 @@ static void intel_setup_wm_latency(struct drm_device *dev)
> >
> >         intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency);
> >         intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency);
> > +
> > +       DRM_DEBUG_KMS("Primary watermark latencies:\n");
> > +       intel_print_wm_latency(dev, dev_priv->wm.pri_latency);
> > +       DRM_DEBUG_KMS("Sprite watermark latencies:\n");
> > +       intel_print_wm_latency(dev, dev_priv->wm.spr_latency);
> > +       DRM_DEBUG_KMS("Cursor watermark latencies:\n");
> > +       intel_print_wm_latency(dev, dev_priv->wm.cur_latency);
> >  }
> >
> >  static void hsw_compute_wm_parameters(struct drm_device *dev,
> > --
> > 1.8.1.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 06/35] drm/i915: Pass the watermark level to primary WM compute functions
  2013-07-30 19:49   ` Paulo Zanoni
@ 2013-08-01  8:01     ` Ville Syrjälä
  0 siblings, 0 replies; 74+ messages in thread
From: Ville Syrjälä @ 2013-08-01  8:01 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Tue, Jul 30, 2013 at 04:49:18PM -0300, Paulo Zanoni wrote:
> 2013/7/5  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Passing the level insted of "is_lp" seems easier. The end result is the
> > same though.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 6b820c4..f178e26 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2185,7 +2185,7 @@ enum hsw_data_buf_partitioning {
> >  /* For both WM_PIPE and WM_LP. */
> >  static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
> >                                    uint32_t mem_value,
> > -                                  bool is_lp)
> > +                                  int level)
> >  {
> >         uint32_t method1, method2;
> >
> > @@ -2197,7 +2197,7 @@ static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
> >                                  params->pri_bytes_per_pixel,
> >                                  mem_value);
> >
> > -       if (!is_lp)
> > +       if (level == 0)
> >                 return method1;
> >
> >         method2 = ilk_wm_method2(params->pixel_rate,
> > @@ -2266,7 +2266,7 @@ static bool hsw_compute_lp_wm(uint32_t mem_value, struct hsw_wm_maximums *max,
> >         for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) {
> >                 struct hsw_pipe_wm_parameters *p = &params[pipe];
> >
> > -               pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, true);
> > +               pri_val[pipe] = ilk_compute_pri_wm(p, mem_value, 1);
> 
> But now even when you're processing levels 2/3/4 you're telling the
> function that you're doing level 1, which is not true. We don't know
> what kind of code changes we'll be doing in January 2023, so we may
> use that incorrect "level" variable to do something wrong. IMHO,
> either we keep the current code or we pass the actual level.

Yeah. I guess we could keep it as bool now. The original reason for
passing the level was that I handled the IVB cursor latency W/A inside
the wm compute funcs, but now with the pre-populated latency info in
dev_priv passing the level makes less sense.

> 
> 
> >                 spr_val[pipe] = ilk_compute_spr_wm(p, mem_value);
> >                 cur_val[pipe] = ilk_compute_cur_wm(p, mem_value);
> >                 fbc_val[pipe] = ilk_compute_fbc_wm(p, pri_val[pipe], mem_value);
> > @@ -2296,7 +2296,7 @@ static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
> >  {
> >         uint32_t pri_val, cur_val, spr_val;
> >
> > -       pri_val = ilk_compute_pri_wm(params, mem_value, false);
> > +       pri_val = ilk_compute_pri_wm(params, mem_value, 0);
> >         spr_val = ilk_compute_spr_wm(params, mem_value);
> >         cur_val = ilk_compute_cur_wm(params, mem_value);
> >
> > --
> > 1.8.1.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 74+ messages in thread

* Re: [PATCH 11/35] drm/i915: Add SNB/IVB support to intel_read_wm_latency
  2013-07-30 21:01   ` Paulo Zanoni
@ 2013-08-05  5:23     ` Daniel Vetter
  0 siblings, 0 replies; 74+ messages in thread
From: Daniel Vetter @ 2013-08-05  5:23 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Tue, Jul 30, 2013 at 06:01:57PM -0300, Paulo Zanoni wrote:
> 2013/7/5  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > SNB and IVB have slightly a different way to read out the
> > watermark latency values.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index a2ca018..6ff89c6 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2350,6 +2350,13 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
> >                 wm[2] = (sskpd >> 12) & 0xFF;
> >                 wm[3] = (sskpd >> 20) & 0x1FF;
> >                 wm[4] = (sskpd >> 32) & 0x1FF;
> > +       } else if (INTEL_INFO(dev)->gen >= 6) {
> > +               uint32_t sskpd = I915_READ(MCH_SSKPD);
> > +
> > +               wm[0] = (sskpd >> SSKPD_WM0_SHIFT) & SSKPD_WM_MASK;
> > +               wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK;
> > +               wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK;
> > +               wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK;
> 
> My documentation is limited, but this seems at least consistent with
> our current definitions.
> 
> I'd also vote to transform this into a "switch (INTEL_INFO(dev))" and
> add a WARN in case Gen is not 6 or 7.

I guess we can do that once all the stuff here (and maybe 1-2 new
generations) have landed.
> 
> Anyway, the patch looks correct: Reviewed-by: Paulo Zanoni
> <paulo.r.zanoni@intel.com>

Ok, I've pulled in all the patches Paulo has already reviewed and deemed
good. I guess to continue we need to dig out the ilk docs for Paulo ;-)

Thanks for the patches&review.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 74+ messages in thread

end of thread, other threads:[~2013-08-05  5:23 UTC | newest]

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-05  8:57 [PATCH 00/35] drm/i915: ILK+ watermark rewrite ville.syrjala
2013-07-05  8:57 ` [PATCH 01/35] drm/i915: Add scaled paramater to update_sprite_watermarks() ville.syrjala
2013-07-30 18:26   ` Paulo Zanoni
2013-07-30 18:30     ` Ville Syrjälä
2013-07-30 18:49       ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 02/35] drm/i915: Pass the actual sprite width to watermarks functions ville.syrjala
2013-07-30 18:32   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 03/35] drm/i915: Calculate the sprite WM based on the source width instead of the destination width ville.syrjala
2013-07-30 19:01   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 04/35] drm/i915: Rename hsw_wm_get_pixel_rate to ilk_pipe_pixel_rate ville.syrjala
2013-07-30 19:20   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 05/35] drm/i915: Rename most wm compute functions to ilk_ prefix ville.syrjala
2013-07-30 19:37   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 06/35] drm/i915: Pass the watermark level to primary WM compute functions ville.syrjala
2013-07-30 19:49   ` Paulo Zanoni
2013-08-01  8:01     ` Ville Syrjälä
2013-07-05  8:57 ` [PATCH 07/35] drm/i915: Don't pass "mem_value" to ilk_compute_fbc_wm ville.syrjala
2013-07-30 19:54   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 08/35] drm/i915: Change the watermark latency type to uint16_t ville.syrjala
2013-07-30 20:01   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 09/35] drm/i915: Split out reading of HSW watermark latency values ville.syrjala
2013-07-05  9:19   ` Chris Wilson
2013-07-05 10:51     ` Ville Syrjälä
2013-07-30 20:09   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 10/35] drm/i915: Don't multiply the watermark latency values too early ville.syrjala
2013-07-30 20:21   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 11/35] drm/i915: Add SNB/IVB support to intel_read_wm_latency ville.syrjala
2013-07-30 21:01   ` Paulo Zanoni
2013-08-05  5:23     ` Daniel Vetter
2013-07-05  8:57 ` [PATCH 12/35] drm/i915: Add ILK " ville.syrjala
2013-07-05  8:57 ` [PATCH 13/35] drm/i915: Store the watermark latency values in dev_priv ville.syrjala
     [not found]   ` <CA+gsUGQ0JqEZiEUsONJh7nr6rPYRfTxJM79oc5tGcexEudB2Og@mail.gmail.com>
2013-07-30 21:42     ` Paulo Zanoni
2013-07-31  9:43       ` Ville Syrjälä
2013-07-05  8:57 ` [PATCH 14/35] drm/i915: Use the stored cursor and plane latencies properly ville.syrjala
2013-07-05  8:57 ` [PATCH 15/35] drm/i915: Print the watermark latencies during init ville.syrjala
2013-07-30 21:49   ` Paulo Zanoni
2013-07-31  9:47     ` Ville Syrjälä
2013-07-05  8:57 ` [PATCH 16/35] drm/i915: Disable specific watermark levels when latency is zero ville.syrjala
2013-07-30 21:51   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 17/35] drm/i915: Pull watermark level validity check out ville.syrjala
2013-07-05  8:57 ` [PATCH 18/35] drm/i915: Split watermark level computation from the code ville.syrjala
2013-07-05  8:57 ` [PATCH 19/35] drm/i915: Kill fbc_enable from hsw_lp_wm_results ville.syrjala
2013-07-05  8:57 ` [PATCH 20/35] drm/i915: Rename hsw_data_buf_partitioning to intel_ddb_partitioning ville.syrjala
2013-07-05  8:57 ` [PATCH 21/35] drm/i915: Rename hsw_lp_wm_result to intel_wm_level ville.syrjala
2013-07-05  8:57 ` [PATCH 22/35] drm/i915: Calculate max watermark levels for ILK+ ville.syrjala
2013-07-05  8:57 ` [PATCH 23/35] drm/i915; Pull some watermarks state into a separate structure ville.syrjala
2013-07-05  8:57 ` [PATCH 24/35] drm/i915: Split plane watermark parameters into a separate struct ville.syrjala
2013-07-05  8:57 ` [PATCH 25/35] drm/i915: Pass crtc to our update/disable_plane hooks ville.syrjala
2013-07-05  8:57 ` [PATCH 26/35] drm/i915: Don't try to disable plane if it's already disabled ville.syrjala
2013-07-05  8:57 ` [PATCH 27/35] drm/i915: Pass plane and crtc to intel_update_sprite_watermarks ville.syrjala
2013-07-05  8:57 ` [PATCH 28/35] drm/i915: Always call intel_update_sprite_watermarks() when disabling a plane ville.syrjala
2013-07-05  8:57 ` [PATCH 29/35] drm/i915: Pass crtc to intel_update_watermarks() and call it in one place during modeset ville.syrjala
2013-07-05  9:32   ` Chris Wilson
2013-07-05  8:57 ` [PATCH 30/35] drm/i915: Replace the ILK/SNB/IVB/HSW watermark code ville.syrjala
2013-07-05  9:37   ` Chris Wilson
2013-07-05 10:49     ` Ville Syrjälä
2013-07-05 17:46       ` Paulo Zanoni
2013-07-05 18:00         ` Ville Syrjälä
2013-07-05 17:51   ` Paulo Zanoni
2013-07-05 18:11     ` Ville Syrjälä
2013-07-05  8:57 ` [PATCH 31/35] drm/i915: Move HSW linetime watermark handling to modeset code ville.syrjala
2013-07-05 17:44   ` Paulo Zanoni
2013-07-05  8:57 ` [PATCH 32/35] hack: Add debug prints to watermark compute funcs ville.syrjala
2013-07-05  8:57 ` [PATCH 33/35] hack: Don't disable underrun reporting on the first error on ILK/SNB/IVB ville.syrjala
2013-07-05 17:19   ` Paulo Zanoni
2013-07-05 17:34     ` Ville Syrjälä
2013-07-05  8:57 ` [PATCH 34/35] hack: Make fifo underruns DRM_ERROR ville.syrjala
2013-07-05 17:19   ` Paulo Zanoni
2013-07-05 17:39     ` Ville Syrjälä
2013-07-05  8:57 ` [PATCH 35/35] hack: Print watermark programming duration ville.syrjala
2013-07-05 16:54 ` [PATCH 00/35] drm/i915: ILK+ watermark rewrite Paulo Zanoni
2013-07-05 17:22   ` Ville Syrjälä
2013-07-05 17:41     ` Paulo Zanoni
2013-07-05 17:54       ` Ville Syrjälä

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.