All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/24] drm/i915: Two part watermark update for ILK+
@ 2014-03-07 16:32 ville.syrjala
  2014-03-07 16:32 ` [PATCH 01/24] drm/i915: Don't read sprite LP2+ registers on ILK/SNB ville.syrjala
                   ` (23 more replies)
  0 siblings, 24 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

This is the last part of my watermark saga. The main thing is the
introduction of the two part watermark update mechanism.

The original idea I had was to do the watermark programming from the
vblank interrupt handler, but that didn't pan out. So instead we need
to split the watermark update into a pre and post stages. In the pre
stage we swithc over to intermediate watermarks that can handle both
the old and new plane configuration. That allows the start of vblank
where the double buffered registers are latched to happen any time after
we've switched over to the intermediate watermarks. And after we're sure
that planes are using the new configuration, we can switch over to the
optimal watermarks instead or running with the potentially sub-standard
intermediate watermarks. All the watermark programming is now done from
the system workqueue and the interrupt handler just schedules the work
when the target vblank count has been reached.

The split between the patches is rather clumsy in parts. I couldn't
come up with any sane way to keep the patches small and split the
feature up in a sane way. So some of the patchs just add stuff w/o
using it, and then one or two patches later it all comes together.
I think it should be bisectable, but I may have missed something. At
least it compiles all the way through.

The series depends on my earlier drm vblank interrupt series [1],
and I've had it sitting on top of my atomic sprite series [2], so
those two should get merged before this one.

[1] http://lists.freedesktop.org/archives/intel-gfx/2014-March/041207.html
[2] http://lists.freedesktop.org/archives/intel-gfx/2014-February/040118.html

Ville Syrjälä (24):
  drm/i915: Don't read sprite LP2+ registers on ILK/SNB
  drm/i915: Add some more tracked state to intel_pipe_wm
  drm/i915: Skip watermark merging for inactive pipes
  drm/i916: Refactor WM register maximums
  drm/i915: Merge LP1+ watermarks in safer way
  drm/i915: Disable/enable planes as the first/last thing during modeset
    on ILK+
  drm/i915: Remove useless checks from primary enable/disable
  drm/i915: Shuffle wait_for_vblank out of primary_enable/disable funcs
  drm/i915: Keep vblank interrupts enabled while enabling/disabling
    planes
  drm/i915: Leave interrupts enabled while disabling crtcs during
    suspend
  drm/i915: Check hw vs. sw watermark state after programming
  drm/i915: Refactor ilk_validate_pipe_wm()
  drm/i915: Refactor ilk_update_wm
  drm/i915: Add dev_priv->wm.mutex
  drm/i915: Add vblank based delayed watermark update mechanism
  drm/i915: Split watermark programming into pre and post steps
  drm/i915: Actually perform the watermark update in two phases
  drm/i915: Wait for watermark updates to finish before disabling a pipe
  drm/i915: Refactor get_other_active_crtc()
  drm/i915: Disable LP1+ watermarks while changing the number of active
    pipes
  drm/i915: Keep track of who disabled LP1+ watermarks
  drm/i915: Prefer the 5/6 DDB split when primary is disabled
  drm/i915: Add a workaround for sprite only <-> primary only switching
  drm/i915: Don't disable LP1+ watermarks for every frame when scaled

 drivers/gpu/drm/i915/i915_drv.c      |   3 +-
 drivers/gpu/drm/i915/i915_drv.h      |  38 +-
 drivers/gpu/drm/i915/i915_irq.c      |  12 +-
 drivers/gpu/drm/i915/intel_display.c | 267 ++++++----
 drivers/gpu/drm/i915/intel_drv.h     |  85 +++-
 drivers/gpu/drm/i915/intel_pm.c      | 924 +++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_sprite.c  | 118 +++--
 7 files changed, 1155 insertions(+), 292 deletions(-)

-- 
1.8.3.2

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

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

* [PATCH 01/24] drm/i915: Don't read sprite LP2+ registers on ILK/SNB
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-04 21:35   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm ville.syrjala
                   ` (22 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Sprite LP2+ registers don't exist on ILK/SNB so don't read them.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 47b502b..26c79ed 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2664,8 +2664,10 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
 	hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
 
 	hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
-	hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
-	hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
+	if (INTEL_INFO(dev)->gen >= 7) {
+		hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
+		hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
+	}
 
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
-- 
1.8.3.2

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

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

* [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
  2014-03-07 16:32 ` [PATCH 01/24] drm/i915: Don't read sprite LP2+ registers on ILK/SNB ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-07 14:14   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 03/24] drm/i915: Skip watermark merging for inactive pipes ville.syrjala
                   ` (21 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

intel_pipe_wm will be used to track the state in different stages
of the watermark update process. For that we need to keep a bit
more state in intel_pipe_wm.

We also need to separate the multi-pipe intel_wm_config computation
from ilk_compute_wm_parameters() as that one deals with the future
state, and we need the intel_wm_config to match the current hardware
state at the time we do the watermark merging for multiple pipes.

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

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 8c9892d..f022a78 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -333,6 +333,9 @@ struct intel_pipe_wm {
 	struct intel_wm_level wm[5];
 	uint32_t linetime;
 	bool fbc_wm_enabled;
+	bool pipe_enabled;
+	bool sprites_enabled;
+	bool sprites_scaled;
 };
 
 struct intel_crtc {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 26c79ed..e0d1c8b 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2105,38 +2105,52 @@ static void intel_setup_wm_latency(struct drm_device *dev)
 }
 
 static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
-				      struct ilk_pipe_wm_parameters *p,
-				      struct intel_wm_config *config)
+				      struct ilk_pipe_wm_parameters *p)
 {
 	struct drm_device *dev = crtc->dev;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	enum pipe pipe = intel_crtc->pipe;
 	struct drm_plane *plane;
 
-	p->active = intel_crtc_active(crtc);
-	if (p->active) {
-		p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_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.pipe_src_w;
-		p->cur.horiz_pixels = 64;
-		/* TODO: for now, assume primary and cursor planes are always enabled. */
-		p->pri.enabled = true;
-		p->cur.enabled = true;
-	}
+	if (!intel_crtc_active(crtc))
+		return;
 
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-		config->num_pipes_active += intel_crtc_active(crtc);
+	p->active = true;
+	p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_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.pipe_src_w;
+	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);
 
-		if (intel_plane->pipe == pipe)
+		if (intel_plane->pipe == pipe) {
 			p->spr = intel_plane->wm;
+			break;
+		}
+	}
+}
 
-		config->sprites_enabled |= intel_plane->wm.enabled;
-		config->sprites_scaled |= intel_plane->wm.scaled;
+static void ilk_compute_wm_config(struct drm_device *dev,
+				  struct intel_wm_config *config)
+{
+	struct intel_crtc *intel_crtc;
+
+	/* Compute the currently _active_ config */
+	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->num_pipes_active++;
 	}
 }
 
@@ -2159,6 +2173,10 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	/* LP0 watermarks always use 1/2 DDB partitioning */
 	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
 
+	pipe_wm->pipe_enabled = params->active;
+	pipe_wm->sprites_enabled = params->spr.enabled;
+	pipe_wm->sprites_scaled = params->spr.scaled;
+
 	/* ILK/SNB: LP2+ watermarks only w/o sprites */
 	if (INTEL_INFO(dev)->gen <= 6 && params->spr.enabled)
 		max_level = 1;
@@ -2548,7 +2566,7 @@ static void ilk_update_wm(struct drm_crtc *crtc)
 	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
 	struct intel_wm_config config = {};
 
-	ilk_compute_wm_parameters(crtc, &params, &config);
+	ilk_compute_wm_parameters(crtc, &params);
 
 	intel_compute_pipe_wm(crtc, &params, &pipe_wm);
 
@@ -2557,6 +2575,8 @@ static void ilk_update_wm(struct drm_crtc *crtc)
 
 	intel_crtc->wm.active = pipe_wm;
 
+	ilk_compute_wm_config(dev, &config);
+
 	ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
 	ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
 
@@ -2623,7 +2643,9 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
 
-	if (intel_crtc_active(crtc)) {
+	active->pipe_enabled = intel_crtc_active(crtc);
+
+	if (active->pipe_enabled) {
 		u32 tmp = hw->wm_pipe[pipe];
 
 		/*
-- 
1.8.3.2

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

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

* [PATCH 03/24] drm/i915: Skip watermark merging for inactive pipes
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
  2014-03-07 16:32 ` [PATCH 01/24] drm/i915: Don't read sprite LP2+ registers on ILK/SNB ville.syrjala
  2014-03-07 16:32 ` [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-07 16:23   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 04/24] drm/i916: Refactor WM register maximums ville.syrjala
                   ` (20 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Even though the inactive pipes should have their watermarks set to all 0
with enable=true, we can possibly shave off a few cycles by completely
skipping the merge procedure for inactive pipes.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e0d1c8b..e13937f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2206,8 +2206,11 @@ static void ilk_merge_wm_level(struct drm_device *dev,
 	const struct intel_crtc *intel_crtc;
 
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
-		const struct intel_wm_level *wm =
-			&intel_crtc->wm.active.wm[level];
+		const struct intel_pipe_wm *active = &intel_crtc->wm.active;
+		const struct intel_wm_level *wm = &active->wm[level];
+
+		if (!active->pipe_enabled)
+			continue;
 
 		if (!wm->enable)
 			return;
-- 
1.8.3.2

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

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

* [PATCH 04/24] drm/i916: Refactor WM register maximums
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (2 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 03/24] drm/i915: Skip watermark merging for inactive pipes ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-07 16:34   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 05/24] drm/i915: Merge LP1+ watermarks in safer way ville.syrjala
                   ` (19 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

We will have another use for the maximum watermark values that the
registers can hold. Pull those out into separate functions.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e13937f..f061ef1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1821,6 +1821,40 @@ static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
 		return 512;
 }
 
+static unsigned int ilk_plane_wm_reg_max(const struct drm_device *dev,
+					 int level, bool is_sprite)
+{
+	if (INTEL_INFO(dev)->gen >= 8)
+		/* BDW primary/sprite plane watermarks */
+		return level == 0 ? 255 : 2047;
+	else if (INTEL_INFO(dev)->gen >= 7)
+		/* IVB/HSW primary/sprite plane watermarks */
+		return level == 0 ? 127 : 1023;
+	else if (!is_sprite)
+		/* ILK/SNB primary plane watermarks */
+		return level == 0 ? 127 : 511;
+	else
+		/* ILK/SNB sprite plane watermarks */
+		return level == 0 ? 63 : 255;
+}
+
+static unsigned int ilk_cursor_wm_reg_max(const struct drm_device *dev,
+					  int level)
+{
+	if (INTEL_INFO(dev)->gen >= 7)
+		return level == 0 ? 63 : 255;
+	else
+		return level == 0 ? 31 : 63;
+}
+
+static unsigned int ilk_fbc_wm_reg_max(const struct drm_device *dev)
+{
+	if (INTEL_INFO(dev)->gen >= 8)
+		return 31;
+	else
+		return 15;
+}
+
 /* Calculate the maximum primary/sprite plane watermark */
 static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 				     int level,
@@ -1829,7 +1863,6 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 				     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 && !config->sprites_enabled)
@@ -1860,19 +1893,7 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 	}
 
 	/* clamp to max that the registers can hold */
-	if (INTEL_INFO(dev)->gen >= 8)
-		max = level == 0 ? 255 : 2047;
-	else 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);
+	return min(fifo_size, ilk_plane_wm_reg_max(dev, level, is_sprite));
 }
 
 /* Calculate the maximum cursor plane watermark */
@@ -1885,20 +1906,7 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
 		return 64;
 
 	/* otherwise 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(const struct drm_device *dev)
-{
-	/* max that registers can hold */
-	if (INTEL_INFO(dev)->gen >= 8)
-		return 31;
-	else
-		return 15;
+	return ilk_cursor_wm_reg_max(dev, level);
 }
 
 static void ilk_compute_wm_maximums(const struct drm_device *dev,
@@ -1910,7 +1918,7 @@ static void ilk_compute_wm_maximums(const struct drm_device *dev,
 	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(dev);
+	max->fbc = ilk_fbc_wm_reg_max(dev);
 }
 
 static bool ilk_validate_wm_level(int level,
-- 
1.8.3.2

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

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

* [PATCH 05/24] drm/i915: Merge LP1+ watermarks in safer way
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (3 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 04/24] drm/i916: Refactor WM register maximums ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-23 19:13   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 06/24] drm/i915: Disable/enable planes as the first/last thing during modeset on ILK+ ville.syrjala
                   ` (18 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

On ILK when we disable a particular watermark level, we must
maintain the actual watermark values for that level for some time
(until the next vblank possibly). Otherwise we risk underruns.

In order to achieve that result we must merge the LP1+ watermarks a
bit differently since we must also merge levels that are to be
disabled. We must also make sure we don't overflow the fields in the
watermark registers in case the calculated watermarks come out too
big to fit.

As early as possbile we mark all computed watermark levels as
disabled if they would exceed the register maximums. We make sure
to leave the actual watermarks for such levels zeroed out. The during
merging, we take the maxium values for every level, regardless if
they're disabled or not. That may seem a bit pointless since at the
moment all the watermark levels we merge should have their values
zeroed if the level is already disabled. However soon we will be
dealing with intermediate watermarks that, in addition to the new
watermark values, also contain the previous watermark values, and so
levels that are disabled may no longer be zeroed out.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f061ef1..ba4b23e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1921,6 +1921,16 @@ static void ilk_compute_wm_maximums(const struct drm_device *dev,
 	max->fbc = ilk_fbc_wm_reg_max(dev);
 }
 
+static void ilk_compute_wm_reg_maximums(struct drm_device *dev,
+					int level,
+					struct ilk_wm_maximums *max)
+{
+	max->pri = ilk_plane_wm_reg_max(dev, level, false);
+	max->spr = ilk_plane_wm_reg_max(dev, level, true);
+	max->cur = ilk_cursor_wm_reg_max(dev, level);
+	max->fbc = ilk_fbc_wm_reg_max(dev);
+}
+
 static bool ilk_validate_wm_level(int level,
 				  const struct ilk_wm_maximums *max,
 				  struct intel_wm_level *result)
@@ -2178,9 +2188,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	};
 	struct ilk_wm_maximums max;
 
-	/* LP0 watermarks always use 1/2 DDB partitioning */
-	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
-
 	pipe_wm->pipe_enabled = params->active;
 	pipe_wm->sprites_enabled = params->spr.enabled;
 	pipe_wm->sprites_scaled = params->spr.scaled;
@@ -2193,15 +2200,37 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	if (params->spr.scaled)
 		max_level = 0;
 
-	for (level = 0; level <= max_level; level++)
-		ilk_compute_wm_level(dev_priv, level, params,
-				     &pipe_wm->wm[level]);
+	ilk_compute_wm_level(dev_priv, 0, params, &pipe_wm->wm[0]);
 
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
 
+	/* LP0 watermarks always use 1/2 DDB partitioning */
+	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+
 	/* At least LP0 must be valid */
-	return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
+	if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
+		return false;
+
+	ilk_compute_wm_reg_maximums(dev, 1, &max);
+
+	for (level = 1; level <= max_level; level++) {
+		struct intel_wm_level wm = {};
+
+		ilk_compute_wm_level(dev_priv, level, params, &wm);
+
+		/*
+		 * Disable any watermark level that exceeds the
+		 * register maximums since such watermarks are
+		 * always invalid.
+		 */
+		if (!ilk_validate_wm_level(level, &max, &wm))
+			break;
+
+		pipe_wm->wm[level] = wm;
+	}
+
+	return true;
 }
 
 /*
@@ -2213,6 +2242,8 @@ static void ilk_merge_wm_level(struct drm_device *dev,
 {
 	const struct intel_crtc *intel_crtc;
 
+	ret_wm->enable = true;
+
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
 		const struct intel_pipe_wm *active = &intel_crtc->wm.active;
 		const struct intel_wm_level *wm = &active->wm[level];
@@ -2220,16 +2251,18 @@ static void ilk_merge_wm_level(struct drm_device *dev,
 		if (!active->pipe_enabled)
 			continue;
 
-		if (!wm->enable)
-			return;
+		/*
+		 * The watermark values may have been used in the past,
+		 * so we must maintain them in the registers for some
+		 * time even if the level is now disabled.
+		 */
+		ret_wm->enable &= wm->enable;
 
 		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);
 	}
-
-	ret_wm->enable = true;
 }
 
 /*
@@ -2241,6 +2274,7 @@ static void ilk_wm_merge(struct drm_device *dev,
 			 struct intel_pipe_wm *merged)
 {
 	int level, max_level = ilk_wm_max_level(dev);
+	int last_enabled_level = max_level;
 
 	/* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
 	if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
@@ -2256,15 +2290,19 @@ static void ilk_wm_merge(struct drm_device *dev,
 
 		ilk_merge_wm_level(dev, level, wm);
 
-		if (!ilk_validate_wm_level(level, max, wm))
-			break;
+		if (level > last_enabled_level)
+			wm->enable = false;
+		else if (!ilk_validate_wm_level(level, max, wm))
+			/* make sure all following levels get disabled */
+			last_enabled_level = level - 1;
 
 		/*
 		 * The spec says it is preferred to disable
 		 * FBC WMs instead of disabling a WM level.
 		 */
 		if (wm->fbc_val > max->fbc) {
-			merged->fbc_wm_enabled = false;
+			if (wm->enable)
+				merged->fbc_wm_enabled = false;
 			wm->fbc_val = 0;
 		}
 	}
@@ -2319,14 +2357,19 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 		level = ilk_wm_lp_to_level(wm_lp, merged);
 
 		r = &merged->wm[level];
-		if (!r->enable)
-			break;
 
-		results->wm_lp[wm_lp - 1] = WM3_LP_EN |
+		/*
+		 * Maintain the watermark values even if the level is
+		 * disabled. Doing otherwise could cause underruns.
+		 */
+		results->wm_lp[wm_lp - 1] =
 			(ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT) |
 			(r->pri_val << WM1_LP_SR_SHIFT) |
 			r->cur_val;
 
+		if (r->enable)
+			results->wm_lp[wm_lp - 1] |= WM1_LP_SR_EN;
+
 		if (INTEL_INFO(dev)->gen >= 8)
 			results->wm_lp[wm_lp - 1] |=
 				r->fbc_val << WM1_LP_FBC_SHIFT_BDW;
@@ -2334,6 +2377,10 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 			results->wm_lp[wm_lp - 1] |=
 				r->fbc_val << WM1_LP_FBC_SHIFT;
 
+		/*
+		 * Always set WM1S_LP_EN when spr_val != 0, even if the
+		 * level is disabled. Doing otherwise could cause underruns.
+		 */
 		if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) {
 			WARN_ON(wm_lp != 1);
 			results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
-- 
1.8.3.2

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

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

* [PATCH 06/24] drm/i915: Disable/enable planes as the first/last thing during modeset on ILK+
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (4 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 05/24] drm/i915: Merge LP1+ watermarks in safer way ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-07 19:51   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 07/24] drm/i915: Remove useless checks from primary enable/disable ville.syrjala
                   ` (17 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

We already do this for HSW, but doing it makes sense for everything else
as well. Extend it for ILK/SNB/IVB since that's where the new watermark
code is used.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c309dd1..7938556 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3543,6 +3543,48 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
 		hsw_enable_ips(intel_crtc);
 }
 
+static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+
+	intel_enable_primary_plane(dev_priv, plane, pipe);
+	intel_enable_planes(crtc);
+	intel_crtc_update_cursor(crtc, true);
+
+	hsw_enable_ips(intel_crtc);
+
+	mutex_lock(&dev->struct_mutex);
+	intel_update_fbc(dev);
+	mutex_unlock(&dev->struct_mutex);
+
+	drm_vblank_on(dev, pipe);
+}
+
+static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+
+	intel_crtc_wait_for_pending_flips(crtc);
+	drm_vblank_off(dev, pipe);
+
+	if (dev_priv->fbc.plane == plane)
+		intel_disable_fbc(dev);
+
+	hsw_disable_ips(intel_crtc);
+
+	intel_crtc_update_cursor(crtc, false);
+	intel_disable_planes(crtc);
+	intel_disable_primary_plane(dev_priv, plane, pipe);
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3550,7 +3592,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
 
 	WARN_ON(!crtc->enabled);
 
@@ -3586,23 +3627,18 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	intel_update_watermarks(crtc);
 	intel_enable_pipe(intel_crtc);
-	intel_enable_primary_plane(dev_priv, plane, pipe);
-	intel_enable_planes(crtc);
-	intel_crtc_update_cursor(crtc, true);
 
 	if (intel_crtc->config.has_pch_encoder)
 		ironlake_pch_enable(crtc);
 
-	mutex_lock(&dev->struct_mutex);
-	intel_update_fbc(dev);
-	mutex_unlock(&dev->struct_mutex);
-
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
 
 	if (HAS_PCH_CPT(dev))
 		cpt_verify_modeset(dev, intel_crtc->pipe);
 
+	ilk_crtc_enable_planes(crtc);
+
 	/*
 	 * There seems to be a race in PCH platform hw (at least on some
 	 * outputs) where an enabled pipe still completes any pageflip right
@@ -3612,8 +3648,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	 * happening.
 	 */
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
-
-	drm_vblank_on(dev, pipe);
 }
 
 /* IPS only exists on ULT machines and is tied to pipe A. */
@@ -3622,49 +3656,6 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
 	return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
 }
 
-static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
-
-	intel_enable_primary_plane(dev_priv, plane, pipe);
-	intel_enable_planes(crtc);
-	intel_crtc_update_cursor(crtc, true);
-
-	hsw_enable_ips(intel_crtc);
-
-	mutex_lock(&dev->struct_mutex);
-	intel_update_fbc(dev);
-	mutex_unlock(&dev->struct_mutex);
-
-	drm_vblank_on(dev, pipe);
-}
-
-static void haswell_crtc_disable_planes(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
-
-	intel_crtc_wait_for_pending_flips(crtc);
-	drm_vblank_off(dev, pipe);
-
-	/* FBC must be disabled before disabling the plane on HSW. */
-	if (dev_priv->fbc.plane == plane)
-		intel_disable_fbc(dev);
-
-	hsw_disable_ips(intel_crtc);
-
-	intel_crtc_update_cursor(crtc, false);
-	intel_disable_planes(crtc);
-	intel_disable_primary_plane(dev_priv, plane, pipe);
-}
-
 /*
  * This implements the workaround described in the "notes" section of the mode
  * set sequence documentation. When going from no pipes or single pipe to
@@ -3747,7 +3738,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	/* If we change the relative order between pipe/planes enabling, we need
 	 * to change the workaround. */
 	haswell_mode_set_planes_workaround(intel_crtc);
-	haswell_crtc_enable_planes(crtc);
+	ilk_crtc_enable_planes(crtc);
 }
 
 static void ironlake_pfit_disable(struct intel_crtc *crtc)
@@ -3772,26 +3763,16 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
 	u32 reg, temp;
 
-
 	if (!intel_crtc->active)
 		return;
 
+	ilk_crtc_disable_planes(crtc);
+
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->disable(encoder);
 
-	intel_crtc_wait_for_pending_flips(crtc);
-	drm_vblank_off(dev, pipe);
-
-	if (dev_priv->fbc.plane == plane)
-		intel_disable_fbc(dev);
-
-	intel_crtc_update_cursor(crtc, false);
-	intel_disable_planes(crtc);
-	intel_disable_primary_plane(dev_priv, plane, pipe);
-
 	if (intel_crtc->config.has_pch_encoder)
 		intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
 
@@ -3850,7 +3831,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	if (!intel_crtc->active)
 		return;
 
-	haswell_crtc_disable_planes(crtc);
+	ilk_crtc_disable_planes(crtc);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder) {
 		intel_opregion_notify_encoder(encoder, false);
-- 
1.8.3.2

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

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

* [PATCH 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (5 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 06/24] drm/i915: Disable/enable planes as the first/last thing during modeset on ILK+ ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 21:29   ` Daniel Vetter
  2014-03-07 16:32 ` [PATCH 08/24] drm/i915: Shuffle wait_for_vblank out of primary_enable/disable funcs ville.syrjala
                   ` (16 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

We won't be calling intel_enable_primary_plane() or
intel_disable_primary_plane() with the primary plane in the
wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7938556..2815351 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1896,8 +1896,6 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
 
 	reg = DSPCNTR(plane);
 	val = I915_READ(reg);
-	if (val & DISPLAY_PLANE_ENABLE)
-		return;
 
 	I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
 	intel_flush_primary_plane(dev_priv, plane);
@@ -1926,8 +1924,6 @@ static void intel_disable_primary_plane(struct drm_i915_private *dev_priv,
 
 	reg = DSPCNTR(plane);
 	val = I915_READ(reg);
-	if ((val & DISPLAY_PLANE_ENABLE) == 0)
-		return;
 
 	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
 	intel_flush_primary_plane(dev_priv, plane);
-- 
1.8.3.2

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

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

* [PATCH 08/24] drm/i915: Shuffle wait_for_vblank out of primary_enable/disable funcs
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (6 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 07/24] drm/i915: Remove useless checks from primary enable/disable ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-07 20:27   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes ville.syrjala
                   ` (15 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Rather than have a wait_for_vblank() in the primary plane enable/disable
funcs, move the wait_for_vblank() to happen after enabling/disabling all
planes.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2815351..4986887 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1899,7 +1899,6 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
 
 	I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
 	intel_flush_primary_plane(dev_priv, plane);
-	intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
 /**
@@ -1927,7 +1926,6 @@ static void intel_disable_primary_plane(struct drm_i915_private *dev_priv,
 
 	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
 	intel_flush_primary_plane(dev_priv, plane);
-	intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
 static bool need_vtd_wa(struct drm_device *dev)
@@ -3550,6 +3548,7 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
 	intel_enable_primary_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
 	intel_crtc_update_cursor(crtc, true);
+	intel_wait_for_vblank(dev, pipe);
 
 	hsw_enable_ips(intel_crtc);
 
@@ -3579,6 +3578,7 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
 	intel_crtc_update_cursor(crtc, false);
 	intel_disable_planes(crtc);
 	intel_disable_primary_plane(dev_priv, plane, pipe);
+	intel_wait_for_vblank(dev, pipe);
 }
 
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
@@ -4211,6 +4211,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 	intel_enable_primary_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
 	intel_crtc_update_cursor(crtc, true);
+	intel_wait_for_vblank(dev, pipe);
 
 	intel_update_fbc(dev);
 
@@ -4258,6 +4259,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
 	/* Give the overlay scaler a chance to enable if it's on this pipe */
 	intel_crtc_dpms_overlay(intel_crtc, true);
+	intel_wait_for_vblank(dev, pipe);
 
 	intel_update_fbc(dev);
 
@@ -4308,6 +4310,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	intel_crtc_update_cursor(crtc, false);
 	intel_disable_planes(crtc);
 	intel_disable_primary_plane(dev_priv, plane, pipe);
+	intel_wait_for_vblank(dev, pipe);
 
 	intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
 	intel_disable_pipe(dev_priv, pipe);
-- 
1.8.3.2

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

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

* [PATCH 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (7 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 08/24] drm/i915: Shuffle wait_for_vblank out of primary_enable/disable funcs ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-07 21:21   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 10/24] drm/i915: Leave interrupts enabled while disabling crtcs during suspend ville.syrjala
                   ` (14 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

We may have use for vblank interrupts during plane enabling/disabling, so
don't call drm_vblank_off() until planes are off, and call
drm_vblank_on() just before we start to enable the planes.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4986887..c028b5c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3545,6 +3545,8 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
+	drm_vblank_on(dev, pipe);
+
 	intel_enable_primary_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
 	intel_crtc_update_cursor(crtc, true);
@@ -3555,8 +3557,6 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
 	mutex_unlock(&dev->struct_mutex);
-
-	drm_vblank_on(dev, pipe);
 }
 
 static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
@@ -3568,7 +3568,6 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
 	int plane = intel_crtc->plane;
 
 	intel_crtc_wait_for_pending_flips(crtc);
-	drm_vblank_off(dev, pipe);
 
 	if (dev_priv->fbc.plane == plane)
 		intel_disable_fbc(dev);
@@ -3579,6 +3578,8 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
 	intel_disable_planes(crtc);
 	intel_disable_primary_plane(dev_priv, plane, pipe);
 	intel_wait_for_vblank(dev, pipe);
+
+	drm_vblank_off(dev, pipe);
 }
 
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
-- 
1.8.3.2

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

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

* [PATCH 10/24] drm/i915: Leave interrupts enabled while disabling crtcs during suspend
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (8 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-24 13:33   ` Daniel Vetter
  2014-03-07 16:32 ` [PATCH 11/24] drm/i915: Check hw vs. sw watermark state after programming ville.syrjala
                   ` (13 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

The new watermaek update mechanism requires interrupts to work
correctly. Because of this we need interrupts while disabling crtcs
during suspend. So move the irq disable to happen a bit later.

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

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 658fe24..079fb904 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -448,7 +448,6 @@ static int i915_drm_freeze(struct drm_device *dev)
 
 		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
 
-		drm_irq_uninstall(dev);
 		dev_priv->enable_hotplug_processing = false;
 		/*
 		 * Disable CRTCs directly since we want to preserve sw state
@@ -459,6 +458,8 @@ static int i915_drm_freeze(struct drm_device *dev)
 			dev_priv->display.crtc_disable(crtc);
 		mutex_unlock(&dev->mode_config.mutex);
 
+		drm_irq_uninstall(dev);
+
 		intel_modeset_suspend_hw(dev);
 	}
 
-- 
1.8.3.2

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

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

* [PATCH 11/24] drm/i915: Check hw vs. sw watermark state after programming
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (9 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 10/24] drm/i915: Leave interrupts enabled while disabling crtcs during suspend ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-23 21:16   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 12/24] drm/i915: Refactor ilk_validate_pipe_wm() ville.syrjala
                   ` (12 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Make sure we programmed the watermarks correctly, by reading out the
hardware state again after programming and comparing it with the
state we supposedly programmed into hardware. Dump the watermark
registers after a mismatch, very much like we for the pipe config.
The only difference is that we don't dump the entire watermark
software tracking state since that's spread around a bit.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ba4b23e..e519578a1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2524,15 +2524,84 @@ static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
 	return changed;
 }
 
+static void _ilk_pipe_wm_get_hw_state(struct drm_device *dev,
+				      enum pipe pipe,
+				      struct ilk_wm_values *hw)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	static const unsigned int wm0_pipe_reg[] = {
+		[PIPE_A] = WM0_PIPEA_ILK,
+		[PIPE_B] = WM0_PIPEB_ILK,
+		[PIPE_C] = WM0_PIPEC_IVB,
+	};
+
+	hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
+
+	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+		hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
+}
+
+static void _ilk_wm_get_hw_state(struct drm_device *dev,
+				 struct ilk_wm_values *hw)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum pipe pipe;
+
+	for_each_pipe(pipe)
+		_ilk_pipe_wm_get_hw_state(dev, pipe, hw);
+
+	hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
+	hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
+	hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
+
+	hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
+	if (INTEL_INFO(dev)->gen >= 7) {
+		hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
+		hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
+	}
+
+	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+		hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
+			INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
+	else if (IS_IVYBRIDGE(dev))
+		hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
+			INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
+
+	hw->enable_fbc_wm =
+		!(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
+}
+
+static void ilk_dump_wm_values(const struct ilk_wm_values *hw,
+			       const char *context)
+{
+	DRM_DEBUG_KMS("%s watermark values\n", context);
+	DRM_DEBUG_KMS("WM_PIPE_A = 0x%08x\n",  hw->wm_pipe[PIPE_A]);
+	DRM_DEBUG_KMS("WM_PIPE_B = 0x%08x\n",  hw->wm_pipe[PIPE_B]);
+	DRM_DEBUG_KMS("WM_PIPE_C = 0x%08x\n",  hw->wm_pipe[PIPE_C]);
+	DRM_DEBUG_KMS("WM_LP_1 = 0x%08x\n", hw->wm_lp[0]);
+	DRM_DEBUG_KMS("WM_LP_2 = 0x%08x\n", hw->wm_lp[1]);
+	DRM_DEBUG_KMS("WM_LP_3 = 0x%08x\n", hw->wm_lp[2]);
+	DRM_DEBUG_KMS("WM_LP_SPR_1 = 0x%08x\n", hw->wm_lp_spr[0]);
+	DRM_DEBUG_KMS("WM_LP_SPR_2 = 0x%08x\n", hw->wm_lp_spr[1]);
+	DRM_DEBUG_KMS("WM_LP_SPR_3 = 0x%08x\n", hw->wm_lp_spr[2]);
+	DRM_DEBUG_KMS("WM_LINETIME_A = 0x%08x\n", hw->wm_linetime[PIPE_A]);
+	DRM_DEBUG_KMS("WM_LINETIME_B = 0x%08x\n", hw->wm_linetime[PIPE_B]);
+	DRM_DEBUG_KMS("WM_LINETIME_C = 0x%08x\n", hw->wm_linetime[PIPE_C]);
+	DRM_DEBUG_KMS("enable FBC watermark = %d\n", hw->enable_fbc_wm);
+	DRM_DEBUG_KMS("DDB partitioning = %s\n",
+		      hw->partitioning == INTEL_DDB_PART_1_2 ? "1/2" : "5/6");
+}
+
 /*
  * 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 ilk_write_wm_values(struct drm_i915_private *dev_priv,
-				struct ilk_wm_values *results)
+				const struct ilk_wm_values *results)
 {
 	struct drm_device *dev = dev_priv->dev;
 	struct ilk_wm_values *previous = &dev_priv->wm.hw;
+	struct ilk_wm_values hw = {};
 	unsigned int dirty;
 	uint32_t val;
 
@@ -2602,6 +2671,14 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
 
 	dev_priv->wm.hw = *results;
+
+	_ilk_wm_get_hw_state(dev, &hw);
+
+	if (memcmp(results, &hw, sizeof(hw))) {
+		WARN(1, "watermark state doesn't match!\n");
+		ilk_dump_wm_values(&hw, "[hw state]");
+		ilk_dump_wm_values(results, "[sw state]");
+	}
 }
 
 static bool ilk_disable_lp_wm(struct drm_device *dev)
@@ -2683,23 +2760,14 @@ static void ilk_update_sprite_wm(struct drm_plane *plane,
 	ilk_update_wm(crtc);
 }
 
-static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
+static void _ilk_pipe_wm_hw_to_sw(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct ilk_wm_values *hw = &dev_priv->wm.hw;
+	const struct ilk_wm_values *hw = &dev_priv->wm.hw;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_pipe_wm *active = &intel_crtc->wm.active;
 	enum pipe pipe = intel_crtc->pipe;
-	static const unsigned int wm0_pipe_reg[] = {
-		[PIPE_A] = WM0_PIPEA_ILK,
-		[PIPE_B] = WM0_PIPEB_ILK,
-		[PIPE_C] = WM0_PIPEC_IVB,
-	};
-
-	hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-		hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
 
 	active->pipe_enabled = intel_crtc_active(crtc);
 
@@ -2733,31 +2801,12 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 void ilk_wm_get_hw_state(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct ilk_wm_values *hw = &dev_priv->wm.hw;
 	struct drm_crtc *crtc;
 
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-		ilk_pipe_wm_get_hw_state(crtc);
-
-	hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
-	hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
-	hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
-
-	hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
-	if (INTEL_INFO(dev)->gen >= 7) {
-		hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
-		hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
-	}
+	_ilk_wm_get_hw_state(dev, &dev_priv->wm.hw);
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-		hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
-			INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
-	else if (IS_IVYBRIDGE(dev))
-		hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
-			INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
-
-	hw->enable_fbc_wm =
-		!(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		_ilk_pipe_wm_hw_to_sw(crtc);
 }
 
 /**
-- 
1.8.3.2

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

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

* [PATCH 12/24] drm/i915: Refactor ilk_validate_pipe_wm()
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (10 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 11/24] drm/i915: Check hw vs. sw watermark state after programming ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-23 21:23   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 13/24] drm/i915: Refactor ilk_update_wm ville.syrjala
                   ` (11 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Pull the LP0 validate out from intel_compute_pipe_wm() into a separate
function. We will have further need for such a function to validate
both the final watermarks and the intermediate watermarks we will be
using while the plane(s) transition between different configurations.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e519578a1..e142095 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2172,6 +2172,24 @@ static void ilk_compute_wm_config(struct drm_device *dev,
 	}
 }
 
+static bool ilk_validate_pipe_wm(struct drm_device *dev,
+				 struct intel_pipe_wm *pipe_wm)
+{
+	/* LP0 watermark maximums depend on this pipe alone */
+	const struct intel_wm_config config = {
+		.num_pipes_active = 1,
+		.sprites_enabled = pipe_wm->sprites_enabled,
+		.sprites_scaled = pipe_wm->sprites_scaled,
+	};
+	struct ilk_wm_maximums max;
+
+	/* LP0 watermarks always use 1/2 DDB partitioning */
+	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+
+	/* At least LP0 must be valid */
+	return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
+}
+
 /* Compute new watermarks for the pipe */
 static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 				  const struct ilk_pipe_wm_parameters *params,
@@ -2180,12 +2198,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	const struct drm_i915_private *dev_priv = dev->dev_private;
 	int level, max_level = ilk_wm_max_level(dev);
-	/* LP0 watermark maximums depend on this pipe alone */
-	struct intel_wm_config config = {
-		.num_pipes_active = 1,
-		.sprites_enabled = params->spr.enabled,
-		.sprites_scaled = params->spr.scaled,
-	};
 	struct ilk_wm_maximums max;
 
 	pipe_wm->pipe_enabled = params->active;
@@ -2205,11 +2217,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
 
-	/* LP0 watermarks always use 1/2 DDB partitioning */
-	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
-
-	/* At least LP0 must be valid */
-	if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
+	if (!ilk_validate_pipe_wm(dev, pipe_wm))
 		return false;
 
 	ilk_compute_wm_reg_maximums(dev, 1, &max);
-- 
1.8.3.2

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

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

* [PATCH 13/24] drm/i915: Refactor ilk_update_wm
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (11 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 12/24] drm/i915: Refactor ilk_validate_pipe_wm() ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-23 21:31   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 14/24] drm/i915: Add dev_priv->wm.mutex ville.syrjala
                   ` (10 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Split ilk_update_wm() into two parts; one doing the progragramming
and the other the calculations.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e142095..3f5c1dc 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2696,27 +2696,14 @@ static bool ilk_disable_lp_wm(struct drm_device *dev)
 	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
 }
 
-static void ilk_update_wm(struct drm_crtc *crtc)
+static void ilk_program_watermarks(struct drm_device *dev)
 {
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
 	struct ilk_wm_maximums max;
-	struct ilk_pipe_wm_parameters params = {};
+	struct intel_wm_config config = {};
 	struct ilk_wm_values results = {};
 	enum intel_ddb_partitioning partitioning;
-	struct intel_pipe_wm pipe_wm = {};
-	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
-	struct intel_wm_config config = {};
-
-	ilk_compute_wm_parameters(crtc, &params);
-
-	intel_compute_pipe_wm(crtc, &params, &pipe_wm);
-
-	if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
-		return;
-
-	intel_crtc->wm.active = pipe_wm;
 
 	ilk_compute_wm_config(dev, &config);
 
@@ -2742,6 +2729,25 @@ static void ilk_update_wm(struct drm_crtc *crtc)
 	ilk_write_wm_values(dev_priv, &results);
 }
 
+static void ilk_update_wm(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct ilk_pipe_wm_parameters params = {};
+	struct intel_pipe_wm pipe_wm = {};
+
+	ilk_compute_wm_parameters(crtc, &params);
+
+	intel_compute_pipe_wm(crtc, &params, &pipe_wm);
+
+	if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
+		return;
+
+	intel_crtc->wm.active = pipe_wm;
+
+	ilk_program_watermarks(dev);
+}
+
 static void ilk_update_sprite_wm(struct drm_plane *plane,
 				     struct drm_crtc *crtc,
 				     uint32_t sprite_width, int pixel_size,
-- 
1.8.3.2

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

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

* [PATCH 14/24] drm/i915: Add dev_priv->wm.mutex
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (12 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 13/24] drm/i915: Refactor ilk_update_wm ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-04-23 21:47   ` Paulo Zanoni
  2014-03-07 16:32 ` [PATCH 15/24] drm/i915: Add vblank based delayed watermark update mechanism ville.syrjala
                   ` (9 subsequent siblings)
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Add a mutex to protect most of the watermark state. Will be useful when
we start to update watermarks asynchronously from plane updates, or
when we get finer grained locking for planes.

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

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 29da39f..0b19723 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1595,8 +1595,17 @@ typedef struct drm_i915_private {
 		/* cursor */
 		uint16_t cur_latency[5];
 
-		/* current hardware state */
+		/*
+		 * current hardware state
+		 * protected by dev_priv->wm.mutex
+		 */
 		struct ilk_wm_values hw;
+
+		/*
+		 * protects some dev_priv->wm and intel_crtc->wm
+		 * state as well as the actual hardware registers
+		 */
+		struct mutex mutex;
 	} wm;
 
 	struct i915_package_c8 pc8;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f022a78..8e32d69 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -384,7 +384,10 @@ struct intel_crtc {
 
 	/* per-pipe watermark state */
 	struct {
-		/* watermarks currently being used  */
+		/*
+		 * watermarks currently being used
+		 * protected by dev_priv->wm.mutex
+		 */
 		struct intel_pipe_wm active;
 	} wm;
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 3f5c1dc..d8adcb3 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2692,8 +2692,13 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
 static bool ilk_disable_lp_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	bool changed;
 
-	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
+	mutex_lock(&dev_priv->wm.mutex);
+	changed = _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
+	mutex_unlock(&dev_priv->wm.mutex);
+
+	return changed;
 }
 
 static void ilk_program_watermarks(struct drm_device *dev)
@@ -2733,6 +2738,7 @@ static void ilk_update_wm(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct ilk_pipe_wm_parameters params = {};
 	struct intel_pipe_wm pipe_wm = {};
 
@@ -2740,12 +2746,17 @@ static void ilk_update_wm(struct drm_crtc *crtc)
 
 	intel_compute_pipe_wm(crtc, &params, &pipe_wm);
 
+	mutex_lock(&dev_priv->wm.mutex);
+
 	if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
-		return;
+		goto unlock;
 
 	intel_crtc->wm.active = pipe_wm;
 
 	ilk_program_watermarks(dev);
+
+ unlock:
+	mutex_unlock(&dev_priv->wm.mutex);
 }
 
 static void ilk_update_sprite_wm(struct drm_plane *plane,
@@ -2817,10 +2828,14 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
 
+	mutex_lock(&dev_priv->wm.mutex);
+
 	_ilk_wm_get_hw_state(dev, &dev_priv->wm.hw);
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 		_ilk_pipe_wm_hw_to_sw(crtc);
+
+	mutex_unlock(&dev_priv->wm.mutex);
 }
 
 /**
@@ -5760,6 +5775,8 @@ void intel_init_pm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	mutex_init(&dev_priv->wm.mutex);
+
 	if (HAS_FBC(dev)) {
 		if (INTEL_INFO(dev)->gen >= 7) {
 			dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
-- 
1.8.3.2

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

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

* [PATCH 15/24] drm/i915: Add vblank based delayed watermark update mechanism
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (13 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 14/24] drm/i915: Add dev_priv->wm.mutex ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 16:32 ` [PATCH 16/24] drm/i915: Split watermark programming into pre and post steps ville.syrjala
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Add a mechanism by which you can queue up watermark update to happen
after the vblank counter has reached a certain value. The vblank
interrupt handler will schedule a work which will do the actual
watermark programming in process context.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |   2 +
 drivers/gpu/drm/i915/i915_irq.c      |  12 ++-
 drivers/gpu/drm/i915/intel_display.c |   1 +
 drivers/gpu/drm/i915/intel_drv.h     |  27 +++++++
 drivers/gpu/drm/i915/intel_pm.c      | 144 +++++++++++++++++++++++++++++++++++
 5 files changed, 183 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0b19723..f79f1b4 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1606,6 +1606,8 @@ typedef struct drm_i915_private {
 		 * state as well as the actual hardware registers
 		 */
 		struct mutex mutex;
+
+		struct work_struct work;
 	} wm;
 
 	struct i915_package_c8 pc8;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index bd79224..052da8c 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1909,8 +1909,10 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir)
 		DRM_ERROR("Poison interrupt\n");
 
 	for_each_pipe(pipe) {
-		if (de_iir & DE_PIPE_VBLANK(pipe))
+		if (de_iir & DE_PIPE_VBLANK(pipe)) {
 			intel_pipe_handle_vblank(dev, pipe);
+			ilk_update_pipe_wm(dev, pipe);
+		}
 
 		if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
 			if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false))
@@ -1959,8 +1961,10 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir)
 		intel_opregion_asle_intr(dev);
 
 	for_each_pipe(pipe) {
-		if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)))
+		if (de_iir & (DE_PIPE_VBLANK_IVB(pipe))) {
 			intel_pipe_handle_vblank(dev, pipe);
+			ilk_update_pipe_wm(dev, pipe);
+		}
 
 		/* plane/pipes map 1:1 on ilk+ */
 		if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) {
@@ -2102,8 +2106,10 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
 			continue;
 
 		pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe));
-		if (pipe_iir & GEN8_PIPE_VBLANK)
+		if (pipe_iir & GEN8_PIPE_VBLANK) {
 			intel_pipe_handle_vblank(dev, pipe);
+			ilk_update_pipe_wm(dev, pipe);
+		}
 
 		if (pipe_iir & GEN8_PIPE_FLIP_DONE) {
 			intel_prepare_page_flip(dev, pipe);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c028b5c..aa9acc5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10283,6 +10283,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 		intel_crtc->plane = !pipe;
 	}
 
+	spin_lock_init(&intel_crtc->wm.lock);
 	init_waitqueue_head(&intel_crtc->vbl_wait);
 
 	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 8e32d69..c9d2603 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -389,6 +389,32 @@ struct intel_crtc {
 		 * protected by dev_priv->wm.mutex
 		 */
 		struct intel_pipe_wm active;
+		/*
+		 * watermarks queued for next vblank
+		 * protected by dev_priv->wm.mutex
+		 */
+		struct intel_pipe_wm pending;
+
+		/*
+		 * the vblank count after which we can switch over to 'pending'
+		 * protected by intel_crtc->wm.lock
+		 */
+		u32 pending_vbl_count;
+		/*
+		 * indicates that 'pending' contains changed watermarks
+		 * protected by intel_crtc->wm.lock
+		 */
+		bool dirty;
+		/*
+		 * watermark update has a vblank reference?
+		 * protected by intel_crtc->wm.lock
+		 */
+		bool vblank;
+
+		/*
+		 * protects some intel_crtc->wm state
+		 */
+		spinlock_t lock;
 	} wm;
 
 	wait_queue_head_t vbl_wait;
@@ -904,6 +930,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
 void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
 void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
+void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe);
 
 
 /* intel_sdvo.c */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d8adcb3..de8fb65 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2701,6 +2701,65 @@ static bool ilk_disable_lp_wm(struct drm_device *dev)
 	return changed;
 }
 
+static bool vbl_count_after_eq(struct drm_device *dev, u32 a, u32 b)
+{
+	u32 mask = dev->max_vblank_count;
+
+	/* just the msb please */
+	mask &= ~(mask >> 1);
+
+	return !((a - b) & mask);
+}
+
+static bool ilk_pending_watermarks_ready(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	u32 vbl_count;
+
+	assert_spin_locked(&intel_crtc->wm.lock);
+
+	if (!intel_crtc->wm.dirty)
+		return false;
+
+	vbl_count = dev->driver->get_vblank_counter(dev, intel_crtc->pipe);
+
+	if (!vbl_count_after_eq(dev, vbl_count, intel_crtc->wm.pending_vbl_count))
+		return false;
+
+	if (intel_crtc->wm.vblank) {
+		drm_vblank_put(dev, intel_crtc->pipe);
+		intel_crtc->wm.vblank = false;
+	}
+
+	return true;
+}
+
+static bool ilk_refresh_pending_watermarks(struct drm_device *dev)
+{
+	struct intel_crtc *intel_crtc;
+	bool changed = false;
+
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
+		bool ready;
+
+		spin_lock_irq(&intel_crtc->wm.lock);
+
+		ready = ilk_pending_watermarks_ready(intel_crtc);
+		if (ready)
+			intel_crtc->wm.dirty = false;
+
+		spin_unlock_irq(&intel_crtc->wm.lock);
+
+		if (!ready)
+			continue;
+
+		intel_crtc->wm.active = intel_crtc->wm.pending;
+		changed = true;
+	}
+
+	return changed;
+}
+
 static void ilk_program_watermarks(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2759,6 +2818,87 @@ static void ilk_update_wm(struct drm_crtc *crtc)
 	mutex_unlock(&dev_priv->wm.mutex);
 }
 
+static void ilk_update_watermarks(struct drm_device *dev)
+{
+	bool changed;
+
+	changed = ilk_refresh_pending_watermarks(dev);
+
+	if (changed)
+		ilk_program_watermarks(dev);
+}
+
+static void ilk_setup_pending_watermarks(struct intel_crtc *intel_crtc,
+					 const struct intel_pipe_wm *pipe_wm,
+					 u32 vbl_count)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	enum pipe pipe = intel_crtc->pipe;
+
+	WARN(!intel_crtc->active, "pipe %c should be enabled\n",
+	     pipe_name(pipe));
+
+	/* do the watermarks actually need changing? */
+	if (!memcmp(&intel_crtc->wm.pending, pipe_wm, sizeof(*pipe_wm)))
+		return;
+
+	intel_crtc->wm.pending = *pipe_wm;
+
+	spin_lock_irq(&intel_crtc->wm.lock);
+	intel_crtc->wm.pending_vbl_count = (vbl_count + 1) & dev->max_vblank_count;
+	intel_crtc->wm.dirty = true;
+	spin_unlock_irq(&intel_crtc->wm.lock);
+
+	/* try to update immediately */
+	ilk_update_watermarks(dev);
+
+	spin_lock_irq(&intel_crtc->wm.lock);
+
+	/* did the immediate update succeed? */
+	if (!intel_crtc->wm.dirty)
+		goto unlock;
+
+	/*
+	 * We might already have a pending watermark update, in
+	 * which case we shouldn't grab another vblank reference.
+	 */
+	if (!intel_crtc->wm.vblank && drm_vblank_get(dev, pipe) == 0)
+		intel_crtc->wm.vblank = true;
+
+	WARN(!intel_crtc->wm.vblank,
+	     "unable to set up watermarks for pipe %c\n", pipe_name(pipe));
+
+ unlock:
+	spin_unlock_irq(&intel_crtc->wm.lock);
+}
+
+static void ilk_watermark_work(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(work, struct drm_i915_private, wm.work);
+
+	mutex_lock(&dev_priv->wm.mutex);
+
+	ilk_update_watermarks(dev_priv->dev);
+
+	mutex_unlock(&dev_priv->wm.mutex);
+}
+
+/* Called 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 intel_crtc *intel_crtc =
+		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+
+	spin_lock(&intel_crtc->wm.lock);
+
+	if (ilk_pending_watermarks_ready(intel_crtc))
+		schedule_work(&dev_priv->wm.work);
+
+	spin_unlock(&intel_crtc->wm.lock);
+}
+
 static void ilk_update_sprite_wm(struct drm_plane *plane,
 				     struct drm_crtc *crtc,
 				     uint32_t sprite_width, int pixel_size,
@@ -2821,6 +2961,9 @@ static void _ilk_pipe_wm_hw_to_sw(struct drm_crtc *crtc)
 		for (level = 0; level <= max_level; level++)
 			active->wm[level].enable = true;
 	}
+
+	/* no update pending */
+	intel_crtc->wm.pending = intel_crtc->wm.active;
 }
 
 void ilk_wm_get_hw_state(struct drm_device *dev)
@@ -5776,6 +5919,7 @@ void intel_init_pm(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	mutex_init(&dev_priv->wm.mutex);
+	INIT_WORK(&dev_priv->wm.work, ilk_watermark_work);
 
 	if (HAS_FBC(dev)) {
 		if (INTEL_INFO(dev)->gen >= 7) {
-- 
1.8.3.2

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

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

* [PATCH 16/24] drm/i915: Split watermark programming into pre and post steps
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (14 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 15/24] drm/i915: Add vblank based delayed watermark update mechanism ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 16:32 ` [PATCH 17/24] drm/i915: Actually perform the watermark update in two phases ville.syrjala
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

We need to perform watermark programming before and after changing the
plane configuration. Add two new vfuncs to do that. The pre phase is
supposed to switch over to the intermediate watermarks which are
computed so that they can deal with both the old and new plane
configurations. The post phase will arm the vblank based update
systems to switch over to the optimal target watermarks after the
plane configuration has for sure changed.

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

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f79f1b4..eb5f8f8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -408,6 +408,7 @@ struct intel_crtc_config;
 struct intel_crtc;
 struct intel_limit;
 struct dpll;
+struct intel_crtc_wm_config;
 
 struct drm_i915_display_funcs {
 	bool (*fbc_enabled)(struct drm_device *dev);
@@ -438,6 +439,10 @@ struct drm_i915_display_funcs {
 				 struct drm_crtc *crtc,
 				 uint32_t sprite_width, int pixel_size,
 				 bool enable, bool scaled);
+	void (*program_wm_pre)(struct drm_crtc *crtc,
+			       const struct intel_crtc_wm_config *config);
+	void (*program_wm_post)(struct drm_crtc *crtc,
+				const struct intel_crtc_wm_config *config);
 	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 c9d2603..2ec600d8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -338,6 +338,13 @@ struct intel_pipe_wm {
 	bool sprites_scaled;
 };
 
+struct intel_crtc_wm_config {
+	/* target watermarks for the pipe */
+	struct intel_pipe_wm target;
+	/* intermediate watermarks for pending/active->target transition */
+	struct intel_pipe_wm intm;
+};
+
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index de8fb65..468d6a5 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2899,6 +2899,20 @@ void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe)
 	spin_unlock(&intel_crtc->wm.lock);
 }
 
+static void ilk_wm_cancel(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+
+	assert_spin_locked(&intel_crtc->wm.lock);
+
+	intel_crtc->wm.dirty = false;
+
+	if (intel_crtc->wm.vblank) {
+		drm_vblank_put(dev, intel_crtc->pipe);
+		intel_crtc->wm.vblank = false;
+	}
+}
+
 static void ilk_update_sprite_wm(struct drm_plane *plane,
 				     struct drm_crtc *crtc,
 				     uint32_t sprite_width, int pixel_size,
@@ -3033,6 +3047,24 @@ void intel_update_sprite_watermarks(struct drm_plane *plane,
 						   pixel_size, enabled, scaled);
 }
 
+void intel_program_watermarks_pre(struct drm_crtc *crtc,
+				  const struct intel_crtc_wm_config *config)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+
+	if (dev_priv->display.program_wm_pre)
+		dev_priv->display.program_wm_pre(crtc, config);
+}
+
+void intel_program_watermarks_post(struct drm_crtc *crtc,
+				   const struct intel_crtc_wm_config *config)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+
+	if (dev_priv->display.program_wm_post)
+		dev_priv->display.program_wm_post(crtc, config);
+}
+
 static struct drm_i915_gem_object *
 intel_alloc_context_page(struct drm_device *dev)
 {
@@ -5913,6 +5945,62 @@ void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
 	pm_runtime_disable(device);
 }
 
+static void ilk_program_wm_pre(struct drm_crtc *crtc,
+			       const struct intel_crtc_wm_config *config)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	mutex_lock(&dev_priv->wm.mutex);
+
+	spin_lock_irq(&intel_crtc->wm.lock);
+	ilk_wm_cancel(intel_crtc);
+	spin_unlock_irq(&intel_crtc->wm.lock);
+
+	/* pending update (if any) got cancelled */
+	intel_crtc->wm.pending = intel_crtc->wm.active;
+
+	if (!memcmp(&intel_crtc->wm.active, &config->intm, sizeof(config->intm)))
+		goto unlock;
+
+	intel_crtc->wm.active = config->intm;
+
+	/* use the most up to date watermarks for other pipes */
+	ilk_refresh_pending_watermarks(dev);
+
+	/* switch over to the intermediate watermarks */
+	ilk_program_watermarks(dev);
+
+ unlock:
+	mutex_unlock(&dev_priv->wm.mutex);
+}
+
+static void ilk_program_wm_post(struct drm_crtc *crtc,
+				const struct intel_crtc_wm_config *config)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	u32 vbl_count;
+
+	/*
+	 * FIXME sample this inside the atomic section to avoid
+	 * needlessly long periods w/ sub-par watermarks
+	 */
+	vbl_count = dev->driver->get_vblank_counter(dev, intel_crtc->pipe);
+
+	mutex_lock(&dev_priv->wm.mutex);
+
+	/*
+	 * We can switch over to the target
+	 * watermarks after the next vblank.
+	 */
+	ilk_setup_pending_watermarks(intel_crtc, &config->target, vbl_count);
+
+	mutex_unlock(&dev_priv->wm.mutex);
+}
+
 /* Set up chip specific power management-related functions */
 void intel_init_pm(struct drm_device *dev)
 {
@@ -5960,6 +6048,8 @@ void intel_init_pm(struct drm_device *dev)
 		     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
 			dev_priv->display.update_wm = ilk_update_wm;
 			dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
+			dev_priv->display.program_wm_pre = ilk_program_wm_pre;
+			dev_priv->display.program_wm_post = ilk_program_wm_post;
 		} else {
 			DRM_DEBUG_KMS("Failed to read display plane latency. "
 				      "Disable CxSR\n");
-- 
1.8.3.2

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

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

* [PATCH 17/24] drm/i915: Actually perform the watermark update in two phases
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (15 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 16/24] drm/i915: Split watermark programming into pre and post steps ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 16:32 ` [PATCH 18/24] drm/i915: Wait for watermark updates to finish before disabling a pipe ville.syrjala
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Switch the code over to using the two phase watermark update. The steps
generally follow this pattern:

1. Calculate new plane parameters for changed planes
2. Calculate new target and intermediate watermarks
3. Check that both the target and intermediate watermarks are valid
4. Program the hardware with the intermediate watermarks
5. Program the plane registers
6. Arm the vblank watermark update machinery for the next vblank
7. Program the hardware with the target watermarks (after vblank)

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |  13 +-
 drivers/gpu/drm/i915/intel_display.c |  59 ++++++++-
 drivers/gpu/drm/i915/intel_drv.h     |  39 ++++--
 drivers/gpu/drm/i915/intel_pm.c      | 230 +++++++++++++++++++++++++++--------
 drivers/gpu/drm/i915/intel_sprite.c  | 118 ++++++++++++------
 5 files changed, 351 insertions(+), 108 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index eb5f8f8..b625601 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -409,6 +409,8 @@ struct intel_crtc;
 struct intel_limit;
 struct dpll;
 struct intel_crtc_wm_config;
+struct intel_plane_wm_parameters;
+struct intel_crtc_wm_config;
 
 struct drm_i915_display_funcs {
 	bool (*fbc_enabled)(struct drm_device *dev);
@@ -435,10 +437,13 @@ struct drm_i915_display_funcs {
 			  struct dpll *match_clock,
 			  struct dpll *best_clock);
 	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,
-				 bool enable, bool scaled);
+	int (*update_primary_wm)(struct drm_crtc *crtc,
+				 struct intel_crtc_wm_config *config);
+	int (*update_cursor_wm)(struct drm_crtc *crtc,
+				struct intel_crtc_wm_config *config);
+	int (*update_sprite_wm)(struct drm_plane *plane,
+				struct drm_crtc *crtc,
+				struct intel_crtc_wm_config *config);
 	void (*program_wm_pre)(struct drm_crtc *crtc,
 			       const struct intel_crtc_wm_config *config);
 	void (*program_wm_post)(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index aa9acc5..8d16ada7 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1871,6 +1871,18 @@ void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
 	POSTING_READ(reg);
 }
 
+static void update_pri_params(struct intel_crtc *intel_crtc,
+			      struct intel_plane_wm_parameters *params,
+			      bool primary_enabled)
+{
+	if (!intel_crtc->active || !primary_enabled)
+		return;
+
+	params->horiz_pixels = intel_crtc->config.pipe_src_w;
+	params->bytes_per_pixel = drm_format_plane_cpp(intel_crtc->base.fb->pixel_format, 0);
+	params->enabled = true;
+}
+
 /**
  * intel_enable_primary_plane - enable the primary plane on a given pipe
  * @dev_priv: i915 private structure
@@ -1882,8 +1894,11 @@ void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
 static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
 				       enum plane plane, enum pipe pipe)
 {
+	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 	struct intel_crtc *intel_crtc =
 		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+	struct intel_crtc_wm_config config = {};
+	int ret;
 	int reg;
 	u32 val;
 
@@ -1892,13 +1907,23 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
 
 	WARN(intel_crtc->primary_enabled, "Primary plane already enabled\n");
 
+	update_pri_params(intel_crtc, &config.pri, true);
+
+	ret = intel_update_primary_watermarks(crtc, &config);
+	WARN(ret, "primary watermarks invalid\n");
+
 	intel_crtc->primary_enabled = true;
 
 	reg = DSPCNTR(plane);
 	val = I915_READ(reg);
 
+	intel_crtc->pri_wm = config.pri;
+	intel_program_watermarks_pre(crtc, &config);
+
 	I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
 	intel_flush_primary_plane(dev_priv, plane);
+
+	intel_program_watermarks_post(crtc, &config);
 }
 
 /**
@@ -1912,20 +1937,33 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
 static void intel_disable_primary_plane(struct drm_i915_private *dev_priv,
 					enum plane plane, enum pipe pipe)
 {
+	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 	struct intel_crtc *intel_crtc =
 		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+	struct intel_crtc_wm_config config = {};
+	int ret;
 	int reg;
 	u32 val;
 
 	WARN(!intel_crtc->primary_enabled, "Primary plane already disabled\n");
 
+	update_pri_params(intel_crtc, &config.pri, false);
+
+	ret = intel_update_primary_watermarks(crtc, &config);
+	WARN(ret, "primary watermarks invalid\n");
+
 	intel_crtc->primary_enabled = false;
 
 	reg = DSPCNTR(plane);
 	val = I915_READ(reg);
 
+	intel_crtc->pri_wm = config.pri;
+	intel_program_watermarks_pre(crtc, &config);
+
 	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
 	intel_flush_primary_plane(dev_priv, plane);
+
+	intel_program_watermarks_post(crtc, &config);
 }
 
 static bool need_vtd_wa(struct drm_device *dev)
@@ -3622,7 +3660,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	 */
 	intel_crtc_load_lut(crtc);
 
-	intel_update_watermarks(crtc);
 	intel_enable_pipe(intel_crtc);
 
 	if (intel_crtc->config.has_pch_encoder)
@@ -3721,7 +3758,6 @@ 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(intel_crtc);
 
 	if (intel_crtc->config.has_pch_encoder)
@@ -3809,7 +3845,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	}
 
 	intel_crtc->active = false;
-	intel_update_watermarks(crtc);
 
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
@@ -3856,7 +3891,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	}
 
 	intel_crtc->active = false;
-	intel_update_watermarks(crtc);
 
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
@@ -7431,11 +7465,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 	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 intel_crtc_wm_config config = {};
 	int pipe = intel_crtc->pipe;
 	int x = intel_crtc->cursor_x;
 	int y = intel_crtc->cursor_y;
 	u32 base = 0, pos = 0;
 	bool visible;
+	int ret;
 
 	if (on)
 		base = intel_crtc->cursor_addr;
@@ -7468,6 +7504,19 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 	if (!visible && !intel_crtc->cursor_visible)
 		return;
 
+	if (visible) {
+		/* FIXME should we use the clipped width? */
+		config.cur.horiz_pixels = 64;
+		config.cur.bytes_per_pixel = 4;
+		config.cur.enabled = true;
+	}
+
+	ret = intel_update_cursor_watermarks(crtc, &config);
+	WARN(ret, "cursor watermarks invalid\n");
+
+	intel_crtc->cur_wm = config.cur;
+	intel_program_watermarks_pre(crtc, &config);
+
 	if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		I915_WRITE(CURPOS_IVB(pipe), pos);
 		ivb_update_cursor(crtc, base);
@@ -7478,6 +7527,8 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 		else
 			i9xx_update_cursor(crtc, base);
 	}
+
+	intel_program_watermarks_post(crtc, &config);
 }
 
 static int intel_crtc_cursor_set(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2ec600d8..c654a89 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -338,7 +338,15 @@ struct intel_pipe_wm {
 	bool sprites_scaled;
 };
 
+struct intel_plane_wm_parameters {
+	uint32_t horiz_pixels;
+	uint8_t bytes_per_pixel;
+	bool enabled;
+	bool scaled;
+};
+
 struct intel_crtc_wm_config {
+	struct intel_plane_wm_parameters pri, spr, cur;
 	/* target watermarks for the pipe */
 	struct intel_pipe_wm target;
 	/* intermediate watermarks for pending/active->target transition */
@@ -424,14 +432,10 @@ struct intel_crtc {
 		spinlock_t lock;
 	} wm;
 
-	wait_queue_head_t vbl_wait;
-};
+	struct intel_plane_wm_parameters pri_wm;
+	struct intel_plane_wm_parameters cur_wm;
 
-struct intel_plane_wm_parameters {
-	uint32_t horiz_pixels;
-	uint8_t bytes_per_pixel;
-	bool enabled;
-	bool scaled;
+	wait_queue_head_t vbl_wait;
 };
 
 struct intel_plane {
@@ -461,9 +465,11 @@ struct intel_plane {
 			     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);
+			     uint32_t src_w, uint32_t src_h,
+			     const struct intel_crtc_wm_config *config);
 	void (*disable_plane)(struct drm_plane *plane,
-			      struct drm_crtc *crtc);
+			      struct drm_crtc *crtc,
+			      const struct intel_crtc_wm_config *config);
 	int (*update_colorkey)(struct drm_plane *plane,
 			       struct drm_intel_sprite_colorkey *key);
 	void (*get_colorkey)(struct drm_plane *plane,
@@ -903,10 +909,17 @@ extern struct drm_display_mode *intel_find_panel_downclock(
 void intel_init_clock_gating(struct drm_device *dev);
 void intel_suspend_hw(struct drm_device *dev);
 void intel_update_watermarks(struct drm_crtc *crtc);
-void intel_update_sprite_watermarks(struct drm_plane *plane,
-				    struct drm_crtc *crtc,
-				    uint32_t sprite_width, int pixel_size,
-				    bool enabled, bool scaled);
+int intel_update_cursor_watermarks(struct drm_crtc *crtc,
+				   struct intel_crtc_wm_config *config);
+int intel_update_primary_watermarks(struct drm_crtc *crtc,
+				   struct intel_crtc_wm_config *config);
+int intel_update_sprite_watermarks(struct drm_plane *plane,
+				   struct drm_crtc *crtc,
+				   struct intel_crtc_wm_config *config);
+void intel_program_watermarks_pre(struct drm_crtc *crtc,
+				  const struct intel_crtc_wm_config *config);
+void intel_program_watermarks_post(struct drm_crtc *crtc,
+				   const struct intel_crtc_wm_config *config);
 void intel_init_pm(struct drm_device *dev);
 void intel_pm_setup(struct drm_device *dev);
 bool intel_fbc_enabled(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 468d6a5..38fbd9a 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2136,13 +2136,9 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
 	p->active = true;
 	p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_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.pipe_src_w;
-	p->cur.horiz_pixels = 64;
-	/* TODO: for now, assume primary and cursor planes are always enabled. */
-	p->pri.enabled = true;
-	p->cur.enabled = true;
+
+	p->pri = intel_crtc->pri_wm;
+	p->cur = intel_crtc->cur_wm;
 
 	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
 		struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -2242,6 +2238,35 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 }
 
 /*
+ * Merge two pipe watermark sets.
+ * Used for computing intermediate watermark levels
+ * for transitioning between two different configurations.
+ */
+static void ilk_wm_merge_intermediate(struct drm_device *dev,
+				      struct intel_pipe_wm *a,
+				      const struct intel_pipe_wm *b)
+{
+	int level, max_level = ilk_wm_max_level(dev);
+
+	a->pipe_enabled |= b->pipe_enabled;
+	a->sprites_enabled |= b->sprites_enabled;
+	a->sprites_scaled |= b->sprites_scaled;
+
+	/* Merge _all_ levels including 0 */
+	for (level = 0; level <= max_level; level++) {
+		struct intel_wm_level *a_wm = &a->wm[level];
+		const struct intel_wm_level *b_wm = &b->wm[level];
+
+		a_wm->enable &= b_wm->enable;
+
+		a_wm->pri_val = max(a_wm->pri_val, b_wm->pri_val);
+		a_wm->spr_val = max(a_wm->spr_val, b_wm->spr_val);
+		a_wm->cur_val = max(a_wm->cur_val, b_wm->cur_val);
+		a_wm->fbc_val = max(a_wm->fbc_val, b_wm->fbc_val);
+	}
+}
+
+/*
  * Merge the watermarks from all active pipes for a specific level.
  */
 static void ilk_merge_wm_level(struct drm_device *dev,
@@ -2793,31 +2818,6 @@ static void ilk_program_watermarks(struct drm_device *dev)
 	ilk_write_wm_values(dev_priv, &results);
 }
 
-static void ilk_update_wm(struct drm_crtc *crtc)
-{
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct ilk_pipe_wm_parameters params = {};
-	struct intel_pipe_wm pipe_wm = {};
-
-	ilk_compute_wm_parameters(crtc, &params);
-
-	intel_compute_pipe_wm(crtc, &params, &pipe_wm);
-
-	mutex_lock(&dev_priv->wm.mutex);
-
-	if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
-		goto unlock;
-
-	intel_crtc->wm.active = pipe_wm;
-
-	ilk_program_watermarks(dev);
-
- unlock:
-	mutex_unlock(&dev_priv->wm.mutex);
-}
-
 static void ilk_update_watermarks(struct drm_device *dev)
 {
 	bool changed;
@@ -2872,6 +2872,72 @@ static void ilk_setup_pending_watermarks(struct intel_crtc *intel_crtc,
 	spin_unlock_irq(&intel_crtc->wm.lock);
 }
 
+static int ilk_pipe_compute_watermarks(struct drm_crtc *crtc,
+				       struct intel_pipe_wm *target,
+				       struct intel_pipe_wm *intm)
+{
+	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 intel_pipe_wm intm_pending;
+	bool dirty;
+
+	/* are the target watermarks valid at all? */
+	if (!ilk_validate_pipe_wm(dev, target))
+		return -EINVAL;
+
+	/*
+	 * We need to come up with intermediate watermark levels
+	 * that will support both the old and new plane configuration
+	 * since we can't flip over to the final watermarks until
+	 * the plane configuration has been latched at some future vblank.
+	 *
+	 * Additionally if there's already an update pending, we can't
+	 * yet be sure which plane configuration will be active at the
+	 * time we apply the intermediate watermarks, so we must account
+	 * for both possibilities.
+	 */
+	mutex_lock(&dev_priv->wm.mutex);
+
+	intm_pending = intel_crtc->wm.pending;
+	*intm = intel_crtc->wm.active;
+
+	spin_lock_irq(&intel_crtc->wm.lock);
+	dirty = intel_crtc->wm.dirty;
+	spin_unlock_irq(&intel_crtc->wm.lock);
+
+	mutex_unlock(&dev_priv->wm.mutex);
+
+	/*
+	 * If the intermediate watermarks aren't valid, we must tell the user to
+	 * try something a bit different. There are two cases to be considered.
+	 * 1) there is no pending update:
+	 *    If the intermediate watermarks for transitioning from the currently
+	 *    active configuration to the new configuration aren't valid, the
+	 *    user must choose another configuration as there is no safe way to
+	 *    transition from the currently active config to the new config.
+	 * 2) there is a pending update:
+	 *    If the intermediate watermarks for transitioning from the ccurrently
+	 *    pending configuration to the new configuration are valid, we can
+	 *    simply tell the user to try again after a while.
+	 */
+	if (dirty) {
+		ilk_wm_merge_intermediate(dev, &intm_pending, target);
+		if (!ilk_validate_pipe_wm(dev, &intm_pending))
+			return -EINVAL;
+
+		ilk_wm_merge_intermediate(dev, intm, &intm_pending);
+		if (!ilk_validate_pipe_wm(dev, intm))
+			return -EAGAIN;
+	} else {
+		ilk_wm_merge_intermediate(dev, intm, target);
+		if (!ilk_validate_pipe_wm(dev, intm))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 static void ilk_watermark_work(struct work_struct *work)
 {
 	struct drm_i915_private *dev_priv =
@@ -2913,18 +2979,46 @@ static void ilk_wm_cancel(struct intel_crtc *intel_crtc)
 	}
 }
 
-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)
+static int ilk_update_primary_wm(struct drm_crtc *crtc,
+				 struct intel_crtc_wm_config *config)
 {
-	struct drm_device *dev = plane->dev;
-	struct intel_plane *intel_plane = to_intel_plane(plane);
+	struct ilk_pipe_wm_parameters params = {};
+
+	ilk_compute_wm_parameters(crtc, &params);
+
+	params.pri = config->pri;
 
-	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;
+	intel_compute_pipe_wm(crtc, &params, &config->target);
+
+	return ilk_pipe_compute_watermarks(crtc,
+					   &config->target,
+					   &config->intm);
+}
+
+static int ilk_update_cursor_wm(struct drm_crtc *crtc,
+				struct intel_crtc_wm_config *config)
+{
+	struct ilk_pipe_wm_parameters params = {};
+
+	ilk_compute_wm_parameters(crtc, &params);
+
+	params.cur = config->cur;
+
+	intel_compute_pipe_wm(crtc, &params, &config->target);
+
+	return ilk_pipe_compute_watermarks(crtc,
+					   &config->target,
+					   &config->intm);
+}
+
+static int ilk_update_sprite_wm(struct drm_plane *plane,
+				struct drm_crtc *crtc,
+				struct intel_crtc_wm_config *config)
+{
+	struct drm_device *dev = crtc->dev;
+	struct ilk_pipe_wm_parameters params = {};
+
+	ilk_compute_wm_parameters(crtc, &params);
 
 	/*
 	 * IVB workaround: must disable low power watermarks for at least
@@ -2933,10 +3027,17 @@ static void ilk_update_sprite_wm(struct drm_plane *plane,
 	 *
 	 * WaCxSRDisabledForSpriteScaling:ivb
 	 */
-	if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev))
-		intel_wait_for_vblank(dev, intel_plane->pipe);
+	if (IS_IVYBRIDGE(dev) && config->spr.scaled && ilk_disable_lp_wm(dev))
+		intel_wait_for_vblank(dev, to_intel_plane(plane)->pipe);
+
+	params.pri = config->pri;
+	params.spr = config->spr;
 
-	ilk_update_wm(crtc);
+	intel_compute_pipe_wm(crtc, &params, &config->target);
+
+	return ilk_pipe_compute_watermarks(crtc,
+					   &config->target,
+					   &config->intm);
 }
 
 static void _ilk_pipe_wm_hw_to_sw(struct drm_crtc *crtc)
@@ -3035,16 +3136,38 @@ void intel_update_watermarks(struct drm_crtc *crtc)
 		dev_priv->display.update_wm(crtc);
 }
 
-void intel_update_sprite_watermarks(struct drm_plane *plane,
-				    struct drm_crtc *crtc,
-				    uint32_t sprite_width, int pixel_size,
-				    bool enabled, bool scaled)
+int intel_update_primary_watermarks(struct drm_crtc *crtc,
+				    struct intel_crtc_wm_config *config)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+
+	if (dev_priv->display.update_primary_wm)
+		return dev_priv->display.update_primary_wm(crtc, config);
+
+	return 0;
+}
+
+int intel_update_cursor_watermarks(struct drm_crtc *crtc,
+				   struct intel_crtc_wm_config *config)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+
+	if (dev_priv->display.update_cursor_wm)
+		return dev_priv->display.update_cursor_wm(crtc, config);
+
+	return 0;
+}
+
+int intel_update_sprite_watermarks(struct drm_plane *plane,
+				   struct drm_crtc *crtc,
+				   struct intel_crtc_wm_config *config)
 {
-	struct drm_i915_private *dev_priv = plane->dev->dev_private;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 
 	if (dev_priv->display.update_sprite_wm)
-		dev_priv->display.update_sprite_wm(plane, crtc, sprite_width,
-						   pixel_size, enabled, scaled);
+		return dev_priv->display.update_sprite_wm(plane, crtc, config);
+
+	return 0;
 }
 
 void intel_program_watermarks_pre(struct drm_crtc *crtc,
@@ -6046,7 +6169,8 @@ void intel_init_pm(struct drm_device *dev)
 		     dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
 		    (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
 		     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
-			dev_priv->display.update_wm = ilk_update_wm;
+			dev_priv->display.update_primary_wm = ilk_update_primary_wm;
+			dev_priv->display.update_cursor_wm = ilk_update_cursor_wm;
 			dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
 			dev_priv->display.program_wm_pre = ilk_program_wm_pre;
 			dev_priv->display.program_wm_post = ilk_program_wm_post;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 213cd58..a9500ba 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -131,7 +131,7 @@ static void intel_update_primary_plane(struct intel_crtc *crtc)
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	int reg = DSPCNTR(crtc->plane);
 
-	if (crtc->primary_enabled)
+	if (crtc->pri_wm.enabled)
 		I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
 	else
 		I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
@@ -143,7 +143,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 		 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)
+		 uint32_t src_w, uint32_t src_h,
+		 const struct intel_crtc_wm_config *config)
 {
 	struct drm_device *dev = dplane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -218,9 +219,6 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 
 	sprctl |= SP_ENABLE;
 
-	intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
-				       src_w != crtc_w || src_h != crtc_h);
-
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
@@ -234,6 +232,10 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 							fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
+	intel_crtc->pri_wm = config->pri;
+	intel_plane->wm = config->spr;
+	intel_program_watermarks_pre(crtc, config);
+
 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 
 	intel_update_primary_plane(intel_crtc);
@@ -255,10 +257,13 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 
 	if (atomic_update)
 		intel_pipe_update_end(intel_crtc, start_vbl_count);
+
+	intel_program_watermarks_post(crtc, config);
 }
 
 static void
-vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
+vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
+		  const struct intel_crtc_wm_config *config)
 {
 	struct drm_device *dev = dplane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -269,6 +274,10 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 	u32 start_vbl_count;
 	bool atomic_update;
 
+	intel_crtc->pri_wm = config->pri;
+	intel_plane->wm = config->spr;
+	intel_program_watermarks_pre(crtc, config);
+
 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 
 	intel_update_primary_plane(intel_crtc);
@@ -283,7 +292,7 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 	if (atomic_update)
 		intel_pipe_update_end(intel_crtc, start_vbl_count);
 
-	intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
+	intel_program_watermarks_post(crtc, config);
 }
 
 static int
@@ -343,7 +352,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		 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)
+		 uint32_t src_w, uint32_t src_h,
+		 const struct intel_crtc_wm_config *config)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -406,9 +416,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
 
-	intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
-				       src_w != crtc_w || src_h != crtc_h);
-
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
@@ -424,6 +431,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 					       pixel_size, fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
+	intel_crtc->pri_wm = config->pri;
+	intel_plane->wm = config->spr;
+	intel_program_watermarks_pre(crtc, config);
+
 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 
 	intel_update_primary_plane(intel_crtc);
@@ -451,10 +462,13 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
 	if (atomic_update)
 		intel_pipe_update_end(intel_crtc, start_vbl_count);
+
+	intel_program_watermarks_post(crtc, config);
 }
 
 static void
-ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
+ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		  const struct intel_crtc_wm_config *config)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -464,6 +478,10 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 	u32 start_vbl_count;
 	bool atomic_update;
 
+	intel_crtc->pri_wm = config->pri;
+	intel_plane->wm = config->spr;
+	intel_program_watermarks_pre(crtc, config);
+
 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 
 	intel_update_primary_plane(intel_crtc);
@@ -480,13 +498,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 	if (atomic_update)
 		intel_pipe_update_end(intel_crtc, start_vbl_count);
 
-	/*
-	 * Avoid underruns when disabling the sprite.
-	 * FIXME remove once watermark updates are done properly.
-	 */
-	intel_wait_for_vblank(dev, pipe);
-
-	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
+	intel_program_watermarks_post(crtc, config);
 }
 
 static int
@@ -549,7 +561,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		 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)
+		 uint32_t src_w, uint32_t src_h,
+		 const struct intel_crtc_wm_config *config)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -606,9 +619,6 @@ 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(plane, crtc, src_w, pixel_size, true,
-				       src_w != crtc_w || src_h != crtc_h);
-
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
@@ -625,6 +635,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 					       pixel_size, fb->pitches[0]);
 	linear_offset -= dvssurf_offset;
 
+	intel_crtc->pri_wm = config->pri;
+	intel_plane->wm = config->spr;
+	intel_program_watermarks_pre(crtc, config);
+
 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 
 	intel_update_primary_plane(intel_crtc);
@@ -647,10 +661,13 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
 	if (atomic_update)
 		intel_pipe_update_end(intel_crtc, start_vbl_count);
+
+	intel_program_watermarks_post(crtc, config);
 }
 
 static void
-ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
+ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		  const struct intel_crtc_wm_config *config)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -660,6 +677,10 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 	u32 start_vbl_count;
 	bool atomic_update;
 
+	intel_crtc->pri_wm = config->pri;
+	intel_plane->wm = config->spr;
+	intel_program_watermarks_pre(crtc, config);
+
 	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 
 	intel_update_primary_plane(intel_crtc);
@@ -675,13 +696,7 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 	if (atomic_update)
 		intel_pipe_update_end(intel_crtc, start_vbl_count);
 
-	/*
-	 * Avoid underruns when disabling the sprite.
-	 * FIXME remove once watermark updates are done properly.
-	 */
-	intel_wait_for_vblank(dev, pipe);
-
-	intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
+	intel_program_watermarks_post(crtc, config);
 }
 
 static void
@@ -804,6 +819,18 @@ static bool colorkey_enabled(struct intel_plane *intel_plane)
 	return key.flags != I915_SET_COLORKEY_NONE;
 }
 
+static void update_pri_params(struct intel_crtc *intel_crtc,
+			      struct intel_plane_wm_parameters *params,
+			      bool primary_enabled)
+{
+	if (!intel_crtc->active || !primary_enabled)
+		return;
+
+	params->horiz_pixels = intel_crtc->config.pipe_src_w;
+	params->bytes_per_pixel = drm_format_plane_cpp(intel_crtc->base.fb->pixel_format, 0);
+	params->enabled = true;
+}
+
 static int
 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -855,6 +882,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		.src_w = src_w,
 		.src_h = src_h,
 	};
+	struct intel_crtc_wm_config config = {};
 
 	/* Don't modify another pipe's plane */
 	if (intel_plane->pipe != intel_crtc->pipe) {
@@ -992,6 +1020,19 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	primary_enabled = !drm_rect_equals(&dst, &clip) || colorkey_enabled(intel_plane);
 	WARN_ON(!primary_enabled && !visible && intel_crtc->active);
 
+	if (visible) {
+		config.spr.horiz_pixels = src_w;
+		config.spr.bytes_per_pixel = pixel_size;
+		config.spr.enabled = true;
+		config.spr.scaled = src_w != crtc_w || src_h != crtc_h;
+	}
+
+	update_pri_params(intel_crtc, &config.pri, primary_enabled);
+
+	ret = intel_update_sprite_watermarks(plane, crtc, &config);
+	if (ret)
+		return ret;
+
 	mutex_lock(&dev->struct_mutex);
 
 	/* Note that this will apply the VT-d workaround for scanouts,
@@ -1027,9 +1068,10 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		if (visible)
 			intel_plane->update_plane(plane, crtc, fb, obj,
 						  crtc_x, crtc_y, crtc_w, crtc_h,
-						  src_x, src_y, src_w, src_h);
+						  src_x, src_y, src_w, src_h,
+						  &config);
 		else
-			intel_plane->disable_plane(plane, crtc);
+			intel_plane->disable_plane(plane, crtc, &config);
 
 		if (!primary_was_enabled && primary_enabled)
 			intel_post_enable_primary(crtc);
@@ -1060,6 +1102,8 @@ intel_disable_plane(struct drm_plane *plane)
 	struct drm_device *dev = plane->dev;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	struct intel_crtc *intel_crtc;
+	struct intel_crtc_wm_config config = {};
+	int ret;
 
 	if (!plane->fb)
 		return 0;
@@ -1069,12 +1113,18 @@ intel_disable_plane(struct drm_plane *plane)
 
 	intel_crtc = to_intel_crtc(plane->crtc);
 
+	update_pri_params(intel_crtc, &config.pri, true);
+
+	ret = intel_update_sprite_watermarks(plane, plane->crtc, &config);
+	if (ret)
+		return ret;
+
 	if (intel_crtc->active) {
 		bool primary_was_enabled = intel_crtc->primary_enabled;
 
 		intel_crtc->primary_enabled = true;
 
-		intel_plane->disable_plane(plane, plane->crtc);
+		intel_plane->disable_plane(plane, plane->crtc, &config);
 
 		if (!primary_was_enabled && intel_crtc->primary_enabled)
 			intel_post_enable_primary(plane->crtc);
-- 
1.8.3.2

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

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

* [PATCH 18/24] drm/i915: Wait for watermark updates to finish before disabling a pipe
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (16 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 17/24] drm/i915: Actually perform the watermark update in two phases ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 16:32 ` [PATCH 19/24] drm/i915: Refactor get_other_active_crtc() ville.syrjala
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

After we've disabled the planes, it seems like a good idea wait for
the vblank driven watermark updates to finish before we turn off the
vblank interrupts and eventually the entire pipe.

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

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b625601..39bcf3b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1618,6 +1618,7 @@ typedef struct drm_i915_private {
 		struct mutex mutex;
 
 		struct work_struct work;
+		wait_queue_head_t wait;
 	} wm;
 
 	struct i915_package_c8 pc8;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8d16ada7..29f9d33 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3617,6 +3617,8 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
 	intel_disable_primary_plane(dev_priv, plane, pipe);
 	intel_wait_for_vblank(dev, pipe);
 
+	ilk_wm_synchronize(crtc);
+
 	drm_vblank_off(dev, pipe);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c654a89..4d8f646 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -951,6 +951,7 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
 void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
 void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe);
+void ilk_wm_synchronize(struct drm_crtc *crtc);
 
 
 /* intel_sdvo.c */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 38fbd9a..a76fa82 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2761,6 +2761,7 @@ static bool ilk_pending_watermarks_ready(struct intel_crtc *intel_crtc)
 
 static bool ilk_refresh_pending_watermarks(struct drm_device *dev)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc;
 	bool changed = false;
 
@@ -2782,6 +2783,9 @@ static bool ilk_refresh_pending_watermarks(struct drm_device *dev)
 		changed = true;
 	}
 
+	if (changed)
+		wake_up_all(&dev_priv->wm.wait);
+
 	return changed;
 }
 
@@ -2979,6 +2983,34 @@ static void ilk_wm_cancel(struct intel_crtc *intel_crtc)
 	}
 }
 
+void ilk_wm_synchronize(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	unsigned long timeout = msecs_to_jiffies(100);
+
+	wait_event_timeout(dev_priv->wm.wait, !intel_crtc->wm.dirty, timeout);
+
+	mutex_lock(&dev_priv->wm.mutex);
+
+	spin_lock_irq(&intel_crtc->wm.lock);
+
+	WARN(intel_crtc->wm.dirty, "pipe %c watermark updates failed to complete\n",
+	     pipe_name(pipe));
+
+	/* clean up if something is left behind */
+	ilk_wm_cancel(intel_crtc);
+
+	spin_unlock_irq(&intel_crtc->wm.lock);
+
+	/* pending update (if any) got cancelled */
+	intel_crtc->wm.pending = intel_crtc->wm.active;
+
+	mutex_unlock(&dev_priv->wm.mutex);
+}
+
 static int ilk_update_primary_wm(struct drm_crtc *crtc,
 				 struct intel_crtc_wm_config *config)
 {
@@ -6130,6 +6162,7 @@ void intel_init_pm(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	mutex_init(&dev_priv->wm.mutex);
+	init_waitqueue_head(&dev_priv->wm.wait);
 	INIT_WORK(&dev_priv->wm.work, ilk_watermark_work);
 
 	if (HAS_FBC(dev)) {
-- 
1.8.3.2

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

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

* [PATCH 19/24] drm/i915: Refactor get_other_active_crtc()
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (17 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 18/24] drm/i915: Wait for watermark updates to finish before disabling a pipe ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 16:32 ` [PATCH 20/24] drm/i915: Disable LP1+ watermarks while changing the number of active pipes ville.syrjala
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Pull the code to locate the other active crtc out from
haswell_mode_set_planes_workaround() into a separate function.
This will have another use later.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 29f9d33..ad36749 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3622,6 +3622,26 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
 	drm_vblank_off(dev, pipe);
 }
 
+static struct intel_crtc *get_other_active_crtc(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct intel_crtc *crtc_it, *other_active_crtc = NULL;
+
+	/* We want to get the other_active_crtc only if there's only 1 other
+	 * active crtc. */
+	list_for_each_entry(crtc_it, &dev->mode_config.crtc_list, base.head) {
+		if (!crtc_it->active || crtc_it == crtc)
+			continue;
+
+		if (other_active_crtc)
+			return NULL;
+
+		other_active_crtc = crtc_it;
+	}
+
+	return other_active_crtc;
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3701,19 +3721,8 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
 static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc)
 {
 	struct drm_device *dev = crtc->base.dev;
-	struct intel_crtc *crtc_it, *other_active_crtc = NULL;
-
-	/* We want to get the other_active_crtc only if there's only 1 other
-	 * active crtc. */
-	list_for_each_entry(crtc_it, &dev->mode_config.crtc_list, base.head) {
-		if (!crtc_it->active || crtc_it == crtc)
-			continue;
+	struct intel_crtc *other_active_crtc = get_other_active_crtc(crtc);
 
-		if (other_active_crtc)
-			return;
-
-		other_active_crtc = crtc_it;
-	}
 	if (!other_active_crtc)
 		return;
 
-- 
1.8.3.2

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

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

* [PATCH 20/24] drm/i915: Disable LP1+ watermarks while changing the number of active pipes
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (18 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 19/24] drm/i915: Refactor get_other_active_crtc() ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 16:32 ` [PATCH 21/24] drm/i915: Keep track of who disabled LP1+ watermarks ville.syrjala
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

When we switch between one active pipe and multiple active pipes, the
display FIFO gets repartitioned. Disable the LP1+ waterwarks while that
is happening to make sure we don't get any glitches on other active
pipes while doing a modeset on another other pipe.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ad36749..9c43751 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3642,6 +3642,27 @@ static struct intel_crtc *get_other_active_crtc(struct intel_crtc *crtc)
 	return other_active_crtc;
 }
 
+static void ilk_prepare_for_num_pipes_change(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct intel_crtc *other_active_crtc = get_other_active_crtc(crtc);
+
+	/*
+	 * If we change between one pipe and multiple pipes,
+	 * make sure the other active pipe is prepared
+	 * for having its FIFO resized. We do that by making
+	 * sure the pipe isn't using LP1+ watermarks when
+	 * the second pipe gets enabled or disabled.
+	 */
+	if (!other_active_crtc)
+		return;
+
+	ilk_wm_synchronize(&other_active_crtc->base);
+
+	if (ilk_disable_lp_wm(dev))
+		intel_wait_for_vblank(dev, other_active_crtc->pipe);
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3657,6 +3678,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	intel_crtc->active = true;
 
+	/* Make sure other pipes are prepared for FIFO resizing */
+	ilk_prepare_for_num_pipes_change(intel_crtc);
+
 	intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
 	intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
 
@@ -3745,6 +3769,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 
 	intel_crtc->active = true;
 
+	/* Make sure other pipes are prepared for FIFO resizing */
+	ilk_prepare_for_num_pipes_change(intel_crtc);
+
 	intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
 	if (intel_crtc->config.has_pch_encoder)
 		intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
@@ -3814,6 +3841,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 	ilk_crtc_disable_planes(crtc);
 
+	/* Make sure other pipes are prepared for FIFO resizing */
+	ilk_prepare_for_num_pipes_change(intel_crtc);
+
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->disable(encoder);
 
@@ -3857,6 +3887,12 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 	intel_crtc->active = false;
 
+	/*
+	 * Potentially let some other pipe use the
+	 * full FIFO, and re-enable LP1+ watermarks.
+	 */
+	ilk_wm_pipe_post_disable(crtc);
+
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
 	mutex_unlock(&dev->struct_mutex);
@@ -3876,6 +3912,9 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
 	ilk_crtc_disable_planes(crtc);
 
+	/* Make sure other pipes are prepared for FIFO resizing */
+	ilk_prepare_for_num_pipes_change(intel_crtc);
+
 	for_each_encoder_on_crtc(dev, crtc, encoder) {
 		intel_opregion_notify_encoder(encoder, false);
 		encoder->disable(encoder);
@@ -3903,6 +3942,12 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
 	intel_crtc->active = false;
 
+	/*
+	 * Potentially let some other pipe use the
+	 * full FIFO, and re-enable LP1+ watermarks.
+	 */
+	ilk_wm_pipe_post_disable(crtc);
+
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
 	mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4d8f646..94e90ad 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -952,6 +952,8 @@ void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
 void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe);
 void ilk_wm_synchronize(struct drm_crtc *crtc);
+void ilk_wm_pipe_post_disable(struct drm_crtc *crtc);
+bool ilk_disable_lp_wm(struct drm_device *dev);
 
 
 /* intel_sdvo.c */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index a76fa82..7230748 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2714,7 +2714,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
 	}
 }
 
-static bool ilk_disable_lp_wm(struct drm_device *dev)
+bool ilk_disable_lp_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	bool changed;
@@ -2822,16 +2822,17 @@ static void ilk_program_watermarks(struct drm_device *dev)
 	ilk_write_wm_values(dev_priv, &results);
 }
 
-static void ilk_update_watermarks(struct drm_device *dev)
+static void ilk_update_watermarks(struct drm_device *dev, bool force)
 {
 	bool changed;
 
 	changed = ilk_refresh_pending_watermarks(dev);
 
-	if (changed)
+	if (changed || force)
 		ilk_program_watermarks(dev);
 }
 
+/* Prepare the pipe to update the its watermarks on the next vblank */
 static void ilk_setup_pending_watermarks(struct intel_crtc *intel_crtc,
 					 const struct intel_pipe_wm *pipe_wm,
 					 u32 vbl_count)
@@ -2854,7 +2855,7 @@ static void ilk_setup_pending_watermarks(struct intel_crtc *intel_crtc,
 	spin_unlock_irq(&intel_crtc->wm.lock);
 
 	/* try to update immediately */
-	ilk_update_watermarks(dev);
+	ilk_update_watermarks(dev, false);
 
 	spin_lock_irq(&intel_crtc->wm.lock);
 
@@ -2949,7 +2950,7 @@ static void ilk_watermark_work(struct work_struct *work)
 
 	mutex_lock(&dev_priv->wm.mutex);
 
-	ilk_update_watermarks(dev_priv->dev);
+	ilk_update_watermarks(dev_priv->dev, false);
 
 	mutex_unlock(&dev_priv->wm.mutex);
 }
@@ -3011,6 +3012,43 @@ void ilk_wm_synchronize(struct drm_crtc *crtc)
 	mutex_unlock(&dev_priv->wm.mutex);
 }
 
+void ilk_wm_pipe_post_disable(struct drm_crtc *crtc)
+{
+	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 ilk_pipe_wm_parameters params = {};
+	struct intel_pipe_wm pipe_wm = {};
+
+	WARN(intel_crtc->active, "pipe %c should be disabled\n",
+	     pipe_name(intel_crtc->pipe));
+
+	ilk_compute_wm_parameters(crtc, &params);
+
+	intel_compute_pipe_wm(crtc, &params, &pipe_wm);
+
+	mutex_lock(&dev_priv->wm.mutex);
+
+	spin_lock_irq(&intel_crtc->wm.lock);
+
+	WARN(intel_crtc->wm.dirty, "pipe %c disabled with dirty watermarks\n",
+	     pipe_name(intel_crtc->pipe));
+
+	/* clean up if something is left behind */
+	ilk_wm_cancel(intel_crtc);
+
+	spin_unlock_irq(&intel_crtc->wm.lock);
+
+	intel_crtc->wm.active = pipe_wm;
+
+	/* pending update (if any) got cancelled */
+	intel_crtc->wm.pending = intel_crtc->wm.active;
+
+	ilk_update_watermarks(dev, true);
+
+	mutex_unlock(&dev_priv->wm.mutex);
+}
+
 static int ilk_update_primary_wm(struct drm_crtc *crtc,
 				 struct intel_crtc_wm_config *config)
 {
-- 
1.8.3.2

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

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

* [PATCH 21/24] drm/i915: Keep track of who disabled LP1+ watermarks
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (19 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 20/24] drm/i915: Disable LP1+ watermarks while changing the number of active pipes ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 16:32 ` [PATCH 22/24] drm/i915: Prefer the 5/6 DDB split when primary is disabled ville.syrjala
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

Currently ilk_disable_lp_wm() just disabled LP1+ watermarks directly.
However there's nothing preventing someone else from re-enabling them
immediately. To make sure sure LP1+ watermarks stay disabled for the
intended period, keep track which pipes require the LP1+ watermarks
to be disabled.

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

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 39bcf3b..5e69ca7 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1612,6 +1612,12 @@ typedef struct drm_i915_private {
 		struct ilk_wm_values hw;
 
 		/*
+		 * bitmask of pipes that have requested
+		 * LP1+ watermarks to be disabled.
+		 */
+		unsigned int lp_disabled;
+
+		/*
 		 * protects some dev_priv->wm and intel_crtc->wm
 		 * state as well as the actual hardware registers
 		 */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9c43751..6673de02 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3659,7 +3659,7 @@ static void ilk_prepare_for_num_pipes_change(struct intel_crtc *crtc)
 
 	ilk_wm_synchronize(&other_active_crtc->base);
 
-	if (ilk_disable_lp_wm(dev))
+	if (ilk_disable_lp_wm(&crtc->base))
 		intel_wait_for_vblank(dev, other_active_crtc->pipe);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 94e90ad..9c84d21 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -953,7 +953,7 @@ void ilk_wm_get_hw_state(struct drm_device *dev);
 void ilk_update_pipe_wm(struct drm_device *dev, enum pipe pipe);
 void ilk_wm_synchronize(struct drm_crtc *crtc);
 void ilk_wm_pipe_post_disable(struct drm_crtc *crtc);
-bool ilk_disable_lp_wm(struct drm_device *dev);
+bool ilk_disable_lp_wm(struct drm_crtc *crtc);
 
 
 /* intel_sdvo.c */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7230748..6e07686 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2377,6 +2377,7 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 				   enum intel_ddb_partitioning partitioning,
 				   struct ilk_wm_values *results)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc;
 	int level, wm_lp;
 
@@ -2400,7 +2401,7 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 			(r->pri_val << WM1_LP_SR_SHIFT) |
 			r->cur_val;
 
-		if (r->enable)
+		if (r->enable && !dev_priv->wm.lp_disabled)
 			results->wm_lp[wm_lp - 1] |= WM1_LP_SR_EN;
 
 		if (INTEL_INFO(dev)->gen >= 8)
@@ -2714,13 +2715,18 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
 	}
 }
 
-bool ilk_disable_lp_wm(struct drm_device *dev)
+bool ilk_disable_lp_wm(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	bool changed;
 
 	mutex_lock(&dev_priv->wm.mutex);
+
+	dev_priv->wm.lp_disabled |= 1 << to_intel_crtc(crtc)->pipe;
+
 	changed = _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
+
 	mutex_unlock(&dev_priv->wm.mutex);
 
 	return changed;
@@ -2838,15 +2844,20 @@ static void ilk_setup_pending_watermarks(struct intel_crtc *intel_crtc,
 					 u32 vbl_count)
 {
 	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum pipe pipe = intel_crtc->pipe;
 
 	WARN(!intel_crtc->active, "pipe %c should be enabled\n",
 	     pipe_name(pipe));
 
 	/* do the watermarks actually need changing? */
-	if (!memcmp(&intel_crtc->wm.pending, pipe_wm, sizeof(*pipe_wm)))
+	if (!(dev_priv->wm.lp_disabled & (1 << intel_crtc->pipe)) &&
+	    !memcmp(&intel_crtc->wm.pending, pipe_wm, sizeof(*pipe_wm)))
 		return;
 
+	/* allow LP1+ watermarks again */
+	dev_priv->wm.lp_disabled &= ~(1 << intel_crtc->pipe);
+
 	intel_crtc->wm.pending = *pipe_wm;
 
 	spin_lock_irq(&intel_crtc->wm.lock);
@@ -3044,6 +3055,9 @@ void ilk_wm_pipe_post_disable(struct drm_crtc *crtc)
 	/* pending update (if any) got cancelled */
 	intel_crtc->wm.pending = intel_crtc->wm.active;
 
+	/* allow LP1+ watermarks again */
+	dev_priv->wm.lp_disabled &= ~(1 << intel_crtc->pipe);
+
 	ilk_update_watermarks(dev, true);
 
 	mutex_unlock(&dev_priv->wm.mutex);
@@ -3097,7 +3111,7 @@ static int ilk_update_sprite_wm(struct drm_plane *plane,
 	 *
 	 * WaCxSRDisabledForSpriteScaling:ivb
 	 */
-	if (IS_IVYBRIDGE(dev) && config->spr.scaled && ilk_disable_lp_wm(dev))
+	if (IS_IVYBRIDGE(dev) && config->spr.scaled && ilk_disable_lp_wm(crtc))
 		intel_wait_for_vblank(dev, to_intel_plane(plane)->pipe);
 
 	params.pri = config->pri;
-- 
1.8.3.2

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

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

* [PATCH 22/24] drm/i915: Prefer the 5/6 DDB split when primary is disabled
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (20 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 21/24] drm/i915: Keep track of who disabled LP1+ watermarks ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 16:32 ` [PATCH 23/24] drm/i915: Add a workaround for sprite only <-> primary only switching ville.syrjala
  2014-03-07 16:32 ` [PATCH 24/24] drm/i915: Don't disable LP1+ watermarks for every frame when scaled ville.syrjala
  23 siblings, 0 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

When the primary plane is disabled, pick the 5/6 DDB split to give the
sprite as much FIFO space as possible.

The normal heuristic of just looking at the highest valid WM level won't
necessarily pick the optimal split since both splits might have the same
number of levels enabled.

Preferring the 5/6 split won't actually affect the watermarks here, but
it does give more FIFO space to the sprite leading to potentially longer
periods spent in LP1+ states since the FIFO takes longer to drain.

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

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9c84d21..848ed22 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -334,6 +334,7 @@ struct intel_pipe_wm {
 	uint32_t linetime;
 	bool fbc_wm_enabled;
 	bool pipe_enabled;
+	bool primary_enabled;
 	bool sprites_enabled;
 	bool sprites_scaled;
 };
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6e07686..ddf77d5 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1726,6 +1726,7 @@ struct ilk_wm_maximums {
 /* used in computing the new watermarks state */
 struct intel_wm_config {
 	unsigned int num_pipes_active;
+	bool primary_enabled;
 	bool sprites_enabled;
 	bool sprites_scaled;
 };
@@ -2162,6 +2163,7 @@ static void ilk_compute_wm_config(struct drm_device *dev,
 		if (!wm->pipe_enabled)
 			continue;
 
+		config->primary_enabled |= wm->primary_enabled;
 		config->sprites_enabled |= wm->sprites_enabled;
 		config->sprites_scaled |= wm->sprites_scaled;
 		config->num_pipes_active++;
@@ -2174,6 +2176,7 @@ static bool ilk_validate_pipe_wm(struct drm_device *dev,
 	/* LP0 watermark maximums depend on this pipe alone */
 	const struct intel_wm_config config = {
 		.num_pipes_active = 1,
+		.primary_enabled = pipe_wm->primary_enabled,
 		.sprites_enabled = pipe_wm->sprites_enabled,
 		.sprites_scaled = pipe_wm->sprites_scaled,
 	};
@@ -2197,6 +2200,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	struct ilk_wm_maximums max;
 
 	pipe_wm->pipe_enabled = params->active;
+	pipe_wm->primary_enabled = params->pri.enabled;
 	pipe_wm->sprites_enabled = params->spr.enabled;
 	pipe_wm->sprites_scaled = params->spr.scaled;
 
@@ -2249,6 +2253,7 @@ static void ilk_wm_merge_intermediate(struct drm_device *dev,
 	int level, max_level = ilk_wm_max_level(dev);
 
 	a->pipe_enabled |= b->pipe_enabled;
+	a->primary_enabled |= b->primary_enabled;
 	a->sprites_enabled |= b->sprites_enabled;
 	a->sprites_scaled |= b->sprites_scaled;
 
@@ -2440,11 +2445,21 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 	}
 }
 
-/* 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. */
+/*
+ * Find the result with the highest level enabled.
+ * When the max level for each result is the same, pick r2
+ * when the primary plane is disabled, otherwise prefer the
+ * result which has FBC WM enabled. All else being equal, pick
+ * r1.
+ *
+ * FIXME should ideally calculate the FIFO drain time for each
+ * plane, and determine which split has the chance to keep
+ * the memory asleep for longest.
+ */
 static struct intel_pipe_wm *ilk_find_best_result(struct drm_device *dev,
 						  struct intel_pipe_wm *r1,
-						  struct intel_pipe_wm *r2)
+						  struct intel_pipe_wm *r2,
+						  bool primary_enabled)
 {
 	int level, max_level = ilk_wm_max_level(dev);
 	int level1 = 0, level2 = 0;
@@ -2457,7 +2472,8 @@ static struct intel_pipe_wm *ilk_find_best_result(struct drm_device *dev,
 	}
 
 	if (level1 == level2) {
-		if (r2->fbc_wm_enabled && !r1->fbc_wm_enabled)
+		if (!primary_enabled ||
+		    (r2->fbc_wm_enabled && !r1->fbc_wm_enabled))
 			return r2;
 		else
 			return r1;
@@ -2815,7 +2831,8 @@ static void ilk_program_watermarks(struct drm_device *dev)
 		ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
 		ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
 
-		best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
+		best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6,
+						  config.primary_enabled);
 	} else {
 		best_lp_wm = &lp_wm_1_2;
 	}
-- 
1.8.3.2

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

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

* [PATCH 23/24] drm/i915: Add a workaround for sprite only <-> primary only switching
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (21 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 22/24] drm/i915: Prefer the 5/6 DDB split when primary is disabled ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  2014-03-07 21:32   ` Daniel Vetter
  2014-03-07 16:32 ` [PATCH 24/24] drm/i915: Don't disable LP1+ watermarks for every frame when scaled ville.syrjala
  23 siblings, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

ILK and IVB don't like switching between sprite only and primary only
configurations when LP1+ watermarks have been enabled in the recent
past. Like WaCxSRDisabledForSpriteScaling we can avoid the flash
by disabling LP1+ watermarks for one frame before the critical plane
reconfiguration.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ddf77d5..c011da5 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3127,9 +3127,18 @@ static int ilk_update_sprite_wm(struct drm_plane *plane,
 	 * when scaling is disabled.
 	 *
 	 * WaCxSRDisabledForSpriteScaling:ivb
+	 *
+	 * We also seem to need something similar when switching between
+	 * primary only and sprite only configurations. Otherwise the screen
+	 * flashes black. No underrun reported though.
 	 */
 	if (IS_IVYBRIDGE(dev) && config->spr.scaled && ilk_disable_lp_wm(crtc))
 		intel_wait_for_vblank(dev, to_intel_plane(plane)->pipe);
+	else if (config->pri.enabled != config->spr.enabled &&
+		 config->pri.enabled != params.pri.enabled &&
+		 config->spr.enabled != params.spr.enabled &&
+		 ilk_disable_lp_wm(crtc))
+		intel_wait_for_vblank(dev, to_intel_plane(plane)->pipe);
 
 	params.pri = config->pri;
 	params.spr = config->spr;
-- 
1.8.3.2

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

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

* [PATCH 24/24] drm/i915: Don't disable LP1+ watermarks for every frame when scaled
  2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
                   ` (22 preceding siblings ...)
  2014-03-07 16:32 ` [PATCH 23/24] drm/i915: Add a workaround for sprite only <-> primary only switching ville.syrjala
@ 2014-03-07 16:32 ` ville.syrjala
  23 siblings, 0 replies; 71+ messages in thread
From: ville.syrjala @ 2014-03-07 16:32 UTC (permalink / raw)
  To: intel-gfx

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

If we mark the LP1+ watermarks as disabled every time sprite scaling
is enabled, we end doing pointless work applying watermarks even though
nothing has changed. This is an artifact of the way
dev_priv->wm.lp_disabled affects the operation of
ilk_setup_pending_watermarks(). If the current pipe is included in
dev_priv->wm.lp_disabled, ilk_setup_pending_watermarks() will not check
if the watermarks actually changed since it will assume it will need to
disable LP1+ watermarks anyway.

A quick fix is to just check if sprite scaling was enabled for the
previous plane update, and if so, we know that LP1+ watermarks must
already be disabled. It might be better in long run to attempt to
change the way the LP1+ disable tracking integrates with the rest of
the watermark update mechanism. But this seems like a simple enough
solution for now.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c011da5..44546a5 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3132,7 +3132,8 @@ static int ilk_update_sprite_wm(struct drm_plane *plane,
 	 * primary only and sprite only configurations. Otherwise the screen
 	 * flashes black. No underrun reported though.
 	 */
-	if (IS_IVYBRIDGE(dev) && config->spr.scaled && ilk_disable_lp_wm(crtc))
+	if (IS_IVYBRIDGE(dev) && !params.spr.scaled &&
+	    config->spr.scaled && ilk_disable_lp_wm(crtc))
 		intel_wait_for_vblank(dev, to_intel_plane(plane)->pipe);
 	else if (config->pri.enabled != config->spr.enabled &&
 		 config->pri.enabled != params.pri.enabled &&
-- 
1.8.3.2

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

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

* Re: [PATCH 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-03-07 16:32 ` [PATCH 07/24] drm/i915: Remove useless checks from primary enable/disable ville.syrjala
@ 2014-03-07 21:29   ` Daniel Vetter
  2014-03-10 11:20     ` Ville Syrjälä
  2014-04-28 12:53     ` [PATCH v2 " ville.syrjala
  0 siblings, 2 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-03-07 21:29 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Fri, Mar 07, 2014 at 06:32:14PM +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We won't be calling intel_enable_primary_plane() or
> intel_disable_primary_plane() with the primary plane in the
> wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Convert them to asserts, or are we already covered in this regard?

/me has an uncanny love for self-checks ...

Cheers, Daniel

> ---
>  drivers/gpu/drm/i915/intel_display.c | 4 ----
>  1 file changed, 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7938556..2815351 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1896,8 +1896,6 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
>  
>  	reg = DSPCNTR(plane);
>  	val = I915_READ(reg);
> -	if (val & DISPLAY_PLANE_ENABLE)
> -		return;
>  
>  	I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
>  	intel_flush_primary_plane(dev_priv, plane);
> @@ -1926,8 +1924,6 @@ static void intel_disable_primary_plane(struct drm_i915_private *dev_priv,
>  
>  	reg = DSPCNTR(plane);
>  	val = I915_READ(reg);
> -	if ((val & DISPLAY_PLANE_ENABLE) == 0)
> -		return;
>  
>  	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
>  	intel_flush_primary_plane(dev_priv, plane);
> -- 
> 1.8.3.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 23/24] drm/i915: Add a workaround for sprite only <-> primary only switching
  2014-03-07 16:32 ` [PATCH 23/24] drm/i915: Add a workaround for sprite only <-> primary only switching ville.syrjala
@ 2014-03-07 21:32   ` Daniel Vetter
  0 siblings, 0 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-03-07 21:32 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Fri, Mar 07, 2014 at 06:32:30PM +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> ILK and IVB don't like switching between sprite only and primary only
> configurations when LP1+ watermarks have been enabled in the recent
> past. Like WaCxSRDisabledForSpriteScaling we can avoid the flash
> by disabling LP1+ watermarks for one frame before the critical plane
> reconfiguration.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index ddf77d5..c011da5 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3127,9 +3127,18 @@ static int ilk_update_sprite_wm(struct drm_plane *plane,
>  	 * when scaling is disabled.
>  	 *
>  	 * WaCxSRDisabledForSpriteScaling:ivb
> +	 *
> +	 * We also seem to need something similar when switching between
> +	 * primary only and sprite only configurations. Otherwise the screen
> +	 * flashes black. No underrun reported though.
>  	 */
>  	if (IS_IVYBRIDGE(dev) && config->spr.scaled && ilk_disable_lp_wm(crtc))
>  		intel_wait_for_vblank(dev, to_intel_plane(plane)->pipe);
> +	else if (config->pri.enabled != config->spr.enabled &&
> +		 config->pri.enabled != params.pri.enabled &&
> +		 config->spr.enabled != params.spr.enabled &&
> +		 ilk_disable_lp_wm(crtc))

I think it would help readability a bit to extract this monster condition
into a tiny helper with descriptive name ... just my bikeshed of the day.
-Daniel

> +		intel_wait_for_vblank(dev, to_intel_plane(plane)->pipe);
>  
>  	params.pri = config->pri;
>  	params.spr = config->spr;
> -- 
> 1.8.3.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-03-07 21:29   ` Daniel Vetter
@ 2014-03-10 11:20     ` Ville Syrjälä
  2014-03-10 11:57       ` Daniel Vetter
  2014-04-28 12:53     ` [PATCH v2 " ville.syrjala
  1 sibling, 1 reply; 71+ messages in thread
From: Ville Syrjälä @ 2014-03-10 11:20 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Fri, Mar 07, 2014 at 10:29:26PM +0100, Daniel Vetter wrote:
> On Fri, Mar 07, 2014 at 06:32:14PM +0200, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > We won't be calling intel_enable_primary_plane() or
> > intel_disable_primary_plane() with the primary plane in the
> > wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Convert them to asserts, or are we already covered in this regard?
> 
> /me has an uncanny love for self-checks ...

There's a WARN() for the crtc->primary_enabled flag in there, which
should cover things. Although we could add some sanity check that makes
sure the DISPLAY_PLANE_ENABLE bit matches crtc->primary_enabled.

> 
> Cheers, Daniel
> 
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 4 ----
> >  1 file changed, 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 7938556..2815351 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -1896,8 +1896,6 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
> >  
> >  	reg = DSPCNTR(plane);
> >  	val = I915_READ(reg);
> > -	if (val & DISPLAY_PLANE_ENABLE)
> > -		return;
> >  
> >  	I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
> >  	intel_flush_primary_plane(dev_priv, plane);
> > @@ -1926,8 +1924,6 @@ static void intel_disable_primary_plane(struct drm_i915_private *dev_priv,
> >  
> >  	reg = DSPCNTR(plane);
> >  	val = I915_READ(reg);
> > -	if ((val & DISPLAY_PLANE_ENABLE) == 0)
> > -		return;
> >  
> >  	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
> >  	intel_flush_primary_plane(dev_priv, plane);
> > -- 
> > 1.8.3.2
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-03-10 11:20     ` Ville Syrjälä
@ 2014-03-10 11:57       ` Daniel Vetter
  2014-04-07 20:04         ` Paulo Zanoni
  0 siblings, 1 reply; 71+ messages in thread
From: Daniel Vetter @ 2014-03-10 11:57 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Mon, Mar 10, 2014 at 12:20 PM, Ville Syrjälä
<ville.syrjala@linux.intel.com> wrote:
> On Fri, Mar 07, 2014 at 10:29:26PM +0100, Daniel Vetter wrote:
>> On Fri, Mar 07, 2014 at 06:32:14PM +0200, ville.syrjala@linux.intel.com wrote:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > We won't be calling intel_enable_primary_plane() or
>> > intel_disable_primary_plane() with the primary plane in the
>> > wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>
>> Convert them to asserts, or are we already covered in this regard?
>>
>> /me has an uncanny love for self-checks ...
>
> There's a WARN() for the crtc->primary_enabled flag in there, which
> should cover things. Although we could add some sanity check that makes
> sure the DISPLAY_PLANE_ENABLE bit matches crtc->primary_enabled.

Yeah, that's what I've thought of - we generally double-check hw state
before frobbing it.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 01/24] drm/i915: Don't read sprite LP2+ registers on ILK/SNB
  2014-03-07 16:32 ` [PATCH 01/24] drm/i915: Don't read sprite LP2+ registers on ILK/SNB ville.syrjala
@ 2014-04-04 21:35   ` Paulo Zanoni
  2014-04-05 15:19     ` Daniel Vetter
  0 siblings, 1 reply; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-04 21:35 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Sprite LP2+ registers don't exist on ILK/SNB so don't read them.
>
> 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, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 47b502b..26c79ed 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2664,8 +2664,10 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
>         hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
>
>         hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> -       hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> -       hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> +       if (INTEL_INFO(dev)->gen >= 7) {
> +               hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> +               hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> +       }
>
>         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
>                 hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [PATCH 01/24] drm/i915: Don't read sprite LP2+ registers on ILK/SNB
  2014-04-04 21:35   ` Paulo Zanoni
@ 2014-04-05 15:19     ` Daniel Vetter
  0 siblings, 0 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-04-05 15:19 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Fri, Apr 04, 2014 at 06:35:49PM -0300, Paulo Zanoni wrote:
> 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Sprite LP2+ registers don't exist on ILK/SNB so don't read them.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Queued for -next, thanks for the patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm
  2014-03-07 16:32 ` [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm ville.syrjala
@ 2014-04-07 14:14   ` Paulo Zanoni
  2014-04-29 11:18     ` Daniel Vetter
  0 siblings, 1 reply; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-07 14:14 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> intel_pipe_wm will be used to track the state in different stages
> of the watermark update process. For that we need to keep a bit
> more state in intel_pipe_wm.
>
> We also need to separate the multi-pipe intel_wm_config computation
> from ilk_compute_wm_parameters() as that one deals with the future
> state, and we need the intel_wm_config to match the current hardware
> state at the time we do the watermark merging for multiple pipes.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Needs minor rebase, but looks correct.

<insert complaint about the fact that the watermarks code is pretty
complex these days>

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

> ---
>  drivers/gpu/drm/i915/intel_drv.h |  3 ++
>  drivers/gpu/drm/i915/intel_pm.c  | 64 +++++++++++++++++++++++++++-------------
>  2 files changed, 46 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 8c9892d..f022a78 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -333,6 +333,9 @@ struct intel_pipe_wm {
>         struct intel_wm_level wm[5];
>         uint32_t linetime;
>         bool fbc_wm_enabled;
> +       bool pipe_enabled;
> +       bool sprites_enabled;
> +       bool sprites_scaled;
>  };
>
>  struct intel_crtc {
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 26c79ed..e0d1c8b 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2105,38 +2105,52 @@ static void intel_setup_wm_latency(struct drm_device *dev)
>  }
>
>  static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
> -                                     struct ilk_pipe_wm_parameters *p,
> -                                     struct intel_wm_config *config)
> +                                     struct ilk_pipe_wm_parameters *p)
>  {
>         struct drm_device *dev = crtc->dev;
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>         enum pipe pipe = intel_crtc->pipe;
>         struct drm_plane *plane;
>
> -       p->active = intel_crtc_active(crtc);
> -       if (p->active) {
> -               p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_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.pipe_src_w;
> -               p->cur.horiz_pixels = 64;
> -               /* TODO: for now, assume primary and cursor planes are always enabled. */
> -               p->pri.enabled = true;
> -               p->cur.enabled = true;
> -       }
> +       if (!intel_crtc_active(crtc))
> +               return;
>
> -       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> -               config->num_pipes_active += intel_crtc_active(crtc);
> +       p->active = true;
> +       p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_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.pipe_src_w;
> +       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);
>
> -               if (intel_plane->pipe == pipe)
> +               if (intel_plane->pipe == pipe) {
>                         p->spr = intel_plane->wm;
> +                       break;
> +               }
> +       }
> +}
>
> -               config->sprites_enabled |= intel_plane->wm.enabled;
> -               config->sprites_scaled |= intel_plane->wm.scaled;
> +static void ilk_compute_wm_config(struct drm_device *dev,
> +                                 struct intel_wm_config *config)
> +{
> +       struct intel_crtc *intel_crtc;
> +
> +       /* Compute the currently _active_ config */
> +       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->num_pipes_active++;
>         }
>  }
>
> @@ -2159,6 +2173,10 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         /* LP0 watermarks always use 1/2 DDB partitioning */
>         ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
>
> +       pipe_wm->pipe_enabled = params->active;
> +       pipe_wm->sprites_enabled = params->spr.enabled;
> +       pipe_wm->sprites_scaled = params->spr.scaled;
> +
>         /* ILK/SNB: LP2+ watermarks only w/o sprites */
>         if (INTEL_INFO(dev)->gen <= 6 && params->spr.enabled)
>                 max_level = 1;
> @@ -2548,7 +2566,7 @@ static void ilk_update_wm(struct drm_crtc *crtc)
>         struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
>         struct intel_wm_config config = {};
>
> -       ilk_compute_wm_parameters(crtc, &params, &config);
> +       ilk_compute_wm_parameters(crtc, &params);
>
>         intel_compute_pipe_wm(crtc, &params, &pipe_wm);
>
> @@ -2557,6 +2575,8 @@ static void ilk_update_wm(struct drm_crtc *crtc)
>
>         intel_crtc->wm.active = pipe_wm;
>
> +       ilk_compute_wm_config(dev, &config);
> +
>         ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
>         ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
>
> @@ -2623,7 +2643,9 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
>         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
>                 hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
>
> -       if (intel_crtc_active(crtc)) {
> +       active->pipe_enabled = intel_crtc_active(crtc);
> +
> +       if (active->pipe_enabled) {
>                 u32 tmp = hw->wm_pipe[pipe];
>
>                 /*
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [PATCH 03/24] drm/i915: Skip watermark merging for inactive pipes
  2014-03-07 16:32 ` [PATCH 03/24] drm/i915: Skip watermark merging for inactive pipes ville.syrjala
@ 2014-04-07 16:23   ` Paulo Zanoni
  0 siblings, 0 replies; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-07 16:23 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Even though the inactive pipes should have their watermarks set to all 0
> with enable=true, we can possibly shave off a few cycles by completely
> skipping the merge procedure for inactive pipes.
>
> 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 | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index e0d1c8b..e13937f 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2206,8 +2206,11 @@ static void ilk_merge_wm_level(struct drm_device *dev,
>         const struct intel_crtc *intel_crtc;
>
>         list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
> -               const struct intel_wm_level *wm =
> -                       &intel_crtc->wm.active.wm[level];
> +               const struct intel_pipe_wm *active = &intel_crtc->wm.active;
> +               const struct intel_wm_level *wm = &active->wm[level];
> +
> +               if (!active->pipe_enabled)
> +                       continue;
>
>                 if (!wm->enable)
>                         return;
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [PATCH 04/24] drm/i916: Refactor WM register maximums
  2014-03-07 16:32 ` [PATCH 04/24] drm/i916: Refactor WM register maximums ville.syrjala
@ 2014-04-07 16:34   ` Paulo Zanoni
  2014-04-09 12:22     ` Daniel Vetter
  0 siblings, 1 reply; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-07 16:34 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We will have another use for the maximum watermark values that the
> registers can hold. Pull those out into separate functions.
>
> 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 | 66 +++++++++++++++++++++++------------------
>  1 file changed, 37 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index e13937f..f061ef1 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1821,6 +1821,40 @@ static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
>                 return 512;
>  }
>
> +static unsigned int ilk_plane_wm_reg_max(const struct drm_device *dev,
> +                                        int level, bool is_sprite)
> +{
> +       if (INTEL_INFO(dev)->gen >= 8)
> +               /* BDW primary/sprite plane watermarks */
> +               return level == 0 ? 255 : 2047;
> +       else if (INTEL_INFO(dev)->gen >= 7)
> +               /* IVB/HSW primary/sprite plane watermarks */
> +               return level == 0 ? 127 : 1023;
> +       else if (!is_sprite)
> +               /* ILK/SNB primary plane watermarks */
> +               return level == 0 ? 127 : 511;
> +       else
> +               /* ILK/SNB sprite plane watermarks */
> +               return level == 0 ? 63 : 255;
> +}
> +
> +static unsigned int ilk_cursor_wm_reg_max(const struct drm_device *dev,
> +                                         int level)
> +{
> +       if (INTEL_INFO(dev)->gen >= 7)
> +               return level == 0 ? 63 : 255;
> +       else
> +               return level == 0 ? 31 : 63;
> +}
> +
> +static unsigned int ilk_fbc_wm_reg_max(const struct drm_device *dev)
> +{
> +       if (INTEL_INFO(dev)->gen >= 8)
> +               return 31;
> +       else
> +               return 15;
> +}
> +
>  /* Calculate the maximum primary/sprite plane watermark */
>  static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
>                                      int level,
> @@ -1829,7 +1863,6 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
>                                      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 && !config->sprites_enabled)
> @@ -1860,19 +1893,7 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
>         }
>
>         /* clamp to max that the registers can hold */
> -       if (INTEL_INFO(dev)->gen >= 8)
> -               max = level == 0 ? 255 : 2047;
> -       else 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);
> +       return min(fifo_size, ilk_plane_wm_reg_max(dev, level, is_sprite));
>  }
>
>  /* Calculate the maximum cursor plane watermark */
> @@ -1885,20 +1906,7 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
>                 return 64;
>
>         /* otherwise 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(const struct drm_device *dev)
> -{
> -       /* max that registers can hold */
> -       if (INTEL_INFO(dev)->gen >= 8)
> -               return 31;
> -       else
> -               return 15;
> +       return ilk_cursor_wm_reg_max(dev, level);
>  }
>
>  static void ilk_compute_wm_maximums(const struct drm_device *dev,
> @@ -1910,7 +1918,7 @@ static void ilk_compute_wm_maximums(const struct drm_device *dev,
>         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(dev);
> +       max->fbc = ilk_fbc_wm_reg_max(dev);
>  }
>
>  static bool ilk_validate_wm_level(int level,
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [PATCH 06/24] drm/i915: Disable/enable planes as the first/last thing during modeset on ILK+
  2014-03-07 16:32 ` [PATCH 06/24] drm/i915: Disable/enable planes as the first/last thing during modeset on ILK+ ville.syrjala
@ 2014-04-07 19:51   ` Paulo Zanoni
  2014-04-15 21:23     ` Daniel Vetter
  0 siblings, 1 reply; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-07 19:51 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We already do this for HSW, but doing it makes sense for everything else
> as well. Extend it for ILK/SNB/IVB since that's where the new watermark
> code is used.
>
> 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_display.c | 115 +++++++++++++++--------------------
>  1 file changed, 48 insertions(+), 67 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c309dd1..7938556 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3543,6 +3543,48 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
>                 hsw_enable_ips(intel_crtc);
>  }
>
> +static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       int pipe = intel_crtc->pipe;
> +       int plane = intel_crtc->plane;
> +
> +       intel_enable_primary_plane(dev_priv, plane, pipe);
> +       intel_enable_planes(crtc);
> +       intel_crtc_update_cursor(crtc, true);
> +
> +       hsw_enable_ips(intel_crtc);
> +
> +       mutex_lock(&dev->struct_mutex);
> +       intel_update_fbc(dev);
> +       mutex_unlock(&dev->struct_mutex);
> +
> +       drm_vblank_on(dev, pipe);
> +}
> +
> +static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       int pipe = intel_crtc->pipe;
> +       int plane = intel_crtc->plane;
> +
> +       intel_crtc_wait_for_pending_flips(crtc);
> +       drm_vblank_off(dev, pipe);
> +
> +       if (dev_priv->fbc.plane == plane)
> +               intel_disable_fbc(dev);
> +
> +       hsw_disable_ips(intel_crtc);
> +
> +       intel_crtc_update_cursor(crtc, false);
> +       intel_disable_planes(crtc);
> +       intel_disable_primary_plane(dev_priv, plane, pipe);
> +}
> +
>  static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  {
>         struct drm_device *dev = crtc->dev;
> @@ -3550,7 +3592,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>         struct intel_encoder *encoder;
>         int pipe = intel_crtc->pipe;
> -       int plane = intel_crtc->plane;
>
>         WARN_ON(!crtc->enabled);
>
> @@ -3586,23 +3627,18 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>
>         intel_update_watermarks(crtc);
>         intel_enable_pipe(intel_crtc);
> -       intel_enable_primary_plane(dev_priv, plane, pipe);
> -       intel_enable_planes(crtc);
> -       intel_crtc_update_cursor(crtc, true);
>
>         if (intel_crtc->config.has_pch_encoder)
>                 ironlake_pch_enable(crtc);
>
> -       mutex_lock(&dev->struct_mutex);
> -       intel_update_fbc(dev);
> -       mutex_unlock(&dev->struct_mutex);
> -
>         for_each_encoder_on_crtc(dev, crtc, encoder)
>                 encoder->enable(encoder);
>
>         if (HAS_PCH_CPT(dev))
>                 cpt_verify_modeset(dev, intel_crtc->pipe);
>
> +       ilk_crtc_enable_planes(crtc);
> +
>         /*
>          * There seems to be a race in PCH platform hw (at least on some
>          * outputs) where an enabled pipe still completes any pageflip right
> @@ -3612,8 +3648,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>          * happening.
>          */
>         intel_wait_for_vblank(dev, intel_crtc->pipe);
> -
> -       drm_vblank_on(dev, pipe);
>  }
>
>  /* IPS only exists on ULT machines and is tied to pipe A. */
> @@ -3622,49 +3656,6 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
>         return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
>  }
>
> -static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->dev;
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -       int pipe = intel_crtc->pipe;
> -       int plane = intel_crtc->plane;
> -
> -       intel_enable_primary_plane(dev_priv, plane, pipe);
> -       intel_enable_planes(crtc);
> -       intel_crtc_update_cursor(crtc, true);
> -
> -       hsw_enable_ips(intel_crtc);
> -
> -       mutex_lock(&dev->struct_mutex);
> -       intel_update_fbc(dev);
> -       mutex_unlock(&dev->struct_mutex);
> -
> -       drm_vblank_on(dev, pipe);
> -}
> -
> -static void haswell_crtc_disable_planes(struct drm_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->dev;
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -       int pipe = intel_crtc->pipe;
> -       int plane = intel_crtc->plane;
> -
> -       intel_crtc_wait_for_pending_flips(crtc);
> -       drm_vblank_off(dev, pipe);
> -
> -       /* FBC must be disabled before disabling the plane on HSW. */
> -       if (dev_priv->fbc.plane == plane)
> -               intel_disable_fbc(dev);
> -
> -       hsw_disable_ips(intel_crtc);
> -
> -       intel_crtc_update_cursor(crtc, false);
> -       intel_disable_planes(crtc);
> -       intel_disable_primary_plane(dev_priv, plane, pipe);
> -}
> -
>  /*
>   * This implements the workaround described in the "notes" section of the mode
>   * set sequence documentation. When going from no pipes or single pipe to
> @@ -3747,7 +3738,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>         /* If we change the relative order between pipe/planes enabling, we need
>          * to change the workaround. */
>         haswell_mode_set_planes_workaround(intel_crtc);
> -       haswell_crtc_enable_planes(crtc);
> +       ilk_crtc_enable_planes(crtc);
>  }
>
>  static void ironlake_pfit_disable(struct intel_crtc *crtc)
> @@ -3772,26 +3763,16 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>         struct intel_encoder *encoder;
>         int pipe = intel_crtc->pipe;
> -       int plane = intel_crtc->plane;
>         u32 reg, temp;
>
> -
>         if (!intel_crtc->active)
>                 return;
>
> +       ilk_crtc_disable_planes(crtc);
> +
>         for_each_encoder_on_crtc(dev, crtc, encoder)
>                 encoder->disable(encoder);
>
> -       intel_crtc_wait_for_pending_flips(crtc);
> -       drm_vblank_off(dev, pipe);
> -
> -       if (dev_priv->fbc.plane == plane)
> -               intel_disable_fbc(dev);
> -
> -       intel_crtc_update_cursor(crtc, false);
> -       intel_disable_planes(crtc);
> -       intel_disable_primary_plane(dev_priv, plane, pipe);
> -
>         if (intel_crtc->config.has_pch_encoder)
>                 intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
>
> @@ -3850,7 +3831,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>         if (!intel_crtc->active)
>                 return;
>
> -       haswell_crtc_disable_planes(crtc);
> +       ilk_crtc_disable_planes(crtc);
>
>         for_each_encoder_on_crtc(dev, crtc, encoder) {
>                 intel_opregion_notify_encoder(encoder, false);
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [PATCH 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-03-10 11:57       ` Daniel Vetter
@ 2014-04-07 20:04         ` Paulo Zanoni
  0 siblings, 0 replies; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-07 20:04 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

2014-03-10 8:57 GMT-03:00 Daniel Vetter <daniel@ffwll.ch>:
> On Mon, Mar 10, 2014 at 12:20 PM, Ville Syrjälä
> <ville.syrjala@linux.intel.com> wrote:
>> On Fri, Mar 07, 2014 at 10:29:26PM +0100, Daniel Vetter wrote:
>>> On Fri, Mar 07, 2014 at 06:32:14PM +0200, ville.syrjala@linux.intel.com wrote:
>>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> >
>>> > We won't be calling intel_enable_primary_plane() or
>>> > intel_disable_primary_plane() with the primary plane in the
>>> > wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.
>>> >
>>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> Convert them to asserts, or are we already covered in this regard?
>>>
>>> /me has an uncanny love for self-checks ...
>>
>> There's a WARN() for the crtc->primary_enabled flag in there, which
>> should cover things. Although we could add some sanity check that makes
>> sure the DISPLAY_PLANE_ENABLE bit matches crtc->primary_enabled.
>
> Yeah, that's what I've thought of - we generally double-check hw state
> before frobbing it.

I agree with Daniel here, let's convert it to a WARN.

> -Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [PATCH 08/24] drm/i915: Shuffle wait_for_vblank out of primary_enable/disable funcs
  2014-03-07 16:32 ` [PATCH 08/24] drm/i915: Shuffle wait_for_vblank out of primary_enable/disable funcs ville.syrjala
@ 2014-04-07 20:27   ` Paulo Zanoni
  2014-04-08 18:55     ` Ville Syrjälä
  0 siblings, 1 reply; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-07 20:27 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Rather than have a wait_for_vblank() in the primary plane enable/disable
> funcs, move the wait_for_vblank() to happen after enabling/disabling all
> planes.

Why exactly? What is improved? Are we solving a bug? What are the
risks? What's the problem with the current code? Did you check the
modeset sequence documentation of every single platform (since you
changed them all) to make sure this is safe?

Please update the commit message with the answers.

Also, we should probably update the first comment of hsw_enable_ips.
It seems things have changed since it was written.

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 2815351..4986887 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1899,7 +1899,6 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
>
>         I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
>         intel_flush_primary_plane(dev_priv, plane);
> -       intel_wait_for_vblank(dev_priv->dev, pipe);
>  }
>
>  /**
> @@ -1927,7 +1926,6 @@ static void intel_disable_primary_plane(struct drm_i915_private *dev_priv,
>
>         I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
>         intel_flush_primary_plane(dev_priv, plane);
> -       intel_wait_for_vblank(dev_priv->dev, pipe);
>  }
>
>  static bool need_vtd_wa(struct drm_device *dev)
> @@ -3550,6 +3548,7 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
>         intel_enable_primary_plane(dev_priv, plane, pipe);
>         intel_enable_planes(crtc);
>         intel_crtc_update_cursor(crtc, true);
> +       intel_wait_for_vblank(dev, pipe);
>
>         hsw_enable_ips(intel_crtc);
>
> @@ -3579,6 +3578,7 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
>         intel_crtc_update_cursor(crtc, false);
>         intel_disable_planes(crtc);
>         intel_disable_primary_plane(dev_priv, plane, pipe);
> +       intel_wait_for_vblank(dev, pipe);
>  }
>
>  static void ironlake_crtc_enable(struct drm_crtc *crtc)
> @@ -4211,6 +4211,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
>         intel_enable_primary_plane(dev_priv, plane, pipe);
>         intel_enable_planes(crtc);
>         intel_crtc_update_cursor(crtc, true);
> +       intel_wait_for_vblank(dev, pipe);
>
>         intel_update_fbc(dev);
>
> @@ -4258,6 +4259,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
>
>         /* Give the overlay scaler a chance to enable if it's on this pipe */
>         intel_crtc_dpms_overlay(intel_crtc, true);
> +       intel_wait_for_vblank(dev, pipe);
>
>         intel_update_fbc(dev);
>
> @@ -4308,6 +4310,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
>         intel_crtc_update_cursor(crtc, false);
>         intel_disable_planes(crtc);
>         intel_disable_primary_plane(dev_priv, plane, pipe);
> +       intel_wait_for_vblank(dev, pipe);
>
>         intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
>         intel_disable_pipe(dev_priv, pipe);
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [PATCH 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes
  2014-03-07 16:32 ` [PATCH 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes ville.syrjala
@ 2014-04-07 21:21   ` Paulo Zanoni
  2014-04-08 18:19     ` Ville Syrjälä
  2014-04-28 12:58     ` [PATCH v2 " ville.syrjala
  0 siblings, 2 replies; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-07 21:21 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We may have use for vblank interrupts during plane enabling/disabling, so
> don't call drm_vblank_off() until planes are off, and call
> drm_vblank_on() just before we start to enable the planes.

Just like the previous patch, this one also needs a more precise
description of the reasons and consequences. If this is going to be
needed in the future, it is probably a good idea to briefly describe
why and the use case you are planning. Because if, in the future, we
ever bisect a bug to this patch, and need to revert, we won't know if
the revert breaks some other feature.

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 4986887..c028b5c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3545,6 +3545,8 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
>         int pipe = intel_crtc->pipe;
>         int plane = intel_crtc->plane;
>
> +       drm_vblank_on(dev, pipe);
> +
>         intel_enable_primary_plane(dev_priv, plane, pipe);
>         intel_enable_planes(crtc);
>         intel_crtc_update_cursor(crtc, true);
> @@ -3555,8 +3557,6 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
>         mutex_lock(&dev->struct_mutex);
>         intel_update_fbc(dev);
>         mutex_unlock(&dev->struct_mutex);
> -
> -       drm_vblank_on(dev, pipe);
>  }
>
>  static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> @@ -3568,7 +3568,6 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
>         int plane = intel_crtc->plane;
>
>         intel_crtc_wait_for_pending_flips(crtc);
> -       drm_vblank_off(dev, pipe);
>
>         if (dev_priv->fbc.plane == plane)
>                 intel_disable_fbc(dev);
> @@ -3579,6 +3578,8 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
>         intel_disable_planes(crtc);
>         intel_disable_primary_plane(dev_priv, plane, pipe);
>         intel_wait_for_vblank(dev, pipe);
> +
> +       drm_vblank_off(dev, pipe);
>  }
>
>  static void ironlake_crtc_enable(struct drm_crtc *crtc)
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [PATCH 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes
  2014-04-07 21:21   ` Paulo Zanoni
@ 2014-04-08 18:19     ` Ville Syrjälä
  2014-04-28 12:58     ` [PATCH v2 " ville.syrjala
  1 sibling, 0 replies; 71+ messages in thread
From: Ville Syrjälä @ 2014-04-08 18:19 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Mon, Apr 07, 2014 at 06:21:08PM -0300, Paulo Zanoni wrote:
> 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > We may have use for vblank interrupts during plane enabling/disabling, so
> > don't call drm_vblank_off() until planes are off, and call
> > drm_vblank_on() just before we start to enable the planes.
> 
> Just like the previous patch, this one also needs a more precise
> description of the reasons and consequences. If this is going to be
> needed in the future, it is probably a good idea to briefly describe
> why and the use case you are planning. Because if, in the future, we
> ever bisect a bug to this patch, and need to revert, we won't know if
> the revert breaks some other feature.

Yeah I guess I should s/may/will/ and say that it's required for
watermark updates.

> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 7 ++++---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 4986887..c028b5c 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -3545,6 +3545,8 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
> >         int pipe = intel_crtc->pipe;
> >         int plane = intel_crtc->plane;
> >
> > +       drm_vblank_on(dev, pipe);
> > +
> >         intel_enable_primary_plane(dev_priv, plane, pipe);
> >         intel_enable_planes(crtc);
> >         intel_crtc_update_cursor(crtc, true);
> > @@ -3555,8 +3557,6 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
> >         mutex_lock(&dev->struct_mutex);
> >         intel_update_fbc(dev);
> >         mutex_unlock(&dev->struct_mutex);
> > -
> > -       drm_vblank_on(dev, pipe);
> >  }
> >
> >  static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> > @@ -3568,7 +3568,6 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> >         int plane = intel_crtc->plane;
> >
> >         intel_crtc_wait_for_pending_flips(crtc);
> > -       drm_vblank_off(dev, pipe);
> >
> >         if (dev_priv->fbc.plane == plane)
> >                 intel_disable_fbc(dev);
> > @@ -3579,6 +3578,8 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> >         intel_disable_planes(crtc);
> >         intel_disable_primary_plane(dev_priv, plane, pipe);
> >         intel_wait_for_vblank(dev, pipe);
> > +
> > +       drm_vblank_off(dev, pipe);
> >  }
> >
> >  static void ironlake_crtc_enable(struct drm_crtc *crtc)
> > --
> > 1.8.3.2
> >
> > _______________________________________________
> > 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] 71+ messages in thread

* Re: [PATCH 08/24] drm/i915: Shuffle wait_for_vblank out of primary_enable/disable funcs
  2014-04-07 20:27   ` Paulo Zanoni
@ 2014-04-08 18:55     ` Ville Syrjälä
  2014-04-29 14:00       ` Daniel Vetter
  0 siblings, 1 reply; 71+ messages in thread
From: Ville Syrjälä @ 2014-04-08 18:55 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Mon, Apr 07, 2014 at 05:27:41PM -0300, Paulo Zanoni wrote:
> 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Rather than have a wait_for_vblank() in the primary plane enable/disable
> > funcs, move the wait_for_vblank() to happen after enabling/disabling all
> > planes.
> 
> Why exactly? What is improved? Are we solving a bug? What are the
> risks? What's the problem with the current code? Did you check the
> modeset sequence documentation of every single platform (since you
> changed them all) to make sure this is safe?

Just another step towards getting all the planes enabled/disabled
atomically during a modeset. I should have probably yanked it from
this series since it shouldn't be strictly needed for the watermark
stuff. At least I can't think of a reason now. I guess I included
it here just to make things a bit more difficult for the new watermark
update mechanism.

In any case there's nothing magical about the primary plane, so we
shouldn't treat it as such. That's my excuse for this patch anyway.

> Please update the commit message with the answers.
> 
> Also, we should probably update the first comment of hsw_enable_ips.
> It seems things have changed since it was written.

I thought I had. Ah no, that's part of the mmio vs. cs flip race series.
Looks like the wait for vblank changes there will conflict with this
stuff anyway. I'll have to revisit that series, and hopefully get it
merged before this series so that we can ignore this patch entirely.

> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 2815351..4986887 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -1899,7 +1899,6 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
> >
> >         I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
> >         intel_flush_primary_plane(dev_priv, plane);
> > -       intel_wait_for_vblank(dev_priv->dev, pipe);
> >  }
> >
> >  /**
> > @@ -1927,7 +1926,6 @@ static void intel_disable_primary_plane(struct drm_i915_private *dev_priv,
> >
> >         I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
> >         intel_flush_primary_plane(dev_priv, plane);
> > -       intel_wait_for_vblank(dev_priv->dev, pipe);
> >  }
> >
> >  static bool need_vtd_wa(struct drm_device *dev)
> > @@ -3550,6 +3548,7 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
> >         intel_enable_primary_plane(dev_priv, plane, pipe);
> >         intel_enable_planes(crtc);
> >         intel_crtc_update_cursor(crtc, true);
> > +       intel_wait_for_vblank(dev, pipe);
> >
> >         hsw_enable_ips(intel_crtc);
> >
> > @@ -3579,6 +3578,7 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> >         intel_crtc_update_cursor(crtc, false);
> >         intel_disable_planes(crtc);
> >         intel_disable_primary_plane(dev_priv, plane, pipe);
> > +       intel_wait_for_vblank(dev, pipe);
> >  }
> >
> >  static void ironlake_crtc_enable(struct drm_crtc *crtc)
> > @@ -4211,6 +4211,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
> >         intel_enable_primary_plane(dev_priv, plane, pipe);
> >         intel_enable_planes(crtc);
> >         intel_crtc_update_cursor(crtc, true);
> > +       intel_wait_for_vblank(dev, pipe);
> >
> >         intel_update_fbc(dev);
> >
> > @@ -4258,6 +4259,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
> >
> >         /* Give the overlay scaler a chance to enable if it's on this pipe */
> >         intel_crtc_dpms_overlay(intel_crtc, true);
> > +       intel_wait_for_vblank(dev, pipe);
> >
> >         intel_update_fbc(dev);
> >
> > @@ -4308,6 +4310,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
> >         intel_crtc_update_cursor(crtc, false);
> >         intel_disable_planes(crtc);
> >         intel_disable_primary_plane(dev_priv, plane, pipe);
> > +       intel_wait_for_vblank(dev, pipe);
> >
> >         intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
> >         intel_disable_pipe(dev_priv, pipe);
> > --
> > 1.8.3.2
> >
> > _______________________________________________
> > 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] 71+ messages in thread

* Re: [PATCH 04/24] drm/i916: Refactor WM register maximums
  2014-04-07 16:34   ` Paulo Zanoni
@ 2014-04-09 12:22     ` Daniel Vetter
  0 siblings, 0 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-04-09 12:22 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Mon, Apr 07, 2014 at 01:34:04PM -0300, Paulo Zanoni wrote:
> 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > We will have another use for the maximum watermark values that the
> > registers can hold. Pull those out into separate functions.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Merged up to this one here to dinq, thanks.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 06/24] drm/i915: Disable/enable planes as the first/last thing during modeset on ILK+
  2014-04-07 19:51   ` Paulo Zanoni
@ 2014-04-15 21:23     ` Daniel Vetter
  0 siblings, 0 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-04-15 21:23 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Mon, Apr 07, 2014 at 04:51:21PM -0300, Paulo Zanoni wrote:
> 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > We already do this for HSW, but doing it makes sense for everything else
> > as well. Extend it for ILK/SNB/IVB since that's where the new watermark
> > code is used.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

I've frobbed the conflict and added the bz link for the vblank wait
warnings which this should fix. Queued for -next, thanks for the patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 05/24] drm/i915: Merge LP1+ watermarks in safer way
  2014-03-07 16:32 ` [PATCH 05/24] drm/i915: Merge LP1+ watermarks in safer way ville.syrjala
@ 2014-04-23 19:13   ` Paulo Zanoni
  2014-04-23 20:28     ` Ville Syrjälä
  2014-04-28 12:44     ` [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers ville.syrjala
  0 siblings, 2 replies; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-23 19:13 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> On ILK when we disable a particular watermark level, we must

Just to be clear: do you mean ILK or ILK+ here?

> maintain the actual watermark values for that level for some time
> (until the next vblank possibly). Otherwise we risk underruns.
>
> In order to achieve that result we must merge the LP1+ watermarks a
> bit differently since we must also merge levels that are to be
> disabled. We must also make sure we don't overflow the fields in the
> watermark registers in case the calculated watermarks come out too
> big to fit.
>
> As early as possbile we mark all computed watermark levels as
> disabled if they would exceed the register maximums. We make sure
> to leave the actual watermarks for such levels zeroed out. The during
> merging, we take the maxium values for every level, regardless if
> they're disabled or not. That may seem a bit pointless since at the
> moment all the watermark levels we merge should have their values
> zeroed if the level is already disabled. However soon we will be
> dealing with intermediate watermarks that, in addition to the new
> watermark values, also contain the previous watermark values, and so
> levels that are disabled may no longer be zeroed out.

I am having a hard time here. Watermarks code is extremely complex
these days, and my brain does not have enough memory to think about
all the implications and side effects of all the changes you did here.
I have stared a this patch for a long time, and I don't think I fully
understand it. I think you should probably try to break this change
into some smaller steps, with nice commit messages. Some stupid
questions to help me clarify:

As far as I understood, the biggest change of this patch is that when
some WM level is disabled, we won't write 0x0 to the WM register, but
we will write actual values, but with bit 31 set to zero, right? On
the first sentence of the commit message, you say we must maintain the
old values for that level for some time, but on the current code we
won't keep the old values: we will generate new values, and if a level
that was previously enabled needs to be disabled, there's no guarantee
that the new value we will generate will be exactly the same as the
old-value-but-with-bit-31-disabled. Why does that work? Since it
doesn't make sense to me, I probably understood something very wrong
here...

A little more below...

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 81 ++++++++++++++++++++++++++++++++---------
>  1 file changed, 64 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index f061ef1..ba4b23e 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1921,6 +1921,16 @@ static void ilk_compute_wm_maximums(const struct drm_device *dev,
>         max->fbc = ilk_fbc_wm_reg_max(dev);
>  }
>
> +static void ilk_compute_wm_reg_maximums(struct drm_device *dev,
> +                                       int level,
> +                                       struct ilk_wm_maximums *max)
> +{
> +       max->pri = ilk_plane_wm_reg_max(dev, level, false);
> +       max->spr = ilk_plane_wm_reg_max(dev, level, true);
> +       max->cur = ilk_cursor_wm_reg_max(dev, level);
> +       max->fbc = ilk_fbc_wm_reg_max(dev);
> +}
> +
>  static bool ilk_validate_wm_level(int level,
>                                   const struct ilk_wm_maximums *max,
>                                   struct intel_wm_level *result)
> @@ -2178,9 +2188,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         };
>         struct ilk_wm_maximums max;
>
> -       /* LP0 watermarks always use 1/2 DDB partitioning */
> -       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> -
>         pipe_wm->pipe_enabled = params->active;
>         pipe_wm->sprites_enabled = params->spr.enabled;
>         pipe_wm->sprites_scaled = params->spr.scaled;
> @@ -2193,15 +2200,37 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         if (params->spr.scaled)
>                 max_level = 0;
>
> -       for (level = 0; level <= max_level; level++)
> -               ilk_compute_wm_level(dev_priv, level, params,
> -                                    &pipe_wm->wm[level]);
> +       ilk_compute_wm_level(dev_priv, 0, params, &pipe_wm->wm[0]);
>
>         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
>                 pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
>
> +       /* LP0 watermarks always use 1/2 DDB partitioning */
> +       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> +
>         /* At least LP0 must be valid */
> -       return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
> +       if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
> +               return false;
> +

For example, this chunk introduces an early return to the function. I
really think this should be on its own patch, with a nice explanation
of why it is needed, and what are the consequences.


> +       ilk_compute_wm_reg_maximums(dev, 1, &max);
> +
> +       for (level = 1; level <= max_level; level++) {
> +               struct intel_wm_level wm = {};
> +
> +               ilk_compute_wm_level(dev_priv, level, params, &wm);
> +
> +               /*
> +                * Disable any watermark level that exceeds the
> +                * register maximums since such watermarks are
> +                * always invalid.
> +                */
> +               if (!ilk_validate_wm_level(level, &max, &wm))
> +                       break;
> +
> +               pipe_wm->wm[level] = wm;
> +       }
> +
> +       return true;
>  }
>
>  /*
> @@ -2213,6 +2242,8 @@ static void ilk_merge_wm_level(struct drm_device *dev,
>  {
>         const struct intel_crtc *intel_crtc;
>
> +       ret_wm->enable = true;
> +
>         list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
>                 const struct intel_pipe_wm *active = &intel_crtc->wm.active;
>                 const struct intel_wm_level *wm = &active->wm[level];
> @@ -2220,16 +2251,18 @@ static void ilk_merge_wm_level(struct drm_device *dev,
>                 if (!active->pipe_enabled)
>                         continue;
>
> -               if (!wm->enable)
> -                       return;
> +               /*
> +                * The watermark values may have been used in the past,
> +                * so we must maintain them in the registers for some
> +                * time even if the level is now disabled.
> +                */
> +               ret_wm->enable &= wm->enable;

I really prefer the "if (!wm->enable) ret_wm->enable = false;" form.
Even if it's less efficient, it's much easier to read and understand.
By the time you make sure what the "&=" statement is supposed to mean,
you already lost all the previous context you were following... And
there's also the possibility that GCC will do the best thing
automagically.


>
>                 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);
>         }
> -
> -       ret_wm->enable = true;
>  }
>
>  /*
> @@ -2241,6 +2274,7 @@ static void ilk_wm_merge(struct drm_device *dev,
>                          struct intel_pipe_wm *merged)
>  {
>         int level, max_level = ilk_wm_max_level(dev);
> +       int last_enabled_level = max_level;
>
>         /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
>         if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
> @@ -2256,15 +2290,19 @@ static void ilk_wm_merge(struct drm_device *dev,
>
>                 ilk_merge_wm_level(dev, level, wm);
>
> -               if (!ilk_validate_wm_level(level, max, wm))
> -                       break;
> +               if (level > last_enabled_level)
> +                       wm->enable = false;
> +               else if (!ilk_validate_wm_level(level, max, wm))
> +                       /* make sure all following levels get disabled */
> +                       last_enabled_level = level - 1;
>
>                 /*
>                  * The spec says it is preferred to disable
>                  * FBC WMs instead of disabling a WM level.
>                  */
>                 if (wm->fbc_val > max->fbc) {
> -                       merged->fbc_wm_enabled = false;
> +                       if (wm->enable)
> +                               merged->fbc_wm_enabled = false;
>                         wm->fbc_val = 0;
>                 }
>         }
> @@ -2319,14 +2357,19 @@ static void ilk_compute_wm_results(struct drm_device *dev,
>                 level = ilk_wm_lp_to_level(wm_lp, merged);
>
>                 r = &merged->wm[level];
> -               if (!r->enable)
> -                       break;
>
> -               results->wm_lp[wm_lp - 1] = WM3_LP_EN |
> +               /*
> +                * Maintain the watermark values even if the level is
> +                * disabled. Doing otherwise could cause underruns.
> +                */
> +               results->wm_lp[wm_lp - 1] =
>                         (ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT) |
>                         (r->pri_val << WM1_LP_SR_SHIFT) |
>                         r->cur_val;
>
> +               if (r->enable)
> +                       results->wm_lp[wm_lp - 1] |= WM1_LP_SR_EN;
> +
>                 if (INTEL_INFO(dev)->gen >= 8)
>                         results->wm_lp[wm_lp - 1] |=
>                                 r->fbc_val << WM1_LP_FBC_SHIFT_BDW;
> @@ -2334,6 +2377,10 @@ static void ilk_compute_wm_results(struct drm_device *dev,
>                         results->wm_lp[wm_lp - 1] |=
>                                 r->fbc_val << WM1_LP_FBC_SHIFT;
>
> +               /*
> +                * Always set WM1S_LP_EN when spr_val != 0, even if the
> +                * level is disabled. Doing otherwise could cause underruns.
> +                */

Shouldn't this comment be on top of the "if (r->enable)" chunk above?
Also, shouldn't this change be on its own separate patch with a
separate explanation?


General comments (not specific to this patch) based on my difficulty
to review the code:

The watermarks code got so complex that I really think we should add
documentation to most of the functions explaining "this function takes
X and Y structs as parameters, and writes the content of Z struct
based on it". Also, I really think we should document and rename a lot
of our structs, because I often can't think what they are supposed to
contain just based on their names, and how some one structure should
be different from the other. And some variable names are extemelly
short, they could certainly be renamed to something with more meaning.

Thanks,
Paulo

>                 if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) {
>                         WARN_ON(wm_lp != 1);
>                         results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



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

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

* Re: [PATCH 05/24] drm/i915: Merge LP1+ watermarks in safer way
  2014-04-23 19:13   ` Paulo Zanoni
@ 2014-04-23 20:28     ` Ville Syrjälä
  2014-04-28 12:44     ` [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers ville.syrjala
  1 sibling, 0 replies; 71+ messages in thread
From: Ville Syrjälä @ 2014-04-23 20:28 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Wed, Apr 23, 2014 at 04:13:25PM -0300, Paulo Zanoni wrote:
> 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > On ILK when we disable a particular watermark level, we must
> 
> Just to be clear: do you mean ILK or ILK+ here?

IIRC ILK was where I saw it really easily. IVB didn't seem quite as
sensitive to it.

> 
> > maintain the actual watermark values for that level for some time
> > (until the next vblank possibly). Otherwise we risk underruns.
> >
> > In order to achieve that result we must merge the LP1+ watermarks a
> > bit differently since we must also merge levels that are to be
> > disabled. We must also make sure we don't overflow the fields in the
> > watermark registers in case the calculated watermarks come out too
> > big to fit.
> >
> > As early as possbile we mark all computed watermark levels as
> > disabled if they would exceed the register maximums. We make sure
> > to leave the actual watermarks for such levels zeroed out. The during
> > merging, we take the maxium values for every level, regardless if
> > they're disabled or not. That may seem a bit pointless since at the
> > moment all the watermark levels we merge should have their values
> > zeroed if the level is already disabled. However soon we will be
> > dealing with intermediate watermarks that, in addition to the new
> > watermark values, also contain the previous watermark values, and so
> > levels that are disabled may no longer be zeroed out.
> 
> I am having a hard time here. Watermarks code is extremely complex
> these days, and my brain does not have enough memory to think about
> all the implications and side effects of all the changes you did here.
> I have stared a this patch for a long time, and I don't think I fully
> understand it. I think you should probably try to break this change
> into some smaller steps, with nice commit messages. Some stupid
> questions to help me clarify:
> 
> As far as I understood, the biggest change of this patch is that when
> some WM level is disabled, we won't write 0x0 to the WM register, but
> we will write actual values, but with bit 31 set to zero, right?

That's the idea.

> On
> the first sentence of the commit message, you say we must maintain the
> old values for that level for some time, but on the current code we
> won't keep the old values: we will generate new values, and if a level
> that was previously enabled needs to be disabled, there's no guarantee
> that the new value we will generate will be exactly the same as the
> old-value-but-with-bit-31-disabled. Why does that work?

It's not really hooked up yet. There's going to be another patch down
the line that calculates the "intermediate" watermarks for an individual
pipe as max(old,new). Those intermediate watermarks get applied to the
affected pipe, and then as we merge the LP1+ watermarks from all pipes
we must use similar logic. Ie. if one pipe has/had LP2=100 but
another pipe has/had LP2 disabled we must write 100 to the register
(w/o the enable bit set of course).

So this patch just modifies the LP1+ merge logic to make that happen.
Another patch will deal with the old vs. new situation.

> Since it
> doesn't make sense to me, I probably understood something very wrong
> here...
> 
> A little more below...
> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 81 ++++++++++++++++++++++++++++++++---------
> >  1 file changed, 64 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index f061ef1..ba4b23e 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -1921,6 +1921,16 @@ static void ilk_compute_wm_maximums(const struct drm_device *dev,
> >         max->fbc = ilk_fbc_wm_reg_max(dev);
> >  }
> >
> > +static void ilk_compute_wm_reg_maximums(struct drm_device *dev,
> > +                                       int level,
> > +                                       struct ilk_wm_maximums *max)
> > +{
> > +       max->pri = ilk_plane_wm_reg_max(dev, level, false);
> > +       max->spr = ilk_plane_wm_reg_max(dev, level, true);
> > +       max->cur = ilk_cursor_wm_reg_max(dev, level);
> > +       max->fbc = ilk_fbc_wm_reg_max(dev);
> > +}
> > +
> >  static bool ilk_validate_wm_level(int level,
> >                                   const struct ilk_wm_maximums *max,
> >                                   struct intel_wm_level *result)
> > @@ -2178,9 +2188,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
> >         };
> >         struct ilk_wm_maximums max;
> >
> > -       /* LP0 watermarks always use 1/2 DDB partitioning */
> > -       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> > -
> >         pipe_wm->pipe_enabled = params->active;
> >         pipe_wm->sprites_enabled = params->spr.enabled;
> >         pipe_wm->sprites_scaled = params->spr.scaled;
> > @@ -2193,15 +2200,37 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
> >         if (params->spr.scaled)
> >                 max_level = 0;
> >
> > -       for (level = 0; level <= max_level; level++)
> > -               ilk_compute_wm_level(dev_priv, level, params,
> > -                                    &pipe_wm->wm[level]);
> > +       ilk_compute_wm_level(dev_priv, 0, params, &pipe_wm->wm[0]);
> >
> >         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> >                 pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
> >
> > +       /* LP0 watermarks always use 1/2 DDB partitioning */
> > +       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> > +
> >         /* At least LP0 must be valid */
> > -       return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
> > +       if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
> > +               return false;
> > +
> 
> For example, this chunk introduces an early return to the function. I
> really think this should be on its own patch, with a nice explanation
> of why it is needed, and what are the consequences.

Hmm. I suppose this patch could be split in two so that this part would
come first. I already had tons of pain trying to split these up, but I
guess I missed some opportunities.

This change was here to make sure we never have any watermark values
stored in pipe_wm that would exceed the maximum allowed in the registers.
That would totally mess up the merging of the watermarks since
wm->enabled==false will no longer prevent us from using those values
in the max() calculation, so we'd end up overflowing the bits in
the register.

> 
> > +       ilk_compute_wm_reg_maximums(dev, 1, &max);
> > +
> > +       for (level = 1; level <= max_level; level++) {
> > +               struct intel_wm_level wm = {};
> > +
> > +               ilk_compute_wm_level(dev_priv, level, params, &wm);
> > +
> > +               /*
> > +                * Disable any watermark level that exceeds the
> > +                * register maximums since such watermarks are
> > +                * always invalid.
> > +                */
> > +               if (!ilk_validate_wm_level(level, &max, &wm))
> > +                       break;
> > +
> > +               pipe_wm->wm[level] = wm;
> > +       }
> > +
> > +       return true;
> >  }
> >
> >  /*
> > @@ -2213,6 +2242,8 @@ static void ilk_merge_wm_level(struct drm_device *dev,
> >  {
> >         const struct intel_crtc *intel_crtc;
> >
> > +       ret_wm->enable = true;
> > +
> >         list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
> >                 const struct intel_pipe_wm *active = &intel_crtc->wm.active;
> >                 const struct intel_wm_level *wm = &active->wm[level];
> > @@ -2220,16 +2251,18 @@ static void ilk_merge_wm_level(struct drm_device *dev,
> >                 if (!active->pipe_enabled)
> >                         continue;
> >
> > -               if (!wm->enable)
> > -                       return;
> > +               /*
> > +                * The watermark values may have been used in the past,
> > +                * so we must maintain them in the registers for some
> > +                * time even if the level is now disabled.
> > +                */
> > +               ret_wm->enable &= wm->enable;
> 
> I really prefer the "if (!wm->enable) ret_wm->enable = false;" form.
> Even if it's less efficient, it's much easier to read and understand.
> By the time you make sure what the "&=" statement is supposed to mean,
> you already lost all the previous context you were following... And
> there's also the possibility that GCC will do the best thing
> automagically.

So you're an optimist :)

> 
> 
> >
> >                 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);
> >         }
> > -
> > -       ret_wm->enable = true;
> >  }
> >
> >  /*
> > @@ -2241,6 +2274,7 @@ static void ilk_wm_merge(struct drm_device *dev,
> >                          struct intel_pipe_wm *merged)
> >  {
> >         int level, max_level = ilk_wm_max_level(dev);
> > +       int last_enabled_level = max_level;
> >
> >         /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
> >         if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
> > @@ -2256,15 +2290,19 @@ static void ilk_wm_merge(struct drm_device *dev,
> >
> >                 ilk_merge_wm_level(dev, level, wm);
> >
> > -               if (!ilk_validate_wm_level(level, max, wm))
> > -                       break;
> > +               if (level > last_enabled_level)
> > +                       wm->enable = false;
> > +               else if (!ilk_validate_wm_level(level, max, wm))
> > +                       /* make sure all following levels get disabled */
> > +                       last_enabled_level = level - 1;
> >
> >                 /*
> >                  * The spec says it is preferred to disable
> >                  * FBC WMs instead of disabling a WM level.
> >                  */
> >                 if (wm->fbc_val > max->fbc) {
> > -                       merged->fbc_wm_enabled = false;
> > +                       if (wm->enable)
> > +                               merged->fbc_wm_enabled = false;
> >                         wm->fbc_val = 0;
> >                 }
> >         }
> > @@ -2319,14 +2357,19 @@ static void ilk_compute_wm_results(struct drm_device *dev,
> >                 level = ilk_wm_lp_to_level(wm_lp, merged);
> >
> >                 r = &merged->wm[level];
> > -               if (!r->enable)
> > -                       break;
> >
> > -               results->wm_lp[wm_lp - 1] = WM3_LP_EN |
> > +               /*
> > +                * Maintain the watermark values even if the level is
> > +                * disabled. Doing otherwise could cause underruns.
> > +                */
> > +               results->wm_lp[wm_lp - 1] =
> >                         (ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT) |
> >                         (r->pri_val << WM1_LP_SR_SHIFT) |
> >                         r->cur_val;
> >
> > +               if (r->enable)
> > +                       results->wm_lp[wm_lp - 1] |= WM1_LP_SR_EN;
> > +
> >                 if (INTEL_INFO(dev)->gen >= 8)
> >                         results->wm_lp[wm_lp - 1] |=
> >                                 r->fbc_val << WM1_LP_FBC_SHIFT_BDW;
> > @@ -2334,6 +2377,10 @@ static void ilk_compute_wm_results(struct drm_device *dev,
> >                         results->wm_lp[wm_lp - 1] |=
> >                                 r->fbc_val << WM1_LP_FBC_SHIFT;
> >
> > +               /*
> > +                * Always set WM1S_LP_EN when spr_val != 0, even if the
> > +                * level is disabled. Doing otherwise could cause underruns.
> > +                */
> 
> Shouldn't this comment be on top of the "if (r->enable)" chunk above?

No, this is about the sprite WM enable bit. That seems to behave like
the actual watermark values in the register. Ie. if we had the sprite
enabled with LP1 watermarks previously but now we're about to disable
the LP1 watermark, we must leave the sprite WM enable bit set just
like we leave the watermark value set in the register.

> Also, shouldn't this change be on its own separate patch with a
> separate explanation?

I have sprinkled similar comments to other parts of intel_pm.c. This
hunk could maybe have been part of those patches except it doesn't
really make sense until the break statement was eliminated from the
loop. I guess it could be split up into a patch of its own. But that
seems a bit pointless.

> 
> 
> General comments (not specific to this patch) based on my difficulty
> to review the code:
> 
> The watermarks code got so complex that I really think we should add
> documentation to most of the functions explaining "this function takes
> X and Y structs as parameters, and writes the content of Z struct
> based on it". Also, I really think we should document and rename a lot
> of our structs, because I often can't think what they are supposed to
> contain just based on their names, and how some one structure should
> be different from the other. And some variable names are extemelly
> short, they could certainly be renamed to something with more meaning.

Yeah the code does have too many structs for various things, and there's
some duplication between them in some cases. And I still keep adding more
to make the intermediate watermarks stuff work. My plan is to shovel some
of that into some plane config thing eventually. That should cut it down
a bit and eliminate some duplicated information. Though in some cases we
need to the duplication since we need to track the watermarks in time.

I have no objections to documentation. I guess I need to find the time
to write it...

> 
> Thanks,
> Paulo
> 
> >                 if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) {
> >                         WARN_ON(wm_lp != 1);
> >                         results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
> > --
> > 1.8.3.2
> >
> > _______________________________________________
> > 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] 71+ messages in thread

* Re: [PATCH 11/24] drm/i915: Check hw vs. sw watermark state after programming
  2014-03-07 16:32 ` [PATCH 11/24] drm/i915: Check hw vs. sw watermark state after programming ville.syrjala
@ 2014-04-23 21:16   ` Paulo Zanoni
  2014-04-29 12:54     ` Ville Syrjälä
  0 siblings, 1 reply; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-23 21:16 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Make sure we programmed the watermarks correctly, by reading out the
> hardware state again after programming and comparing it with the
> state we supposedly programmed into hardware. Dump the watermark
> registers after a mismatch, very much like we for the pipe config.
> The only difference is that we don't dump the entire watermark
> software tracking state since that's spread around a bit.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

This one could also have been split into more than one patch: first
you extract the functions, then later you add the new callers.

My only comment is: do we really want to check HW/SW state right after
we write the register values? Shouldn't  this be done at some other
time, like the end of the modeset sequence?

Still, the patch seems correct, so: Reviewed-by: Paulo Zanoni
<paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 117 ++++++++++++++++++++++++++++------------
>  1 file changed, 83 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index ba4b23e..e519578a1 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2524,15 +2524,84 @@ static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
>         return changed;
>  }
>
> +static void _ilk_pipe_wm_get_hw_state(struct drm_device *dev,
> +                                     enum pipe pipe,
> +                                     struct ilk_wm_values *hw)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       static const unsigned int wm0_pipe_reg[] = {
> +               [PIPE_A] = WM0_PIPEA_ILK,
> +               [PIPE_B] = WM0_PIPEB_ILK,
> +               [PIPE_C] = WM0_PIPEC_IVB,
> +       };
> +
> +       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
> +
> +       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> +               hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
> +}
> +
> +static void _ilk_wm_get_hw_state(struct drm_device *dev,
> +                                struct ilk_wm_values *hw)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       enum pipe pipe;
> +
> +       for_each_pipe(pipe)
> +               _ilk_pipe_wm_get_hw_state(dev, pipe, hw);
> +
> +       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
> +       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
> +       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
> +
> +       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> +       if (INTEL_INFO(dev)->gen >= 7) {
> +               hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> +               hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> +       }
> +
> +       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> +               hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> +                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> +       else if (IS_IVYBRIDGE(dev))
> +               hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
> +                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> +
> +       hw->enable_fbc_wm =
> +               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> +}
> +
> +static void ilk_dump_wm_values(const struct ilk_wm_values *hw,
> +                              const char *context)
> +{
> +       DRM_DEBUG_KMS("%s watermark values\n", context);
> +       DRM_DEBUG_KMS("WM_PIPE_A = 0x%08x\n",  hw->wm_pipe[PIPE_A]);
> +       DRM_DEBUG_KMS("WM_PIPE_B = 0x%08x\n",  hw->wm_pipe[PIPE_B]);
> +       DRM_DEBUG_KMS("WM_PIPE_C = 0x%08x\n",  hw->wm_pipe[PIPE_C]);
> +       DRM_DEBUG_KMS("WM_LP_1 = 0x%08x\n", hw->wm_lp[0]);
> +       DRM_DEBUG_KMS("WM_LP_2 = 0x%08x\n", hw->wm_lp[1]);
> +       DRM_DEBUG_KMS("WM_LP_3 = 0x%08x\n", hw->wm_lp[2]);
> +       DRM_DEBUG_KMS("WM_LP_SPR_1 = 0x%08x\n", hw->wm_lp_spr[0]);
> +       DRM_DEBUG_KMS("WM_LP_SPR_2 = 0x%08x\n", hw->wm_lp_spr[1]);
> +       DRM_DEBUG_KMS("WM_LP_SPR_3 = 0x%08x\n", hw->wm_lp_spr[2]);
> +       DRM_DEBUG_KMS("WM_LINETIME_A = 0x%08x\n", hw->wm_linetime[PIPE_A]);
> +       DRM_DEBUG_KMS("WM_LINETIME_B = 0x%08x\n", hw->wm_linetime[PIPE_B]);
> +       DRM_DEBUG_KMS("WM_LINETIME_C = 0x%08x\n", hw->wm_linetime[PIPE_C]);
> +       DRM_DEBUG_KMS("enable FBC watermark = %d\n", hw->enable_fbc_wm);
> +       DRM_DEBUG_KMS("DDB partitioning = %s\n",
> +                     hw->partitioning == INTEL_DDB_PART_1_2 ? "1/2" : "5/6");
> +}
> +
>  /*
>   * 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 ilk_write_wm_values(struct drm_i915_private *dev_priv,
> -                               struct ilk_wm_values *results)
> +                               const struct ilk_wm_values *results)
>  {
>         struct drm_device *dev = dev_priv->dev;
>         struct ilk_wm_values *previous = &dev_priv->wm.hw;
> +       struct ilk_wm_values hw = {};
>         unsigned int dirty;
>         uint32_t val;
>
> @@ -2602,6 +2671,14 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
>                 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
>
>         dev_priv->wm.hw = *results;
> +
> +       _ilk_wm_get_hw_state(dev, &hw);
> +
> +       if (memcmp(results, &hw, sizeof(hw))) {
> +               WARN(1, "watermark state doesn't match!\n");
> +               ilk_dump_wm_values(&hw, "[hw state]");
> +               ilk_dump_wm_values(results, "[sw state]");
> +       }
>  }
>
>  static bool ilk_disable_lp_wm(struct drm_device *dev)
> @@ -2683,23 +2760,14 @@ static void ilk_update_sprite_wm(struct drm_plane *plane,
>         ilk_update_wm(crtc);
>  }
>
> -static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
> +static void _ilk_pipe_wm_hw_to_sw(struct drm_crtc *crtc)
>  {
>         struct drm_device *dev = crtc->dev;
>         struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct ilk_wm_values *hw = &dev_priv->wm.hw;
> +       const struct ilk_wm_values *hw = &dev_priv->wm.hw;
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>         struct intel_pipe_wm *active = &intel_crtc->wm.active;
>         enum pipe pipe = intel_crtc->pipe;
> -       static const unsigned int wm0_pipe_reg[] = {
> -               [PIPE_A] = WM0_PIPEA_ILK,
> -               [PIPE_B] = WM0_PIPEB_ILK,
> -               [PIPE_C] = WM0_PIPEC_IVB,
> -       };
> -
> -       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
> -       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> -               hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
>
>         active->pipe_enabled = intel_crtc_active(crtc);
>
> @@ -2733,31 +2801,12 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
>  void ilk_wm_get_hw_state(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct ilk_wm_values *hw = &dev_priv->wm.hw;
>         struct drm_crtc *crtc;
>
> -       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> -               ilk_pipe_wm_get_hw_state(crtc);
> -
> -       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
> -       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
> -       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
> -
> -       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> -       if (INTEL_INFO(dev)->gen >= 7) {
> -               hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> -               hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> -       }
> +       _ilk_wm_get_hw_state(dev, &dev_priv->wm.hw);
>
> -       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> -               hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> -                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> -       else if (IS_IVYBRIDGE(dev))
> -               hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
> -                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> -
> -       hw->enable_fbc_wm =
> -               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> +               _ilk_pipe_wm_hw_to_sw(crtc);
>  }
>
>  /**
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



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

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

* Re: [PATCH 12/24] drm/i915: Refactor ilk_validate_pipe_wm()
  2014-03-07 16:32 ` [PATCH 12/24] drm/i915: Refactor ilk_validate_pipe_wm() ville.syrjala
@ 2014-04-23 21:23   ` Paulo Zanoni
  0 siblings, 0 replies; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-23 21:23 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Pull the LP0 validate out from intel_compute_pipe_wm() into a separate
> function. We will have further need for such a function to validate
> both the final watermarks and the intermediate watermarks we will be
> using while the plane(s) transition between different configurations.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 30 +++++++++++++++++++-----------
>  1 file changed, 19 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index e519578a1..e142095 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2172,6 +2172,24 @@ static void ilk_compute_wm_config(struct drm_device *dev,
>         }
>  }
>
> +static bool ilk_validate_pipe_wm(struct drm_device *dev,
> +                                struct intel_pipe_wm *pipe_wm)
> +{
> +       /* LP0 watermark maximums depend on this pipe alone */
> +       const struct intel_wm_config config = {
> +               .num_pipes_active = 1,
> +               .sprites_enabled = pipe_wm->sprites_enabled,
> +               .sprites_scaled = pipe_wm->sprites_scaled,
> +       };
> +       struct ilk_wm_maximums max;
> +
> +       /* LP0 watermarks always use 1/2 DDB partitioning */
> +       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> +
> +       /* At least LP0 must be valid */

I would remove this comment, and keep the original one on the caller.
IMHO it makes more sense there.

With or without that change:
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> +       return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
> +}
> +
>  /* Compute new watermarks for the pipe */
>  static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>                                   const struct ilk_pipe_wm_parameters *params,
> @@ -2180,12 +2198,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         struct drm_device *dev = crtc->dev;
>         const struct drm_i915_private *dev_priv = dev->dev_private;
>         int level, max_level = ilk_wm_max_level(dev);
> -       /* LP0 watermark maximums depend on this pipe alone */
> -       struct intel_wm_config config = {
> -               .num_pipes_active = 1,
> -               .sprites_enabled = params->spr.enabled,
> -               .sprites_scaled = params->spr.scaled,
> -       };
>         struct ilk_wm_maximums max;
>
>         pipe_wm->pipe_enabled = params->active;
> @@ -2205,11 +2217,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
>                 pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
>
> -       /* LP0 watermarks always use 1/2 DDB partitioning */
> -       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> -
> -       /* At least LP0 must be valid */
> -       if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
> +       if (!ilk_validate_pipe_wm(dev, pipe_wm))
>                 return false;
>
>         ilk_compute_wm_reg_maximums(dev, 1, &max);
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



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

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

* Re: [PATCH 13/24] drm/i915: Refactor ilk_update_wm
  2014-03-07 16:32 ` [PATCH 13/24] drm/i915: Refactor ilk_update_wm ville.syrjala
@ 2014-04-23 21:31   ` Paulo Zanoni
  0 siblings, 0 replies; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-23 21:31 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Split ilk_update_wm() into two parts; one doing the progragramming
> and the other the calculations.

There are 1.060 google results for the word "progragramming", which
you used above :)
Sounds like one of those words that have some special funny meaning.

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

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 38 ++++++++++++++++++++++----------------
>  1 file changed, 22 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index e142095..3f5c1dc 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2696,27 +2696,14 @@ static bool ilk_disable_lp_wm(struct drm_device *dev)
>         return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
>  }
>
> -static void ilk_update_wm(struct drm_crtc *crtc)
> +static void ilk_program_watermarks(struct drm_device *dev)
>  {
> -       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -       struct drm_device *dev = crtc->dev;
>         struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
>         struct ilk_wm_maximums max;
> -       struct ilk_pipe_wm_parameters params = {};
> +       struct intel_wm_config config = {};
>         struct ilk_wm_values results = {};
>         enum intel_ddb_partitioning partitioning;
> -       struct intel_pipe_wm pipe_wm = {};
> -       struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
> -       struct intel_wm_config config = {};
> -
> -       ilk_compute_wm_parameters(crtc, &params);
> -
> -       intel_compute_pipe_wm(crtc, &params, &pipe_wm);
> -
> -       if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
> -               return;
> -
> -       intel_crtc->wm.active = pipe_wm;
>
>         ilk_compute_wm_config(dev, &config);
>
> @@ -2742,6 +2729,25 @@ static void ilk_update_wm(struct drm_crtc *crtc)
>         ilk_write_wm_values(dev_priv, &results);
>  }
>
> +static void ilk_update_wm(struct drm_crtc *crtc)
> +{
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       struct drm_device *dev = crtc->dev;
> +       struct ilk_pipe_wm_parameters params = {};
> +       struct intel_pipe_wm pipe_wm = {};
> +
> +       ilk_compute_wm_parameters(crtc, &params);
> +
> +       intel_compute_pipe_wm(crtc, &params, &pipe_wm);
> +
> +       if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
> +               return;
> +
> +       intel_crtc->wm.active = pipe_wm;
> +
> +       ilk_program_watermarks(dev);
> +}
> +
>  static void ilk_update_sprite_wm(struct drm_plane *plane,
>                                      struct drm_crtc *crtc,
>                                      uint32_t sprite_width, int pixel_size,
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



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

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

* Re: [PATCH 14/24] drm/i915: Add dev_priv->wm.mutex
  2014-03-07 16:32 ` [PATCH 14/24] drm/i915: Add dev_priv->wm.mutex ville.syrjala
@ 2014-04-23 21:47   ` Paulo Zanoni
  2014-04-24  8:07     ` Ville Syrjälä
  0 siblings, 1 reply; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-23 21:47 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Add a mutex to protect most of the watermark state. Will be useful when
> we start to update watermarks asynchronously from plane updates, or
> when we get finer grained locking for planes.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h  | 11 ++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h |  5 ++++-
>  drivers/gpu/drm/i915/intel_pm.c  | 21 +++++++++++++++++++--
>  3 files changed, 33 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 29da39f..0b19723 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1595,8 +1595,17 @@ typedef struct drm_i915_private {
>                 /* cursor */
>                 uint16_t cur_latency[5];
>
> -               /* current hardware state */
> +               /*
> +                * current hardware state
> +                * protected by dev_priv->wm.mutex
> +                */
>                 struct ilk_wm_values hw;
> +
> +               /*
> +                * protects some dev_priv->wm and intel_crtc->wm
> +                * state as well as the actual hardware registers
> +                */
> +               struct mutex mutex;
>         } wm;
>
>         struct i915_package_c8 pc8;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index f022a78..8e32d69 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -384,7 +384,10 @@ struct intel_crtc {
>
>         /* per-pipe watermark state */
>         struct {
> -               /* watermarks currently being used  */
> +               /*
> +                * watermarks currently being used
> +                * protected by dev_priv->wm.mutex
> +                */
>                 struct intel_pipe_wm active;
>         } wm;
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 3f5c1dc..d8adcb3 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2692,8 +2692,13 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
>  static bool ilk_disable_lp_wm(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
> +       bool changed;
>
> -       return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
> +       mutex_lock(&dev_priv->wm.mutex);
> +       changed = _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
> +       mutex_unlock(&dev_priv->wm.mutex);
> +
> +       return changed;
>  }
>
>  static void ilk_program_watermarks(struct drm_device *dev)
> @@ -2733,6 +2738,7 @@ static void ilk_update_wm(struct drm_crtc *crtc)
>  {
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>         struct drm_device *dev = crtc->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
>         struct ilk_pipe_wm_parameters params = {};
>         struct intel_pipe_wm pipe_wm = {};
>
> @@ -2740,12 +2746,17 @@ static void ilk_update_wm(struct drm_crtc *crtc)
>
>         intel_compute_pipe_wm(crtc, &params, &pipe_wm);
>
> +       mutex_lock(&dev_priv->wm.mutex);
> +
>         if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
> -               return;
> +               goto unlock;
>
>         intel_crtc->wm.active = pipe_wm;
>
>         ilk_program_watermarks(dev);
> +
> + unlock:
> +       mutex_unlock(&dev_priv->wm.mutex);
>  }
>
>  static void ilk_update_sprite_wm(struct drm_plane *plane,
> @@ -2817,10 +2828,14 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
>         struct drm_i915_private *dev_priv = dev->dev_private;
>         struct drm_crtc *crtc;
>
> +       mutex_lock(&dev_priv->wm.mutex);
> +
>         _ilk_wm_get_hw_state(dev, &dev_priv->wm.hw);
>
>         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
>                 _ilk_pipe_wm_hw_to_sw(crtc);
> +
> +       mutex_unlock(&dev_priv->wm.mutex);
>  }
>
>  /**
> @@ -5760,6 +5775,8 @@ void intel_init_pm(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
>
> +       mutex_init(&dev_priv->wm.mutex);
> +

I think you should probably init this at intel_pm_setup(), which is
called way earlier. Just to be safe.

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

>         if (HAS_FBC(dev)) {
>                 if (INTEL_INFO(dev)->gen >= 7) {
>                         dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
> --
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



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

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

* Re: [PATCH 14/24] drm/i915: Add dev_priv->wm.mutex
  2014-04-23 21:47   ` Paulo Zanoni
@ 2014-04-24  8:07     ` Ville Syrjälä
  0 siblings, 0 replies; 71+ messages in thread
From: Ville Syrjälä @ 2014-04-24  8:07 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Wed, Apr 23, 2014 at 06:47:04PM -0300, Paulo Zanoni wrote:
> 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Add a mutex to protect most of the watermark state. Will be useful when
> > we start to update watermarks asynchronously from plane updates, or
> > when we get finer grained locking for planes.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h  | 11 ++++++++++-
> >  drivers/gpu/drm/i915/intel_drv.h |  5 ++++-
> >  drivers/gpu/drm/i915/intel_pm.c  | 21 +++++++++++++++++++--
> >  3 files changed, 33 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 29da39f..0b19723 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1595,8 +1595,17 @@ typedef struct drm_i915_private {
> >                 /* cursor */
> >                 uint16_t cur_latency[5];
> >
> > -               /* current hardware state */
> > +               /*
> > +                * current hardware state
> > +                * protected by dev_priv->wm.mutex
> > +                */
> >                 struct ilk_wm_values hw;
> > +
> > +               /*
> > +                * protects some dev_priv->wm and intel_crtc->wm
> > +                * state as well as the actual hardware registers
> > +                */
> > +               struct mutex mutex;
> >         } wm;
> >
> >         struct i915_package_c8 pc8;
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index f022a78..8e32d69 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -384,7 +384,10 @@ struct intel_crtc {
> >
> >         /* per-pipe watermark state */
> >         struct {
> > -               /* watermarks currently being used  */
> > +               /*
> > +                * watermarks currently being used
> > +                * protected by dev_priv->wm.mutex
> > +                */
> >                 struct intel_pipe_wm active;
> >         } wm;
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 3f5c1dc..d8adcb3 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2692,8 +2692,13 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
> >  static bool ilk_disable_lp_wm(struct drm_device *dev)
> >  {
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> > +       bool changed;
> >
> > -       return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
> > +       mutex_lock(&dev_priv->wm.mutex);
> > +       changed = _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
> > +       mutex_unlock(&dev_priv->wm.mutex);
> > +
> > +       return changed;
> >  }
> >
> >  static void ilk_program_watermarks(struct drm_device *dev)
> > @@ -2733,6 +2738,7 @@ static void ilk_update_wm(struct drm_crtc *crtc)
> >  {
> >         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >         struct drm_device *dev = crtc->dev;
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> >         struct ilk_pipe_wm_parameters params = {};
> >         struct intel_pipe_wm pipe_wm = {};
> >
> > @@ -2740,12 +2746,17 @@ static void ilk_update_wm(struct drm_crtc *crtc)
> >
> >         intel_compute_pipe_wm(crtc, &params, &pipe_wm);
> >
> > +       mutex_lock(&dev_priv->wm.mutex);
> > +
> >         if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
> > -               return;
> > +               goto unlock;
> >
> >         intel_crtc->wm.active = pipe_wm;
> >
> >         ilk_program_watermarks(dev);
> > +
> > + unlock:
> > +       mutex_unlock(&dev_priv->wm.mutex);
> >  }
> >
> >  static void ilk_update_sprite_wm(struct drm_plane *plane,
> > @@ -2817,10 +2828,14 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> >         struct drm_crtc *crtc;
> >
> > +       mutex_lock(&dev_priv->wm.mutex);
> > +
> >         _ilk_wm_get_hw_state(dev, &dev_priv->wm.hw);
> >
> >         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> >                 _ilk_pipe_wm_hw_to_sw(crtc);
> > +
> > +       mutex_unlock(&dev_priv->wm.mutex);
> >  }
> >
> >  /**
> > @@ -5760,6 +5775,8 @@ void intel_init_pm(struct drm_device *dev)
> >  {
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> >
> > +       mutex_init(&dev_priv->wm.mutex);
> > +
> 
> I think you should probably init this at intel_pm_setup(), which is
> called way earlier. Just to be safe.

If we call some WM function before intel_init_pm() we have a serious
bug. This is where we set up the WM function pointers and extract the
latency values from SSKPD/MLTR.

> 
> With that fixed: Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>.
> 
> >         if (HAS_FBC(dev)) {
> >                 if (INTEL_INFO(dev)->gen >= 7) {
> >                         dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
> > --
> > 1.8.3.2
> >
> > _______________________________________________
> > 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] 71+ messages in thread

* Re: [PATCH 10/24] drm/i915: Leave interrupts enabled while disabling crtcs during suspend
  2014-03-07 16:32 ` [PATCH 10/24] drm/i915: Leave interrupts enabled while disabling crtcs during suspend ville.syrjala
@ 2014-04-24 13:33   ` Daniel Vetter
  0 siblings, 0 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-04-24 13:33 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Fri, Mar 07, 2014 at 06:32:17PM +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> The new watermaek update mechanism requires interrupts to work
> correctly. Because of this we need interrupts while disabling crtcs
> during suspend. So move the irq disable to happen a bit later.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

I guess we have sufficient amounts of WARN_ON(!dev->irqs_enabled)
sprinkled over relevant places already?

Just want to start locking down our setup/teardown sequences as much as
possible since making them more fancy and dynamic is an ongoing effort.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_drv.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 658fe24..079fb904 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -448,7 +448,6 @@ static int i915_drm_freeze(struct drm_device *dev)
>  
>  		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
>  
> -		drm_irq_uninstall(dev);
>  		dev_priv->enable_hotplug_processing = false;
>  		/*
>  		 * Disable CRTCs directly since we want to preserve sw state
> @@ -459,6 +458,8 @@ static int i915_drm_freeze(struct drm_device *dev)
>  			dev_priv->display.crtc_disable(crtc);
>  		mutex_unlock(&dev->mode_config.mutex);
>  
> +		drm_irq_uninstall(dev);
> +
>  		intel_modeset_suspend_hw(dev);
>  	}
>  
> -- 
> 1.8.3.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers
  2014-04-23 19:13   ` Paulo Zanoni
  2014-04-23 20:28     ` Ville Syrjälä
@ 2014-04-28 12:44     ` ville.syrjala
  2014-04-28 12:44       ` [PATCH v2 05.2/24] drm/i915: Merge LP1+ watermarks in safer way ville.syrjala
  2014-04-28 21:23       ` [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers Paulo Zanoni
  1 sibling, 2 replies; 71+ messages in thread
From: ville.syrjala @ 2014-04-28 12:44 UTC (permalink / raw)
  To: intel-gfx

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

When we calculate the watermarks for a pipe make sure we leave any
level fully zeroed out if it would exceed any of the maximum values
that fit in the registers.

This will be important later when we start to use also disabled
watermark levels during LP1+ merging.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f061ef1..c722acb 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1921,6 +1921,16 @@ static void ilk_compute_wm_maximums(const struct drm_device *dev,
 	max->fbc = ilk_fbc_wm_reg_max(dev);
 }
 
+static void ilk_compute_wm_reg_maximums(struct drm_device *dev,
+					int level,
+					struct ilk_wm_maximums *max)
+{
+	max->pri = ilk_plane_wm_reg_max(dev, level, false);
+	max->spr = ilk_plane_wm_reg_max(dev, level, true);
+	max->cur = ilk_cursor_wm_reg_max(dev, level);
+	max->fbc = ilk_fbc_wm_reg_max(dev);
+}
+
 static bool ilk_validate_wm_level(int level,
 				  const struct ilk_wm_maximums *max,
 				  struct intel_wm_level *result)
@@ -2178,9 +2188,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	};
 	struct ilk_wm_maximums max;
 
-	/* LP0 watermarks always use 1/2 DDB partitioning */
-	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
-
 	pipe_wm->pipe_enabled = params->active;
 	pipe_wm->sprites_enabled = params->spr.enabled;
 	pipe_wm->sprites_scaled = params->spr.scaled;
@@ -2193,15 +2200,37 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	if (params->spr.scaled)
 		max_level = 0;
 
-	for (level = 0; level <= max_level; level++)
-		ilk_compute_wm_level(dev_priv, level, params,
-				     &pipe_wm->wm[level]);
+	ilk_compute_wm_level(dev_priv, 0, params, &pipe_wm->wm[0]);
 
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
 
+	/* LP0 watermarks always use 1/2 DDB partitioning */
+	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+
 	/* At least LP0 must be valid */
-	return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
+	if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
+		return false;
+
+	ilk_compute_wm_reg_maximums(dev, 1, &max);
+
+	for (level = 1; level <= max_level; level++) {
+		struct intel_wm_level wm = {};
+
+		ilk_compute_wm_level(dev_priv, level, params, &wm);
+
+		/*
+		 * Disable any watermark level that exceeds the
+		 * register maximums since such watermarks are
+		 * always invalid.
+		 */
+		if (!ilk_validate_wm_level(level, &max, &wm))
+			break;
+
+		pipe_wm->wm[level] = wm;
+	}
+
+	return true;
 }
 
 /*
-- 
1.8.3.2

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

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

* [PATCH v2 05.2/24] drm/i915: Merge LP1+ watermarks in safer way
  2014-04-28 12:44     ` [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers ville.syrjala
@ 2014-04-28 12:44       ` ville.syrjala
  2014-04-28 21:35         ` Paulo Zanoni
  2014-04-28 21:23       ` [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers Paulo Zanoni
  1 sibling, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-04-28 12:44 UTC (permalink / raw)
  To: intel-gfx

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

On ILK when we disable a particular watermark level, we must
maintain the actual watermark values for that level for some time
(until the next vblank possibly). Otherwise we risk underruns.

In order to achieve that result we must merge the LP1+ watermarks a
bit differently since we must also merge levels that are to be
disabled. We must also make sure we don't overflow the fields in the
watermark registers in case the calculated watermarks come out too
big to fit.

As early as possbile we mark all computed watermark levels as
disabled if they would exceed the register maximums. We make sure
to leave the actual watermarks for such levels zeroed out. The during
merging, we take the maxium values for every level, regardless if
they're disabled or not. That may seem a bit pointless since at the
moment all the watermark levels we merge should have their values
zeroed if the level is already disabled. However soon we will be
dealing with intermediate watermarks that, in addition to the new
watermark values, also contain the previous watermark values, and so
levels that are disabled may no longer be zeroed out.

v2: Split the patch in two (Paulo)
    Use if() instead of & when merging ->enable (Paulo)

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c722acb..b89fc33 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2242,6 +2242,8 @@ static void ilk_merge_wm_level(struct drm_device *dev,
 {
 	const struct intel_crtc *intel_crtc;
 
+	ret_wm->enable = true;
+
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
 		const struct intel_pipe_wm *active = &intel_crtc->wm.active;
 		const struct intel_wm_level *wm = &active->wm[level];
@@ -2249,16 +2251,19 @@ static void ilk_merge_wm_level(struct drm_device *dev,
 		if (!active->pipe_enabled)
 			continue;
 
+		/*
+		 * The watermark values may have been used in the past,
+		 * so we must maintain them in the registers for some
+		 * time even if the level is now disabled.
+		 */
 		if (!wm->enable)
-			return;
+			ret_wm->enable = false;
 
 		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);
 	}
-
-	ret_wm->enable = true;
 }
 
 /*
@@ -2270,6 +2275,7 @@ static void ilk_wm_merge(struct drm_device *dev,
 			 struct intel_pipe_wm *merged)
 {
 	int level, max_level = ilk_wm_max_level(dev);
+	int last_enabled_level = max_level;
 
 	/* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
 	if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
@@ -2285,15 +2291,19 @@ static void ilk_wm_merge(struct drm_device *dev,
 
 		ilk_merge_wm_level(dev, level, wm);
 
-		if (!ilk_validate_wm_level(level, max, wm))
-			break;
+		if (level > last_enabled_level)
+			wm->enable = false;
+		else if (!ilk_validate_wm_level(level, max, wm))
+			/* make sure all following levels get disabled */
+			last_enabled_level = level - 1;
 
 		/*
 		 * The spec says it is preferred to disable
 		 * FBC WMs instead of disabling a WM level.
 		 */
 		if (wm->fbc_val > max->fbc) {
-			merged->fbc_wm_enabled = false;
+			if (wm->enable)
+				merged->fbc_wm_enabled = false;
 			wm->fbc_val = 0;
 		}
 	}
@@ -2348,14 +2358,19 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 		level = ilk_wm_lp_to_level(wm_lp, merged);
 
 		r = &merged->wm[level];
-		if (!r->enable)
-			break;
 
-		results->wm_lp[wm_lp - 1] = WM3_LP_EN |
+		/*
+		 * Maintain the watermark values even if the level is
+		 * disabled. Doing otherwise could cause underruns.
+		 */
+		results->wm_lp[wm_lp - 1] =
 			(ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT) |
 			(r->pri_val << WM1_LP_SR_SHIFT) |
 			r->cur_val;
 
+		if (r->enable)
+			results->wm_lp[wm_lp - 1] |= WM1_LP_SR_EN;
+
 		if (INTEL_INFO(dev)->gen >= 8)
 			results->wm_lp[wm_lp - 1] |=
 				r->fbc_val << WM1_LP_FBC_SHIFT_BDW;
@@ -2363,6 +2378,10 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 			results->wm_lp[wm_lp - 1] |=
 				r->fbc_val << WM1_LP_FBC_SHIFT;
 
+		/*
+		 * Always set WM1S_LP_EN when spr_val != 0, even if the
+		 * level is disabled. Doing otherwise could cause underruns.
+		 */
 		if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) {
 			WARN_ON(wm_lp != 1);
 			results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
-- 
1.8.3.2

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

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

* [PATCH v2 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-03-07 21:29   ` Daniel Vetter
  2014-03-10 11:20     ` Ville Syrjälä
@ 2014-04-28 12:53     ` ville.syrjala
  2014-04-28 21:39       ` Paulo Zanoni
  2014-04-30 11:28       ` Chris Wilson
  1 sibling, 2 replies; 71+ messages in thread
From: ville.syrjala @ 2014-04-28 12:53 UTC (permalink / raw)
  To: intel-gfx

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

We won't be calling intel_enable_primary_plane() or
intel_disable_primary_plane() with the primary plane in the
wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.

v2: Convert the checks to WARNs instead (Daniel,Paulo)

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7938556..af9e3fe 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1896,8 +1896,7 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
 
 	reg = DSPCNTR(plane);
 	val = I915_READ(reg);
-	if (val & DISPLAY_PLANE_ENABLE)
-		return;
+	WARN_ON(val & DISPLAY_PLANE_ENABLE);
 
 	I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
 	intel_flush_primary_plane(dev_priv, plane);
@@ -1926,8 +1925,7 @@ static void intel_disable_primary_plane(struct drm_i915_private *dev_priv,
 
 	reg = DSPCNTR(plane);
 	val = I915_READ(reg);
-	if ((val & DISPLAY_PLANE_ENABLE) == 0)
-		return;
+	WARN_ON((val & DISPLAY_PLANE_ENABLE) == 0);
 
 	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
 	intel_flush_primary_plane(dev_priv, plane);
-- 
1.8.3.2

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

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

* [PATCH v2 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes
  2014-04-07 21:21   ` Paulo Zanoni
  2014-04-08 18:19     ` Ville Syrjälä
@ 2014-04-28 12:58     ` ville.syrjala
  2014-04-28 21:42       ` Paulo Zanoni
  1 sibling, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-04-28 12:58 UTC (permalink / raw)
  To: intel-gfx

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

Becasue of the upcoming vblank interrupt driven watermark update
mechanism we will have use for vblank interrupts during plane
enabling/disabling. So don't call drm_vblank_off() until planes
are off, and call drm_vblank_on() just before we start to enable
the planes.

v2: Pimp commit message (Paulo)

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 88df4ea..8d2a31e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3547,6 +3547,8 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
+	drm_vblank_on(dev, pipe);
+
 	intel_enable_primary_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
 	intel_crtc_update_cursor(crtc, true);
@@ -3557,8 +3559,6 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
 	mutex_lock(&dev->struct_mutex);
 	intel_update_fbc(dev);
 	mutex_unlock(&dev->struct_mutex);
-
-	drm_vblank_on(dev, pipe);
 }
 
 static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
@@ -3570,7 +3570,6 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
 	int plane = intel_crtc->plane;
 
 	intel_crtc_wait_for_pending_flips(crtc);
-	drm_vblank_off(dev, pipe);
 
 	if (dev_priv->fbc.plane == plane)
 		intel_disable_fbc(dev);
@@ -3581,6 +3580,8 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
 	intel_disable_planes(crtc);
 	intel_disable_primary_plane(dev_priv, plane, pipe);
 	intel_wait_for_vblank(dev, pipe);
+
+	drm_vblank_off(dev, pipe);
 }
 
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
-- 
1.8.3.2

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

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

* Re: [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers
  2014-04-28 12:44     ` [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers ville.syrjala
  2014-04-28 12:44       ` [PATCH v2 05.2/24] drm/i915: Merge LP1+ watermarks in safer way ville.syrjala
@ 2014-04-28 21:23       ` Paulo Zanoni
  1 sibling, 0 replies; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-28 21:23 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-04-28 9:44 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> When we calculate the watermarks for a pipe make sure we leave any
> level fully zeroed out if it would exceed any of the maximum values
> that fit in the registers.
>
> This will be important later when we start to use also disabled
> watermark levels during LP1+ merging.

Thanks for splitting the patch! It's much easier to review now :)

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 43 ++++++++++++++++++++++++++++++++++-------
>  1 file changed, 36 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index f061ef1..c722acb 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1921,6 +1921,16 @@ static void ilk_compute_wm_maximums(const struct drm_device *dev,
>         max->fbc = ilk_fbc_wm_reg_max(dev);
>  }
>
> +static void ilk_compute_wm_reg_maximums(struct drm_device *dev,
> +                                       int level,
> +                                       struct ilk_wm_maximums *max)
> +{
> +       max->pri = ilk_plane_wm_reg_max(dev, level, false);
> +       max->spr = ilk_plane_wm_reg_max(dev, level, true);
> +       max->cur = ilk_cursor_wm_reg_max(dev, level);
> +       max->fbc = ilk_fbc_wm_reg_max(dev);
> +}
> +
>  static bool ilk_validate_wm_level(int level,
>                                   const struct ilk_wm_maximums *max,
>                                   struct intel_wm_level *result)
> @@ -2178,9 +2188,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         };
>         struct ilk_wm_maximums max;
>
> -       /* LP0 watermarks always use 1/2 DDB partitioning */
> -       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> -
>         pipe_wm->pipe_enabled = params->active;
>         pipe_wm->sprites_enabled = params->spr.enabled;
>         pipe_wm->sprites_scaled = params->spr.scaled;
> @@ -2193,15 +2200,37 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         if (params->spr.scaled)
>                 max_level = 0;
>
> -       for (level = 0; level <= max_level; level++)
> -               ilk_compute_wm_level(dev_priv, level, params,
> -                                    &pipe_wm->wm[level]);
> +       ilk_compute_wm_level(dev_priv, 0, params, &pipe_wm->wm[0]);
>
>         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
>                 pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
>
> +       /* LP0 watermarks always use 1/2 DDB partitioning */
> +       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> +
>         /* At least LP0 must be valid */
> -       return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
> +       if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
> +               return false;

The only caller of this function does not really check its return
value. OTOH, fixing this is outside of the scope of your patch, I'm
just mentioning in case you have some watermarks TODO list :)

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

> +
> +       ilk_compute_wm_reg_maximums(dev, 1, &max);
> +
> +       for (level = 1; level <= max_level; level++) {
> +               struct intel_wm_level wm = {};
> +
> +               ilk_compute_wm_level(dev_priv, level, params, &wm);
> +
> +               /*
> +                * Disable any watermark level that exceeds the
> +                * register maximums since such watermarks are
> +                * always invalid.
> +                */
> +               if (!ilk_validate_wm_level(level, &max, &wm))
> +                       break;
> +
> +               pipe_wm->wm[level] = wm;
> +       }
> +
> +       return true;
>  }
>
>  /*
> --
> 1.8.3.2
>



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

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

* Re: [PATCH v2 05.2/24] drm/i915: Merge LP1+ watermarks in safer way
  2014-04-28 12:44       ` [PATCH v2 05.2/24] drm/i915: Merge LP1+ watermarks in safer way ville.syrjala
@ 2014-04-28 21:35         ` Paulo Zanoni
  0 siblings, 0 replies; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-28 21:35 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-04-28 9:44 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> On ILK when we disable a particular watermark level, we must
> maintain the actual watermark values for that level for some time
> (until the next vblank possibly). Otherwise we risk underruns.
>
> In order to achieve that result we must merge the LP1+ watermarks a
> bit differently since we must also merge levels that are to be
> disabled. We must also make sure we don't overflow the fields in the
> watermark registers in case the calculated watermarks come out too
> big to fit.
>
> As early as possbile we mark all computed watermark levels as
> disabled if they would exceed the register maximums. We make sure
> to leave the actual watermarks for such levels zeroed out. The during

"_Then_ during merging", I guess.

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

> merging, we take the maxium values for every level, regardless if
> they're disabled or not. That may seem a bit pointless since at the
> moment all the watermark levels we merge should have their values
> zeroed if the level is already disabled. However soon we will be
> dealing with intermediate watermarks that, in addition to the new
> watermark values, also contain the previous watermark values, and so
> levels that are disabled may no longer be zeroed out.
>
> v2: Split the patch in two (Paulo)
>     Use if() instead of & when merging ->enable (Paulo)
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 37 ++++++++++++++++++++++++++++---------
>  1 file changed, 28 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c722acb..b89fc33 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2242,6 +2242,8 @@ static void ilk_merge_wm_level(struct drm_device *dev,
>  {
>         const struct intel_crtc *intel_crtc;
>
> +       ret_wm->enable = true;
> +
>         list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
>                 const struct intel_pipe_wm *active = &intel_crtc->wm.active;
>                 const struct intel_wm_level *wm = &active->wm[level];
> @@ -2249,16 +2251,19 @@ static void ilk_merge_wm_level(struct drm_device *dev,
>                 if (!active->pipe_enabled)
>                         continue;
>
> +               /*
> +                * The watermark values may have been used in the past,
> +                * so we must maintain them in the registers for some
> +                * time even if the level is now disabled.
> +                */
>                 if (!wm->enable)
> -                       return;
> +                       ret_wm->enable = false;
>
>                 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);
>         }
> -
> -       ret_wm->enable = true;
>  }
>
>  /*
> @@ -2270,6 +2275,7 @@ static void ilk_wm_merge(struct drm_device *dev,
>                          struct intel_pipe_wm *merged)
>  {
>         int level, max_level = ilk_wm_max_level(dev);
> +       int last_enabled_level = max_level;
>
>         /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
>         if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
> @@ -2285,15 +2291,19 @@ static void ilk_wm_merge(struct drm_device *dev,
>
>                 ilk_merge_wm_level(dev, level, wm);
>
> -               if (!ilk_validate_wm_level(level, max, wm))
> -                       break;
> +               if (level > last_enabled_level)
> +                       wm->enable = false;
> +               else if (!ilk_validate_wm_level(level, max, wm))
> +                       /* make sure all following levels get disabled */
> +                       last_enabled_level = level - 1;
>
>                 /*
>                  * The spec says it is preferred to disable
>                  * FBC WMs instead of disabling a WM level.
>                  */
>                 if (wm->fbc_val > max->fbc) {
> -                       merged->fbc_wm_enabled = false;
> +                       if (wm->enable)
> +                               merged->fbc_wm_enabled = false;
>                         wm->fbc_val = 0;
>                 }
>         }
> @@ -2348,14 +2358,19 @@ static void ilk_compute_wm_results(struct drm_device *dev,
>                 level = ilk_wm_lp_to_level(wm_lp, merged);
>
>                 r = &merged->wm[level];
> -               if (!r->enable)
> -                       break;
>
> -               results->wm_lp[wm_lp - 1] = WM3_LP_EN |
> +               /*
> +                * Maintain the watermark values even if the level is
> +                * disabled. Doing otherwise could cause underruns.
> +                */
> +               results->wm_lp[wm_lp - 1] =
>                         (ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT) |
>                         (r->pri_val << WM1_LP_SR_SHIFT) |
>                         r->cur_val;
>
> +               if (r->enable)
> +                       results->wm_lp[wm_lp - 1] |= WM1_LP_SR_EN;
> +
>                 if (INTEL_INFO(dev)->gen >= 8)
>                         results->wm_lp[wm_lp - 1] |=
>                                 r->fbc_val << WM1_LP_FBC_SHIFT_BDW;
> @@ -2363,6 +2378,10 @@ static void ilk_compute_wm_results(struct drm_device *dev,
>                         results->wm_lp[wm_lp - 1] |=
>                                 r->fbc_val << WM1_LP_FBC_SHIFT;
>
> +               /*
> +                * Always set WM1S_LP_EN when spr_val != 0, even if the
> +                * level is disabled. Doing otherwise could cause underruns.
> +                */
>                 if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) {
>                         WARN_ON(wm_lp != 1);
>                         results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
> --
> 1.8.3.2
>



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

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

* Re: [PATCH v2 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-04-28 12:53     ` [PATCH v2 " ville.syrjala
@ 2014-04-28 21:39       ` Paulo Zanoni
  2014-04-30 11:28       ` Chris Wilson
  1 sibling, 0 replies; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-28 21:39 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-04-28 9:53 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We won't be calling intel_enable_primary_plane() or
> intel_disable_primary_plane() with the primary plane in the
> wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.
>
> v2: Convert the checks to WARNs instead (Daniel,Paulo)

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

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7938556..af9e3fe 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1896,8 +1896,7 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv,
>
>         reg = DSPCNTR(plane);
>         val = I915_READ(reg);
> -       if (val & DISPLAY_PLANE_ENABLE)
> -               return;
> +       WARN_ON(val & DISPLAY_PLANE_ENABLE);
>
>         I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
>         intel_flush_primary_plane(dev_priv, plane);
> @@ -1926,8 +1925,7 @@ static void intel_disable_primary_plane(struct drm_i915_private *dev_priv,
>
>         reg = DSPCNTR(plane);
>         val = I915_READ(reg);
> -       if ((val & DISPLAY_PLANE_ENABLE) == 0)
> -               return;
> +       WARN_ON((val & DISPLAY_PLANE_ENABLE) == 0);
>
>         I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
>         intel_flush_primary_plane(dev_priv, plane);
> --
> 1.8.3.2
>



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

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

* Re: [PATCH v2 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes
  2014-04-28 12:58     ` [PATCH v2 " ville.syrjala
@ 2014-04-28 21:42       ` Paulo Zanoni
  2014-04-29 14:04         ` Daniel Vetter
  0 siblings, 1 reply; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-28 21:42 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2014-04-28 9:58 GMT-03:00  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Becasue of the upcoming vblank interrupt driven watermark update

BecaUSe.

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

> mechanism we will have use for vblank interrupts during plane
> enabling/disabling. So don't call drm_vblank_off() until planes
> are off, and call drm_vblank_on() just before we start to enable
> the planes.
>
> v2: Pimp commit message (Paulo)
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 88df4ea..8d2a31e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3547,6 +3547,8 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
>         int pipe = intel_crtc->pipe;
>         int plane = intel_crtc->plane;
>
> +       drm_vblank_on(dev, pipe);
> +
>         intel_enable_primary_plane(dev_priv, plane, pipe);
>         intel_enable_planes(crtc);
>         intel_crtc_update_cursor(crtc, true);
> @@ -3557,8 +3559,6 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
>         mutex_lock(&dev->struct_mutex);
>         intel_update_fbc(dev);
>         mutex_unlock(&dev->struct_mutex);
> -
> -       drm_vblank_on(dev, pipe);
>  }
>
>  static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> @@ -3570,7 +3570,6 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
>         int plane = intel_crtc->plane;
>
>         intel_crtc_wait_for_pending_flips(crtc);
> -       drm_vblank_off(dev, pipe);
>
>         if (dev_priv->fbc.plane == plane)
>                 intel_disable_fbc(dev);
> @@ -3581,6 +3580,8 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
>         intel_disable_planes(crtc);
>         intel_disable_primary_plane(dev_priv, plane, pipe);
>         intel_wait_for_vblank(dev, pipe);
> +
> +       drm_vblank_off(dev, pipe);
>  }
>
>  static void ironlake_crtc_enable(struct drm_crtc *crtc)
> --
> 1.8.3.2
>



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

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

* Re: [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm
  2014-04-07 14:14   ` Paulo Zanoni
@ 2014-04-29 11:18     ` Daniel Vetter
  2014-04-29 11:20       ` Daniel Vetter
  0 siblings, 1 reply; 71+ messages in thread
From: Daniel Vetter @ 2014-04-29 11:18 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Mon, Apr 07, 2014 at 11:14:05AM -0300, Paulo Zanoni wrote:
> 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > intel_pipe_wm will be used to track the state in different stages
> > of the watermark update process. For that we need to keep a bit
> > more state in intel_pipe_wm.
> >
> > We also need to separate the multi-pipe intel_wm_config computation
> > from ilk_compute_wm_parameters() as that one deals with the future
> > state, and we need the intel_wm_config to match the current hardware
> > state at the time we do the watermark merging for multiple pipes.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Needs minor rebase, but looks correct.

Ok in my eyes this conflict looks a bit tricky, and since I lack the
insight of you two for the watermark code I'd prefer a rebased version.
-Daniel

> 
> <insert complaint about the fact that the watermarks code is pretty
> complex these days>
> 
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> > ---
> >  drivers/gpu/drm/i915/intel_drv.h |  3 ++
> >  drivers/gpu/drm/i915/intel_pm.c  | 64 +++++++++++++++++++++++++++-------------
> >  2 files changed, 46 insertions(+), 21 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 8c9892d..f022a78 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -333,6 +333,9 @@ struct intel_pipe_wm {
> >         struct intel_wm_level wm[5];
> >         uint32_t linetime;
> >         bool fbc_wm_enabled;
> > +       bool pipe_enabled;
> > +       bool sprites_enabled;
> > +       bool sprites_scaled;
> >  };
> >
> >  struct intel_crtc {
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 26c79ed..e0d1c8b 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2105,38 +2105,52 @@ static void intel_setup_wm_latency(struct drm_device *dev)
> >  }
> >
> >  static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
> > -                                     struct ilk_pipe_wm_parameters *p,
> > -                                     struct intel_wm_config *config)
> > +                                     struct ilk_pipe_wm_parameters *p)
> >  {
> >         struct drm_device *dev = crtc->dev;
> >         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >         enum pipe pipe = intel_crtc->pipe;
> >         struct drm_plane *plane;
> >
> > -       p->active = intel_crtc_active(crtc);
> > -       if (p->active) {
> > -               p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_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.pipe_src_w;
> > -               p->cur.horiz_pixels = 64;
> > -               /* TODO: for now, assume primary and cursor planes are always enabled. */
> > -               p->pri.enabled = true;
> > -               p->cur.enabled = true;
> > -       }
> > +       if (!intel_crtc_active(crtc))
> > +               return;
> >
> > -       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> > -               config->num_pipes_active += intel_crtc_active(crtc);
> > +       p->active = true;
> > +       p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_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.pipe_src_w;
> > +       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);
> >
> > -               if (intel_plane->pipe == pipe)
> > +               if (intel_plane->pipe == pipe) {
> >                         p->spr = intel_plane->wm;
> > +                       break;
> > +               }
> > +       }
> > +}
> >
> > -               config->sprites_enabled |= intel_plane->wm.enabled;
> > -               config->sprites_scaled |= intel_plane->wm.scaled;
> > +static void ilk_compute_wm_config(struct drm_device *dev,
> > +                                 struct intel_wm_config *config)
> > +{
> > +       struct intel_crtc *intel_crtc;
> > +
> > +       /* Compute the currently _active_ config */
> > +       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->num_pipes_active++;
> >         }
> >  }
> >
> > @@ -2159,6 +2173,10 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
> >         /* LP0 watermarks always use 1/2 DDB partitioning */
> >         ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> >
> > +       pipe_wm->pipe_enabled = params->active;
> > +       pipe_wm->sprites_enabled = params->spr.enabled;
> > +       pipe_wm->sprites_scaled = params->spr.scaled;
> > +
> >         /* ILK/SNB: LP2+ watermarks only w/o sprites */
> >         if (INTEL_INFO(dev)->gen <= 6 && params->spr.enabled)
> >                 max_level = 1;
> > @@ -2548,7 +2566,7 @@ static void ilk_update_wm(struct drm_crtc *crtc)
> >         struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
> >         struct intel_wm_config config = {};
> >
> > -       ilk_compute_wm_parameters(crtc, &params, &config);
> > +       ilk_compute_wm_parameters(crtc, &params);
> >
> >         intel_compute_pipe_wm(crtc, &params, &pipe_wm);
> >
> > @@ -2557,6 +2575,8 @@ static void ilk_update_wm(struct drm_crtc *crtc)
> >
> >         intel_crtc->wm.active = pipe_wm;
> >
> > +       ilk_compute_wm_config(dev, &config);
> > +
> >         ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
> >         ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
> >
> > @@ -2623,7 +2643,9 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
> >         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> >                 hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
> >
> > -       if (intel_crtc_active(crtc)) {
> > +       active->pipe_enabled = intel_crtc_active(crtc);
> > +
> > +       if (active->pipe_enabled) {
> >                 u32 tmp = hw->wm_pipe[pipe];
> >
> >                 /*
> > --
> > 1.8.3.2
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm
  2014-04-29 11:18     ` Daniel Vetter
@ 2014-04-29 11:20       ` Daniel Vetter
  2014-04-29 12:34         ` Paulo Zanoni
  0 siblings, 1 reply; 71+ messages in thread
From: Daniel Vetter @ 2014-04-29 11:20 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Tue, Apr 29, 2014 at 01:18:50PM +0200, Daniel Vetter wrote:
> On Mon, Apr 07, 2014 at 11:14:05AM -0300, Paulo Zanoni wrote:
> > 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >
> > > intel_pipe_wm will be used to track the state in different stages
> > > of the watermark update process. For that we need to keep a bit
> > > more state in intel_pipe_wm.
> > >
> > > We also need to separate the multi-pipe intel_wm_config computation
> > > from ilk_compute_wm_parameters() as that one deals with the future
> > > state, and we need the intel_wm_config to match the current hardware
> > > state at the time we do the watermark merging for multiple pipes.
> > >
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Needs minor rebase, but looks correct.
> 
> Ok in my eyes this conflict looks a bit tricky, and since I lack the
> insight of you two for the watermark code I'd prefer a rebased version.

Or is this just because dinq is a bit out of sync with -nightly? In that
case I'm stalling on Dave to open up drm-next so that I can rebase the
entire shebang ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm
  2014-04-29 11:20       ` Daniel Vetter
@ 2014-04-29 12:34         ` Paulo Zanoni
  2014-04-29 13:57           ` Daniel Vetter
  0 siblings, 1 reply; 71+ messages in thread
From: Paulo Zanoni @ 2014-04-29 12:34 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

2014-04-29 8:20 GMT-03:00 Daniel Vetter <daniel@ffwll.ch>:
> On Tue, Apr 29, 2014 at 01:18:50PM +0200, Daniel Vetter wrote:
>> On Mon, Apr 07, 2014 at 11:14:05AM -0300, Paulo Zanoni wrote:
>> > 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
>> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > >
>> > > intel_pipe_wm will be used to track the state in different stages
>> > > of the watermark update process. For that we need to keep a bit
>> > > more state in intel_pipe_wm.
>> > >
>> > > We also need to separate the multi-pipe intel_wm_config computation
>> > > from ilk_compute_wm_parameters() as that one deals with the future
>> > > state, and we need the intel_wm_config to match the current hardware
>> > > state at the time we do the watermark merging for multiple pipes.
>> > >
>> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > Needs minor rebase, but looks correct.
>>
>> Ok in my eyes this conflict looks a bit tricky, and since I lack the
>> insight of you two for the watermark code I'd prefer a rebased version.
>
> Or is this just because dinq is a bit out of sync with -nightly? In that
> case I'm stalling on Dave to open up drm-next so that I can rebase the
> entire shebang ...

I believe you have already applied patches 1-4 a few weeks ago. Maybe
you're getting conflicts because you're applying already-applied
patches? :)

> -Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



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

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

* Re: [PATCH 11/24] drm/i915: Check hw vs. sw watermark state after programming
  2014-04-23 21:16   ` Paulo Zanoni
@ 2014-04-29 12:54     ` Ville Syrjälä
  0 siblings, 0 replies; 71+ messages in thread
From: Ville Syrjälä @ 2014-04-29 12:54 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Wed, Apr 23, 2014 at 06:16:07PM -0300, Paulo Zanoni wrote:
> 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Make sure we programmed the watermarks correctly, by reading out the
> > hardware state again after programming and comparing it with the
> > state we supposedly programmed into hardware. Dump the watermark
> > registers after a mismatch, very much like we for the pipe config.
> > The only difference is that we don't dump the entire watermark
> > software tracking state since that's spread around a bit.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> This one could also have been split into more than one patch: first
> you extract the functions, then later you add the new callers.
> 
> My only comment is: do we really want to check HW/SW state right after
> we write the register values? Shouldn't  this be done at some other
> time, like the end of the modeset sequence?

There's no guarantee that the WM update has finished there. I guess we
could sprinkle such checks to a few places. The check would have to merge
the active watermarks from all pipes and compare that with the register
contents. So it would check that our hardware state matches the software
active state at some point in time. But it can't really check that our
idea of active watermarks is correct.

This patch just checks that we actually wrote what we inteded into the
registers. So it basically tests that ilk_compute_wm_dirty() works and
that ilk_write_wm_values() didn't neglect to update something that was
deemed dirty.

> 
> Still, the patch seems correct, so: Reviewed-by: Paulo Zanoni
> <paulo.r.zanoni@intel.com>
> 
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 117 ++++++++++++++++++++++++++++------------
> >  1 file changed, 83 insertions(+), 34 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index ba4b23e..e519578a1 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2524,15 +2524,84 @@ static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
> >         return changed;
> >  }
> >
> > +static void _ilk_pipe_wm_get_hw_state(struct drm_device *dev,
> > +                                     enum pipe pipe,
> > +                                     struct ilk_wm_values *hw)
> > +{
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> > +       static const unsigned int wm0_pipe_reg[] = {
> > +               [PIPE_A] = WM0_PIPEA_ILK,
> > +               [PIPE_B] = WM0_PIPEB_ILK,
> > +               [PIPE_C] = WM0_PIPEC_IVB,
> > +       };
> > +
> > +       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
> > +
> > +       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > +               hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
> > +}
> > +
> > +static void _ilk_wm_get_hw_state(struct drm_device *dev,
> > +                                struct ilk_wm_values *hw)
> > +{
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> > +       enum pipe pipe;
> > +
> > +       for_each_pipe(pipe)
> > +               _ilk_pipe_wm_get_hw_state(dev, pipe, hw);
> > +
> > +       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
> > +       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
> > +       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
> > +
> > +       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> > +       if (INTEL_INFO(dev)->gen >= 7) {
> > +               hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> > +               hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> > +       }
> > +
> > +       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > +               hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> > +                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> > +       else if (IS_IVYBRIDGE(dev))
> > +               hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
> > +                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> > +
> > +       hw->enable_fbc_wm =
> > +               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> > +}
> > +
> > +static void ilk_dump_wm_values(const struct ilk_wm_values *hw,
> > +                              const char *context)
> > +{
> > +       DRM_DEBUG_KMS("%s watermark values\n", context);
> > +       DRM_DEBUG_KMS("WM_PIPE_A = 0x%08x\n",  hw->wm_pipe[PIPE_A]);
> > +       DRM_DEBUG_KMS("WM_PIPE_B = 0x%08x\n",  hw->wm_pipe[PIPE_B]);
> > +       DRM_DEBUG_KMS("WM_PIPE_C = 0x%08x\n",  hw->wm_pipe[PIPE_C]);
> > +       DRM_DEBUG_KMS("WM_LP_1 = 0x%08x\n", hw->wm_lp[0]);
> > +       DRM_DEBUG_KMS("WM_LP_2 = 0x%08x\n", hw->wm_lp[1]);
> > +       DRM_DEBUG_KMS("WM_LP_3 = 0x%08x\n", hw->wm_lp[2]);
> > +       DRM_DEBUG_KMS("WM_LP_SPR_1 = 0x%08x\n", hw->wm_lp_spr[0]);
> > +       DRM_DEBUG_KMS("WM_LP_SPR_2 = 0x%08x\n", hw->wm_lp_spr[1]);
> > +       DRM_DEBUG_KMS("WM_LP_SPR_3 = 0x%08x\n", hw->wm_lp_spr[2]);
> > +       DRM_DEBUG_KMS("WM_LINETIME_A = 0x%08x\n", hw->wm_linetime[PIPE_A]);
> > +       DRM_DEBUG_KMS("WM_LINETIME_B = 0x%08x\n", hw->wm_linetime[PIPE_B]);
> > +       DRM_DEBUG_KMS("WM_LINETIME_C = 0x%08x\n", hw->wm_linetime[PIPE_C]);
> > +       DRM_DEBUG_KMS("enable FBC watermark = %d\n", hw->enable_fbc_wm);
> > +       DRM_DEBUG_KMS("DDB partitioning = %s\n",
> > +                     hw->partitioning == INTEL_DDB_PART_1_2 ? "1/2" : "5/6");
> > +}
> > +
> >  /*
> >   * 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 ilk_write_wm_values(struct drm_i915_private *dev_priv,
> > -                               struct ilk_wm_values *results)
> > +                               const struct ilk_wm_values *results)
> >  {
> >         struct drm_device *dev = dev_priv->dev;
> >         struct ilk_wm_values *previous = &dev_priv->wm.hw;
> > +       struct ilk_wm_values hw = {};
> >         unsigned int dirty;
> >         uint32_t val;
> >
> > @@ -2602,6 +2671,14 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
> >                 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
> >
> >         dev_priv->wm.hw = *results;
> > +
> > +       _ilk_wm_get_hw_state(dev, &hw);
> > +
> > +       if (memcmp(results, &hw, sizeof(hw))) {
> > +               WARN(1, "watermark state doesn't match!\n");
> > +               ilk_dump_wm_values(&hw, "[hw state]");
> > +               ilk_dump_wm_values(results, "[sw state]");
> > +       }
> >  }
> >
> >  static bool ilk_disable_lp_wm(struct drm_device *dev)
> > @@ -2683,23 +2760,14 @@ static void ilk_update_sprite_wm(struct drm_plane *plane,
> >         ilk_update_wm(crtc);
> >  }
> >
> > -static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
> > +static void _ilk_pipe_wm_hw_to_sw(struct drm_crtc *crtc)
> >  {
> >         struct drm_device *dev = crtc->dev;
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> > -       struct ilk_wm_values *hw = &dev_priv->wm.hw;
> > +       const struct ilk_wm_values *hw = &dev_priv->wm.hw;
> >         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >         struct intel_pipe_wm *active = &intel_crtc->wm.active;
> >         enum pipe pipe = intel_crtc->pipe;
> > -       static const unsigned int wm0_pipe_reg[] = {
> > -               [PIPE_A] = WM0_PIPEA_ILK,
> > -               [PIPE_B] = WM0_PIPEB_ILK,
> > -               [PIPE_C] = WM0_PIPEC_IVB,
> > -       };
> > -
> > -       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
> > -       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > -               hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
> >
> >         active->pipe_enabled = intel_crtc_active(crtc);
> >
> > @@ -2733,31 +2801,12 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
> >  void ilk_wm_get_hw_state(struct drm_device *dev)
> >  {
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> > -       struct ilk_wm_values *hw = &dev_priv->wm.hw;
> >         struct drm_crtc *crtc;
> >
> > -       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> > -               ilk_pipe_wm_get_hw_state(crtc);
> > -
> > -       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
> > -       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
> > -       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
> > -
> > -       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> > -       if (INTEL_INFO(dev)->gen >= 7) {
> > -               hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> > -               hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> > -       }
> > +       _ilk_wm_get_hw_state(dev, &dev_priv->wm.hw);
> >
> > -       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > -               hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> > -                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> > -       else if (IS_IVYBRIDGE(dev))
> > -               hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
> > -                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> > -
> > -       hw->enable_fbc_wm =
> > -               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> > +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> > +               _ilk_pipe_wm_hw_to_sw(crtc);
> >  }
> >
> >  /**
> > --
> > 1.8.3.2
> >
> > _______________________________________________
> > 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] 71+ messages in thread

* Re: [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm
  2014-04-29 12:34         ` Paulo Zanoni
@ 2014-04-29 13:57           ` Daniel Vetter
  0 siblings, 0 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-04-29 13:57 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Tue, Apr 29, 2014 at 09:34:28AM -0300, Paulo Zanoni wrote:
> 2014-04-29 8:20 GMT-03:00 Daniel Vetter <daniel@ffwll.ch>:
> > On Tue, Apr 29, 2014 at 01:18:50PM +0200, Daniel Vetter wrote:
> >> On Mon, Apr 07, 2014 at 11:14:05AM -0300, Paulo Zanoni wrote:
> >> > 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> >> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> > >
> >> > > intel_pipe_wm will be used to track the state in different stages
> >> > > of the watermark update process. For that we need to keep a bit
> >> > > more state in intel_pipe_wm.
> >> > >
> >> > > We also need to separate the multi-pipe intel_wm_config computation
> >> > > from ilk_compute_wm_parameters() as that one deals with the future
> >> > > state, and we need the intel_wm_config to match the current hardware
> >> > > state at the time we do the watermark merging for multiple pipes.
> >> > >
> >> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >
> >> > Needs minor rebase, but looks correct.
> >>
> >> Ok in my eyes this conflict looks a bit tricky, and since I lack the
> >> insight of you two for the watermark code I'd prefer a rebased version.
> >
> > Or is this just because dinq is a bit out of sync with -nightly? In that
> > case I'm stalling on Dave to open up drm-next so that I can rebase the
> > entire shebang ...
> 
> I believe you have already applied patches 1-4 a few weeks ago. Maybe
> you're getting conflicts because you're applying already-applied
> patches? :)

Ah, that might indeed explain why the conflict looks so funny ;-)

/me puts on the idiot hat

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

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

* Re: [PATCH 08/24] drm/i915: Shuffle wait_for_vblank out of primary_enable/disable funcs
  2014-04-08 18:55     ` Ville Syrjälä
@ 2014-04-29 14:00       ` Daniel Vetter
  0 siblings, 0 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-04-29 14:00 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

On Tue, Apr 08, 2014 at 09:55:45PM +0300, Ville Syrjälä wrote:
> On Mon, Apr 07, 2014 at 05:27:41PM -0300, Paulo Zanoni wrote:
> > 2014-03-07 13:32 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >
> > > Rather than have a wait_for_vblank() in the primary plane enable/disable
> > > funcs, move the wait_for_vblank() to happen after enabling/disabling all
> > > planes.
> > 
> > Why exactly? What is improved? Are we solving a bug? What are the
> > risks? What's the problem with the current code? Did you check the
> > modeset sequence documentation of every single platform (since you
> > changed them all) to make sure this is safe?
> 
> Just another step towards getting all the planes enabled/disabled
> atomically during a modeset. I should have probably yanked it from
> this series since it shouldn't be strictly needed for the watermark
> stuff. At least I can't think of a reason now. I guess I included
> it here just to make things a bit more difficult for the new watermark
> update mechanism.
> 
> In any case there's nothing magical about the primary plane, so we
> shouldn't treat it as such. That's my excuse for this patch anyway.
> 
> > Please update the commit message with the answers.
> > 
> > Also, we should probably update the first comment of hsw_enable_ips.
> > It seems things have changed since it was written.
> 
> I thought I had. Ah no, that's part of the mmio vs. cs flip race series.
> Looks like the wait for vblank changes there will conflict with this
> stuff anyway. I'll have to revisit that series, and hopefully get it
> merged before this series so that we can ignore this patch entirely.

I'll ignore this one her for now ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v2 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes
  2014-04-28 21:42       ` Paulo Zanoni
@ 2014-04-29 14:04         ` Daniel Vetter
  0 siblings, 0 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-04-29 14:04 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Mon, Apr 28, 2014 at 06:42:50PM -0300, Paulo Zanoni wrote:
> 2014-04-28 9:58 GMT-03:00  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Becasue of the upcoming vblank interrupt driven watermark update
> 
> BecaUSe.
> 
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> > mechanism we will have use for vblank interrupts during plane
> > enabling/disabling. So don't call drm_vblank_off() until planes
> > are off, and call drm_vblank_on() just before we start to enable
> > the planes.
> >
> > v2: Pimp commit message (Paulo)
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Argh, this depends upon the drm vblank rework in the core, which is still
hanging tight in a topic branch waiting for me to polish it. I'll move
that todo up on my priority list ...

Previous patches should be merged to dinq now (except the one I've noted).
-Daniel

> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 7 ++++---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 88df4ea..8d2a31e 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -3547,6 +3547,8 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
> >         int pipe = intel_crtc->pipe;
> >         int plane = intel_crtc->plane;
> >
> > +       drm_vblank_on(dev, pipe);
> > +
> >         intel_enable_primary_plane(dev_priv, plane, pipe);
> >         intel_enable_planes(crtc);
> >         intel_crtc_update_cursor(crtc, true);
> > @@ -3557,8 +3559,6 @@ static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
> >         mutex_lock(&dev->struct_mutex);
> >         intel_update_fbc(dev);
> >         mutex_unlock(&dev->struct_mutex);
> > -
> > -       drm_vblank_on(dev, pipe);
> >  }
> >
> >  static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> > @@ -3570,7 +3570,6 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> >         int plane = intel_crtc->plane;
> >
> >         intel_crtc_wait_for_pending_flips(crtc);
> > -       drm_vblank_off(dev, pipe);
> >
> >         if (dev_priv->fbc.plane == plane)
> >                 intel_disable_fbc(dev);
> > @@ -3581,6 +3580,8 @@ static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
> >         intel_disable_planes(crtc);
> >         intel_disable_primary_plane(dev_priv, plane, pipe);
> >         intel_wait_for_vblank(dev, pipe);
> > +
> > +       drm_vblank_off(dev, pipe);
> >  }
> >
> >  static void ironlake_crtc_enable(struct drm_crtc *crtc)
> > --
> > 1.8.3.2
> >
> 
> 
> 
> -- 
> Paulo Zanoni
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH v2 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-04-28 12:53     ` [PATCH v2 " ville.syrjala
  2014-04-28 21:39       ` Paulo Zanoni
@ 2014-04-30 11:28       ` Chris Wilson
  2014-04-30 11:40         ` Ville Syrjälä
  1 sibling, 1 reply; 71+ messages in thread
From: Chris Wilson @ 2014-04-30 11:28 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Mon, Apr 28, 2014 at 03:53:25PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We won't be calling intel_enable_primary_plane() or
> intel_disable_primary_plane() with the primary plane in the
> wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.

Oh, really? That sounds very, very confident. However,
haswell_get_pipe_config() disagrees with you.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH v2 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-04-30 11:28       ` Chris Wilson
@ 2014-04-30 11:40         ` Ville Syrjälä
  2014-04-30 11:43           ` Chris Wilson
  0 siblings, 1 reply; 71+ messages in thread
From: Ville Syrjälä @ 2014-04-30 11:40 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On Wed, Apr 30, 2014 at 12:28:25PM +0100, Chris Wilson wrote:
> On Mon, Apr 28, 2014 at 03:53:25PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > We won't be calling intel_enable_primary_plane() or
> > intel_disable_primary_plane() with the primary plane in the
> > wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.
> 
> Oh, really? That sounds very, very confident. However,
> haswell_get_pipe_config() disagrees with you.

Are you saying you have a machine where the BIOS enables the pipe
but not the plane? Otherwise I don't know what get_pipe_config() has to
do with this.

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-04-30 11:40         ` Ville Syrjälä
@ 2014-04-30 11:43           ` Chris Wilson
  2014-04-30 12:34             ` Daniel Vetter
  2014-04-30 14:43             ` [PATCH] drm/i915: Make primary_enabled match the actual hardware state ville.syrjala
  0 siblings, 2 replies; 71+ messages in thread
From: Chris Wilson @ 2014-04-30 11:43 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, Apr 30, 2014 at 02:40:10PM +0300, Ville Syrjälä wrote:
> On Wed, Apr 30, 2014 at 12:28:25PM +0100, Chris Wilson wrote:
> > On Mon, Apr 28, 2014 at 03:53:25PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > We won't be calling intel_enable_primary_plane() or
> > > intel_disable_primary_plane() with the primary plane in the
> > > wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.
> > 
> > Oh, really? That sounds very, very confident. However,
> > haswell_get_pipe_config() disagrees with you.
> 
> Are you saying you have a machine where the BIOS enables the pipe
> but not the plane? Otherwise I don't know what get_pipe_config() has to
> do with this.

Yes.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH v2 07/24] drm/i915: Remove useless checks from primary enable/disable
  2014-04-30 11:43           ` Chris Wilson
@ 2014-04-30 12:34             ` Daniel Vetter
  2014-04-30 14:43             ` [PATCH] drm/i915: Make primary_enabled match the actual hardware state ville.syrjala
  1 sibling, 0 replies; 71+ messages in thread
From: Daniel Vetter @ 2014-04-30 12:34 UTC (permalink / raw)
  To: Chris Wilson, Ville Syrjälä, intel-gfx

On Wed, Apr 30, 2014 at 12:43:18PM +0100, Chris Wilson wrote:
> On Wed, Apr 30, 2014 at 02:40:10PM +0300, Ville Syrjälä wrote:
> > On Wed, Apr 30, 2014 at 12:28:25PM +0100, Chris Wilson wrote:
> > > On Mon, Apr 28, 2014 at 03:53:25PM +0300, ville.syrjala@linux.intel.com wrote:
> > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > 
> > > > We won't be calling intel_enable_primary_plane() or
> > > > intel_disable_primary_plane() with the primary plane in the
> > > > wrong state. So remove the useless DISPLAY_PLANE_ENABLE checks.
> > > 
> > > Oh, really? That sounds very, very confident. However,
> > > haswell_get_pipe_config() disagrees with you.
> > 
> > Are you saying you have a machine where the BIOS enables the pipe
> > but not the plane? Otherwise I don't know what get_pipe_config() has to
> > do with this.
> 
> Yes.

I guess we need to shovel the plane related state out of the pipe_config
into the mythical plane_config ... One issue atm is that we use the plane
bpp to decide what bpp the pipe should be driven at. And the dither
settings for it. Especially for dithering I'm a bit unclear whether we can
change that while the pipe is enabled or not ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* [PATCH] drm/i915: Make primary_enabled match the actual hardware state
  2014-04-30 11:43           ` Chris Wilson
  2014-04-30 12:34             ` Daniel Vetter
@ 2014-04-30 14:43             ` ville.syrjala
  2014-04-30 16:01               ` Chris Wilson
  1 sibling, 1 reply; 71+ messages in thread
From: ville.syrjala @ 2014-04-30 14:43 UTC (permalink / raw)
  To: intel-gfx

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

The BIOS can enable a pipe but leave the primary plane disabled. This
coflicts with out current idea of primary_enabled. Read the actual
hardware plane state and set primary_enabled appropriately.

We currently assume that primary_enabled is always true when we're about
to disable a crtc. That needs to change now as the plane may not be
enabled. So replace the relevant WARNs with early returns in
intel_{enable,disable}_primary_hw_plane().

Fixes the following warning
[    3.831602] WARNING: CPU: 0 PID: 1112 at linux/drivers/gpu/drm/i915/intel_display.c:1918 intel_disable_primary_hw_plane+0xe4/0xf0 [i915]()

which got introduced here by me:
 commit e9e39655c0c30cddc3f8c09a757678a24dd36737
 Author: Ville Syrjälä <ville.syrjala@linux.intel.com>
 Date:   Mon Apr 28 15:53:25 2014 +0300

    drm/i915: Remove useless checks from primary enable/disable

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e1e1239..4b5c2d0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1880,7 +1880,8 @@ static void intel_enable_primary_hw_plane(struct drm_i915_private *dev_priv,
 	/* If the pipe isn't enabled, we can't pump pixels and may hang */
 	assert_pipe_enabled(dev_priv, pipe);
 
-	WARN(intel_crtc->primary_enabled, "Primary plane already enabled\n");
+	if (intel_crtc->primary_enabled)
+		return;
 
 	intel_crtc->primary_enabled = true;
 
@@ -1909,7 +1910,8 @@ static void intel_disable_primary_hw_plane(struct drm_i915_private *dev_priv,
 	int reg;
 	u32 val;
 
-	WARN(!intel_crtc->primary_enabled, "Primary plane already disabled\n");
+	if (!intel_crtc->primary_enabled)
+		return;
 
 	intel_crtc->primary_enabled = false;
 
@@ -11584,6 +11586,16 @@ void i915_redisable_vga(struct drm_device *dev)
 	i915_redisable_vga_power_on(dev);
 }
 
+static bool primary_get_hw_state(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+	if (!crtc->active)
+		return false;
+
+	return I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE;
+}
+
 static void intel_modeset_readout_hw_state(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -11603,7 +11615,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 								 &crtc->config);
 
 		crtc->base.enabled = crtc->active;
-		crtc->primary_enabled = crtc->active;
+		crtc->primary_enabled = primary_get_hw_state(crtc);
 
 		DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
 			      crtc->base.base.id,
-- 
1.8.3.2

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

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

* Re: [PATCH] drm/i915: Make primary_enabled match the actual hardware state
  2014-04-30 14:43             ` [PATCH] drm/i915: Make primary_enabled match the actual hardware state ville.syrjala
@ 2014-04-30 16:01               ` Chris Wilson
  0 siblings, 0 replies; 71+ messages in thread
From: Chris Wilson @ 2014-04-30 16:01 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Apr 30, 2014 at 05:43:01PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> The BIOS can enable a pipe but leave the primary plane disabled. This
> coflicts with out current idea of primary_enabled. Read the actual
> hardware plane state and set primary_enabled appropriately.
> 
> We currently assume that primary_enabled is always true when we're about
> to disable a crtc. That needs to change now as the plane may not be
> enabled. So replace the relevant WARNs with early returns in
> intel_{enable,disable}_primary_hw_plane().
> 
> Fixes the following warning
> [    3.831602] WARNING: CPU: 0 PID: 1112 at linux/drivers/gpu/drm/i915/intel_display.c:1918 intel_disable_primary_hw_plane+0xe4/0xf0 [i915]()
> 
> which got introduced here by me:
>  commit e9e39655c0c30cddc3f8c09a757678a24dd36737
>  Author: Ville Syrjälä <ville.syrjala@linux.intel.com>
>  Date:   Mon Apr 28 15:53:25 2014 +0300
> 
>     drm/i915: Remove useless checks from primary enable/disable
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

end of thread, other threads:[~2014-04-30 16:01 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-07 16:32 [PATCH 00/24] drm/i915: Two part watermark update for ILK+ ville.syrjala
2014-03-07 16:32 ` [PATCH 01/24] drm/i915: Don't read sprite LP2+ registers on ILK/SNB ville.syrjala
2014-04-04 21:35   ` Paulo Zanoni
2014-04-05 15:19     ` Daniel Vetter
2014-03-07 16:32 ` [PATCH 02/24] drm/i915: Add some more tracked state to intel_pipe_wm ville.syrjala
2014-04-07 14:14   ` Paulo Zanoni
2014-04-29 11:18     ` Daniel Vetter
2014-04-29 11:20       ` Daniel Vetter
2014-04-29 12:34         ` Paulo Zanoni
2014-04-29 13:57           ` Daniel Vetter
2014-03-07 16:32 ` [PATCH 03/24] drm/i915: Skip watermark merging for inactive pipes ville.syrjala
2014-04-07 16:23   ` Paulo Zanoni
2014-03-07 16:32 ` [PATCH 04/24] drm/i916: Refactor WM register maximums ville.syrjala
2014-04-07 16:34   ` Paulo Zanoni
2014-04-09 12:22     ` Daniel Vetter
2014-03-07 16:32 ` [PATCH 05/24] drm/i915: Merge LP1+ watermarks in safer way ville.syrjala
2014-04-23 19:13   ` Paulo Zanoni
2014-04-23 20:28     ` Ville Syrjälä
2014-04-28 12:44     ` [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers ville.syrjala
2014-04-28 12:44       ` [PATCH v2 05.2/24] drm/i915: Merge LP1+ watermarks in safer way ville.syrjala
2014-04-28 21:35         ` Paulo Zanoni
2014-04-28 21:23       ` [PATCH 05.1/24] drm/i915: Make sure computed watermarks never overflow the registers Paulo Zanoni
2014-03-07 16:32 ` [PATCH 06/24] drm/i915: Disable/enable planes as the first/last thing during modeset on ILK+ ville.syrjala
2014-04-07 19:51   ` Paulo Zanoni
2014-04-15 21:23     ` Daniel Vetter
2014-03-07 16:32 ` [PATCH 07/24] drm/i915: Remove useless checks from primary enable/disable ville.syrjala
2014-03-07 21:29   ` Daniel Vetter
2014-03-10 11:20     ` Ville Syrjälä
2014-03-10 11:57       ` Daniel Vetter
2014-04-07 20:04         ` Paulo Zanoni
2014-04-28 12:53     ` [PATCH v2 " ville.syrjala
2014-04-28 21:39       ` Paulo Zanoni
2014-04-30 11:28       ` Chris Wilson
2014-04-30 11:40         ` Ville Syrjälä
2014-04-30 11:43           ` Chris Wilson
2014-04-30 12:34             ` Daniel Vetter
2014-04-30 14:43             ` [PATCH] drm/i915: Make primary_enabled match the actual hardware state ville.syrjala
2014-04-30 16:01               ` Chris Wilson
2014-03-07 16:32 ` [PATCH 08/24] drm/i915: Shuffle wait_for_vblank out of primary_enable/disable funcs ville.syrjala
2014-04-07 20:27   ` Paulo Zanoni
2014-04-08 18:55     ` Ville Syrjälä
2014-04-29 14:00       ` Daniel Vetter
2014-03-07 16:32 ` [PATCH 09/24] drm/i915: Keep vblank interrupts enabled while enabling/disabling planes ville.syrjala
2014-04-07 21:21   ` Paulo Zanoni
2014-04-08 18:19     ` Ville Syrjälä
2014-04-28 12:58     ` [PATCH v2 " ville.syrjala
2014-04-28 21:42       ` Paulo Zanoni
2014-04-29 14:04         ` Daniel Vetter
2014-03-07 16:32 ` [PATCH 10/24] drm/i915: Leave interrupts enabled while disabling crtcs during suspend ville.syrjala
2014-04-24 13:33   ` Daniel Vetter
2014-03-07 16:32 ` [PATCH 11/24] drm/i915: Check hw vs. sw watermark state after programming ville.syrjala
2014-04-23 21:16   ` Paulo Zanoni
2014-04-29 12:54     ` Ville Syrjälä
2014-03-07 16:32 ` [PATCH 12/24] drm/i915: Refactor ilk_validate_pipe_wm() ville.syrjala
2014-04-23 21:23   ` Paulo Zanoni
2014-03-07 16:32 ` [PATCH 13/24] drm/i915: Refactor ilk_update_wm ville.syrjala
2014-04-23 21:31   ` Paulo Zanoni
2014-03-07 16:32 ` [PATCH 14/24] drm/i915: Add dev_priv->wm.mutex ville.syrjala
2014-04-23 21:47   ` Paulo Zanoni
2014-04-24  8:07     ` Ville Syrjälä
2014-03-07 16:32 ` [PATCH 15/24] drm/i915: Add vblank based delayed watermark update mechanism ville.syrjala
2014-03-07 16:32 ` [PATCH 16/24] drm/i915: Split watermark programming into pre and post steps ville.syrjala
2014-03-07 16:32 ` [PATCH 17/24] drm/i915: Actually perform the watermark update in two phases ville.syrjala
2014-03-07 16:32 ` [PATCH 18/24] drm/i915: Wait for watermark updates to finish before disabling a pipe ville.syrjala
2014-03-07 16:32 ` [PATCH 19/24] drm/i915: Refactor get_other_active_crtc() ville.syrjala
2014-03-07 16:32 ` [PATCH 20/24] drm/i915: Disable LP1+ watermarks while changing the number of active pipes ville.syrjala
2014-03-07 16:32 ` [PATCH 21/24] drm/i915: Keep track of who disabled LP1+ watermarks ville.syrjala
2014-03-07 16:32 ` [PATCH 22/24] drm/i915: Prefer the 5/6 DDB split when primary is disabled ville.syrjala
2014-03-07 16:32 ` [PATCH 23/24] drm/i915: Add a workaround for sprite only <-> primary only switching ville.syrjala
2014-03-07 21:32   ` Daniel Vetter
2014-03-07 16:32 ` [PATCH 24/24] drm/i915: Don't disable LP1+ watermarks for every frame when scaled ville.syrjala

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.