All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks
@ 2016-12-12 20:35 ville.syrjala
  2016-12-12 20:35 ` [PATCH 01/14] drm/i915: Track visible planes in a bitmask ville.syrjala
                   ` (15 more replies)
  0 siblings, 16 replies; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

OK, so finally managed to beat the HW mostly into submission
and got the two stage watermark programming to work on VLV/CHV.

So the hardware has the following features:
* single buffered watermark registers, hence we need the two-stage programming
* inverted watermark registers, which actually makes the two-stage stuff
  easier than on ilk-bdw
* double buffered FIFO split registers, hence FIFO split changed atomically
  with the plane updates as long as we program everything within the same frame
* various ways to make things blow up. I found two new ones this time, but
  they were reasonable easy to workaround

One of the goals I had was to keep the planes as independent as possible, and
so I track the watermark and FIFO in the crtc state rather than the plane
states so that we don't need the plane locks for the other planes when only
a subset of planes is changing.

Entire series available here:
git://github.com/vsyrjala/linux.git vlv_atomic_wm_4

Ville Syrjälä (14):
  drm/i915: Track visible planes in a bitmask
  drm/i915: Track plane fifo sizes under intel_crtc
  drm/i915: Move vlv wms from crtc->wm_state to crtc->wm.active.vlv
  drm/i915: Plop vlv wm state into crtc_state
  drm/i915: Plop vlv/chv fifo sizes into crtc state
  drm/i915: Compute VLV/CHV FIFO sizes based on the PM2 watermarks
  drm/i915: Compute vlv/chv wms the atomic way
  drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not
    needed
  drm/i915: Compute proper intermediate wms for vlv/cvh
  drm/i915: Nuke crtc->wm.cxsr_allowed
  drm/i915: Only use update_wm_{pre,post} for pre-ilk platforms
  drm/i915: Sanitize VLV/CHV watermarks properly
  drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
  drm/i915: Kill level 0 wm hack for VLV/CHV

 drivers/gpu/drm/i915/i915_drv.h           |   8 +
 drivers/gpu/drm/i915/intel_atomic.c       |   1 +
 drivers/gpu/drm/i915/intel_atomic_plane.c |   6 +
 drivers/gpu/drm/i915/intel_display.c      | 175 ++++----
 drivers/gpu/drm/i915/intel_drv.h          |  46 ++-
 drivers/gpu/drm/i915/intel_pm.c           | 662 ++++++++++++++++++++----------
 6 files changed, 605 insertions(+), 293 deletions(-)

-- 
2.7.4

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

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

* [PATCH 01/14] drm/i915: Track visible planes in a bitmask
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-15 14:56   ` Maarten Lankhorst
  2016-12-12 20:35 ` [PATCH 02/14] drm/i915: Track plane fifo sizes under intel_crtc ville.syrjala
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

In a lot of place we wish to know which planes on the crtc are actually
visible, or how many of them there are. Let's start tracking that in a
bitmask in the crtc state.

We already track enabled planes (ie. ones with an fb and crtc specified by
the user) but that's not quite the same thing as enabled planes may
still end up being invisible due to clipping and whatnot.

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

diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index dbe9fb41ae53..7ec12edda4d4 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -181,6 +181,12 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
 	if (ret)
 		return ret;
 
+	/* FIXME pre-g4x don't work like this */
+	if (intel_state->base.visible)
+		crtc_state->active_planes |= BIT(intel_plane->id);
+	else
+		crtc_state->active_planes &= ~BIT(intel_plane->id);
+
 	return intel_plane_atomic_calc_changes(&crtc_state->base, state);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bc1af87789bc..3f027341b0f3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2741,6 +2741,29 @@ update_state_fb(struct drm_plane *plane)
 }
 
 static void
+intel_set_plane_visible(struct intel_crtc_state *crtc_state,
+			struct intel_plane_state *plane_state,
+			bool visible)
+{
+	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+
+	plane_state->base.visible = visible;
+
+	/* FIXME pre-g4x don't work like this */
+	if (visible) {
+		crtc_state->base.plane_mask |= BIT(drm_plane_index(&plane->base));
+		crtc_state->active_planes |= BIT(plane->id);
+	} else {
+		crtc_state->base.plane_mask &= ~BIT(drm_plane_index(&plane->base));
+		crtc_state->active_planes &= ~BIT(plane->id);
+	}
+
+	DRM_DEBUG_KMS("%s active planes 0x%x\n",
+		      crtc_state->base.crtc->name,
+		      crtc_state->active_planes);
+}
+
+static void
 intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
 			     struct intel_initial_plane_config *plane_config)
 {
@@ -2798,8 +2821,9 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
 	 * simplest solution is to just disable the primary plane now and
 	 * pretend the BIOS never had it enabled.
 	 */
-	to_intel_plane_state(plane_state)->base.visible = false;
-	crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
+	intel_set_plane_visible(to_intel_crtc_state(crtc_state),
+				to_intel_plane_state(plane_state),
+				false);
 	intel_pre_disable_primary_noatomic(&intel_crtc->base);
 	intel_plane->disable_plane(primary, &intel_crtc->base);
 
@@ -2826,7 +2850,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
 	drm_framebuffer_reference(fb);
 	primary->fb = primary->state->fb = fb;
 	primary->crtc = primary->state->crtc = &intel_crtc->base;
-	intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
+
+	intel_set_plane_visible(to_intel_crtc_state(intel_crtc->base.state),
+				to_intel_plane_state(primary->state),
+				true);
+
 	atomic_or(to_intel_plane(primary)->frontbuffer_bit,
 		  &obj->frontbuffer_bits);
 }
@@ -12440,11 +12468,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 	struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
 	struct drm_crtc *crtc = crtc_state->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_plane *plane = plane_state->plane;
+	struct intel_plane *plane = to_intel_plane(plane_state->plane);
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_plane_state *old_plane_state =
-		to_intel_plane_state(plane->state);
+		to_intel_plane_state(plane->base.state);
 	bool mode_changed = needs_modeset(crtc_state);
 	bool was_crtc_enabled = crtc->state->active;
 	bool is_crtc_enabled = crtc_state->active;
@@ -12452,7 +12480,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 	struct drm_framebuffer *fb = plane_state->fb;
 	int ret;
 
-	if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
+	if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_CURSOR) {
 		ret = skl_update_scaler_plane(
 			to_intel_crtc_state(crtc_state),
 			to_intel_plane_state(plane_state));
@@ -12476,8 +12504,10 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 	 * per-plane wm computation to the .check_plane() hook, and
 	 * only combine the results from all planes in the current place?
 	 */
-	if (!is_crtc_enabled)
+	if (!is_crtc_enabled) {
 		to_intel_plane_state(plane_state)->base.visible = visible = false;
+		to_intel_crtc_state(crtc_state)->active_planes &= ~BIT(plane->id);
+	}
 
 	if (!was_visible && !visible)
 		return 0;
@@ -12489,13 +12519,12 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 	turn_on = visible && (!was_visible || mode_changed);
 
 	DRM_DEBUG_ATOMIC("[CRTC:%d:%s] has [PLANE:%d:%s] with fb %i\n",
-			 intel_crtc->base.base.id,
-			 intel_crtc->base.name,
-			 plane->base.id, plane->name,
+			 intel_crtc->base.base.id, intel_crtc->base.name,
+			 plane->base.base.id, plane->base.name,
 			 fb ? fb->base.id : -1);
 
 	DRM_DEBUG_ATOMIC("[PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
-			 plane->base.id, plane->name,
+			 plane->base.base.id, plane->base.name,
 			 was_visible, visible,
 			 turn_off, turn_on, mode_changed);
 
@@ -12503,15 +12532,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 		pipe_config->update_wm_pre = true;
 
 		/* must disable cxsr around plane enable/disable */
-		if (plane->type != DRM_PLANE_TYPE_CURSOR)
+		if (plane->id != PLANE_CURSOR)
 			pipe_config->disable_cxsr = true;
 	} else if (turn_off) {
 		pipe_config->update_wm_post = true;
 
 		/* must disable cxsr around plane enable/disable */
-		if (plane->type != DRM_PLANE_TYPE_CURSOR)
+		if (plane->id != PLANE_CURSOR)
 			pipe_config->disable_cxsr = true;
-	} else if (intel_wm_need_update(plane, plane_state)) {
+	} else if (intel_wm_need_update(&plane->base, plane_state)) {
 		/* FIXME bollocks */
 		pipe_config->update_wm_pre = true;
 		pipe_config->update_wm_post = true;
@@ -12523,7 +12552,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 		to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
 
 	if (visible || was_visible)
-		pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit;
+		pipe_config->fb_bits |= plane->frontbuffer_bit;
 
 	/*
 	 * WaCxSRDisabledForSpriteScaling:ivb
@@ -12531,7 +12560,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 	 * cstate->update_wm was already set above, so this flag will
 	 * take effect when we commit and program watermarks.
 	 */
-	if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) &&
+	if (plane->id == PLANE_SPRITE0 && IS_IVYBRIDGE(dev_priv) &&
 	    needs_scaling(to_intel_plane_state(plane_state)) &&
 	    !needs_scaling(old_plane_state))
 		pipe_config->disable_lp_wm = true;
@@ -16876,15 +16905,14 @@ static bool primary_get_hw_state(struct intel_plane *plane)
 /* FIXME read out full plane state for all planes */
 static void readout_plane_state(struct intel_crtc *crtc)
 {
-	struct drm_plane *primary = crtc->base.primary;
-	struct intel_plane_state *plane_state =
-		to_intel_plane_state(primary->state);
+	struct intel_plane *primary = to_intel_plane(crtc->base.primary);
+	bool visible;
 
-	plane_state->base.visible = crtc->active &&
-		primary_get_hw_state(to_intel_plane(primary));
+	visible = crtc->active && primary_get_hw_state(primary);
 
-	if (plane_state->base.visible)
-		crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
+	intel_set_plane_visible(to_intel_crtc_state(crtc->base.state),
+				to_intel_plane_state(primary->base.state),
+				visible);
 }
 
 static void intel_modeset_readout_hw_state(struct drm_device *dev)
@@ -17171,7 +17199,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
 			c->primary->fb = NULL;
 			c->primary->crtc = c->primary->state->crtc = NULL;
 			update_state_fb(c->primary);
-			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
+
+			intel_set_plane_visible(to_intel_crtc_state(c->state),
+						to_intel_plane_state(c->primary->state),
+						false);
 		}
 	}
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 8f4ddca0f521..20ba8f48bc3b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -669,6 +669,9 @@ struct intel_crtc_state {
 
 	/* Gamma mode programmed on the pipe */
 	uint32_t gamma_mode;
+
+	/* bitmask of visible planes (enum plane_id) */
+	u8 active_planes;
 };
 
 struct vlv_wm_state {
-- 
2.7.4

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

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

* [PATCH 02/14] drm/i915: Track plane fifo sizes under intel_crtc
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
  2016-12-12 20:35 ` [PATCH 01/14] drm/i915: Track visible planes in a bitmask ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-15 14:58   ` Maarten Lankhorst
  2016-12-12 20:35 ` [PATCH 03/14] drm/i915: Move vlv wms from crtc->wm_state to crtc->wm.active.vlv ville.syrjala
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Track the plane fifo sizes under intel_crtc instead of under each
intel_plane. Avoids looping over the planes in a bunch of places,
and later we'll move this tracking into the crtc state properly.

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

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 20ba8f48bc3b..69b6f45e3eed 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -683,6 +683,10 @@ struct vlv_wm_state {
 	bool cxsr;
 };
 
+struct vlv_fifo_state {
+	uint16_t plane[I915_MAX_PLANES];
+};
+
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
@@ -732,6 +736,8 @@ struct intel_crtc {
 
 		/* allow CxSR on this pipe */
 		bool cxsr_allowed;
+
+		struct vlv_fifo_state fifo_state;
 	} wm;
 
 	int scanline_offset;
@@ -765,7 +771,6 @@ struct intel_plane_wm_parameters {
 	bool scaled;
 	u64 tiling;
 	unsigned int rotation;
-	uint16_t fifo_size;
 };
 
 struct intel_plane {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 06e55967f180..26af87f82608 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -393,15 +393,14 @@ static const int pessimal_latency_ns = 5000;
 #define VLV_FIFO_START(dsparb, dsparb2, lo_shift, hi_shift) \
 	((((dsparb) >> (lo_shift)) & 0xff) | ((((dsparb2) >> (hi_shift)) & 0x1) << 8))
 
-static int vlv_get_fifo_size(struct intel_plane *plane)
+static void vlv_get_fifo_size(struct intel_crtc *crtc)
 {
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	int sprite0_start, sprite1_start, size;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
+	enum pipe pipe = crtc->pipe;
+	int sprite0_start, sprite1_start;
 
-	if (plane->id == PLANE_CURSOR)
-		return 63;
-
-	switch (plane->pipe) {
+	switch (pipe) {
 		uint32_t dsparb, dsparb2, dsparb3;
 	case PIPE_A:
 		dsparb = I915_READ(DSPARB);
@@ -422,26 +421,21 @@ static int vlv_get_fifo_size(struct intel_plane *plane)
 		sprite1_start = VLV_FIFO_START(dsparb3, dsparb2, 8, 20);
 		break;
 	default:
-		return 0;
+		MISSING_CASE(pipe);
+		return;
 	}
 
-	switch (plane->id) {
-	case PLANE_PRIMARY:
-		size = sprite0_start;
-		break;
-	case PLANE_SPRITE0:
-		size = sprite1_start - sprite0_start;
-		break;
-	case PLANE_SPRITE1:
-		size = 512 - 1 - sprite1_start;
-		break;
-	default:
-		return 0;
-	}
-
-	DRM_DEBUG_KMS("%s FIFO size: %d\n", plane->base.name, size);
+	fifo_state->plane[PLANE_PRIMARY] = sprite0_start;
+	fifo_state->plane[PLANE_SPRITE0] = sprite1_start - sprite0_start;
+	fifo_state->plane[PLANE_SPRITE1] = 511 - sprite1_start;
+	fifo_state->plane[PLANE_CURSOR] = 63;
 
-	return size;
+	DRM_DEBUG_KMS("Pipe %c FIFO size: %d/%d/%d/%d\n",
+		      pipe_name(pipe),
+		      fifo_state->plane[PLANE_PRIMARY],
+		      fifo_state->plane[PLANE_SPRITE0],
+		      fifo_state->plane[PLANE_SPRITE1],
+		      fifo_state->plane[PLANE_CURSOR]);
 }
 
 static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv, int plane)
@@ -1019,8 +1013,9 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
 
 static void vlv_compute_fifo(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->base.dev;
 	struct vlv_wm_state *wm_state = &crtc->wm_state;
+	struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
+	struct drm_device *dev = crtc->base.dev;
 	struct intel_plane *plane;
 	unsigned int total_rate = 0;
 	const int fifo_size = 512 - 1;
@@ -1030,7 +1025,7 @@ static void vlv_compute_fifo(struct intel_crtc *crtc)
 		struct intel_plane_state *state =
 			to_intel_plane_state(plane->base.state);
 
-		if (plane->base.type == DRM_PLANE_TYPE_CURSOR)
+		if (plane->id == PLANE_CURSOR)
 			continue;
 
 		if (state->base.visible) {
@@ -1044,19 +1039,19 @@ static void vlv_compute_fifo(struct intel_crtc *crtc)
 			to_intel_plane_state(plane->base.state);
 		unsigned int rate;
 
-		if (plane->base.type == DRM_PLANE_TYPE_CURSOR) {
-			plane->wm.fifo_size = 63;
+		if (plane->id == PLANE_CURSOR) {
+			fifo_state->plane[plane->id] = 63;
 			continue;
 		}
 
 		if (!state->base.visible) {
-			plane->wm.fifo_size = 0;
+			fifo_state->plane[plane->id] = 0;
 			continue;
 		}
 
 		rate = drm_format_plane_cpp(state->base.fb->pixel_format, 0);
-		plane->wm.fifo_size = fifo_size * rate / total_rate;
-		fifo_left -= plane->wm.fifo_size;
+		fifo_state->plane[plane->id] = fifo_size * rate / total_rate;
+		fifo_left -= fifo_state->plane[plane->id];
 	}
 
 	fifo_extra = DIV_ROUND_UP(fifo_left, wm_state->num_active_planes ?: 1);
@@ -1068,16 +1063,16 @@ static void vlv_compute_fifo(struct intel_crtc *crtc)
 		if (fifo_left == 0)
 			break;
 
-		if (plane->base.type == DRM_PLANE_TYPE_CURSOR)
+		if (plane->id == PLANE_CURSOR)
 			continue;
 
 		/* give it all to the first plane if none are active */
-		if (plane->wm.fifo_size == 0 &&
+		if (fifo_state->plane[plane->id] == 0 &&
 		    wm_state->num_active_planes)
 			continue;
 
 		plane_extra = min(fifo_extra, fifo_left);
-		plane->wm.fifo_size += plane_extra;
+		fifo_state->plane[plane->id] += plane_extra;
 		fifo_left -= plane_extra;
 	}
 
@@ -1099,9 +1094,10 @@ static void vlv_invert_wms(struct intel_crtc *crtc)
 
 	for (level = 0; level < wm_state->num_levels; level++) {
 		struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+		const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
 		const int sr_fifo_size =
 			INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
-		struct intel_plane *plane;
+		enum plane_id plane_id;
 
 		wm_state->sr[level].plane =
 			vlv_invert_wm_value(wm_state->sr[level].plane,
@@ -1110,10 +1106,10 @@ static void vlv_invert_wms(struct intel_crtc *crtc)
 			vlv_invert_wm_value(wm_state->sr[level].cursor,
 					    63);
 
-		for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
-			wm_state->wm[level].plane[plane->id] =
-				vlv_invert_wm_value(wm_state->wm[level].plane[plane->id],
-						    plane->wm.fifo_size);
+		for_each_plane_id_on_crtc(crtc, plane_id) {
+			wm_state->wm[level].plane[plane_id] =
+				vlv_invert_wm_value(wm_state->wm[level].plane[plane_id],
+						    fifo_state->plane[plane_id]);
 		}
 	}
 }
@@ -1122,6 +1118,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct vlv_wm_state *wm_state = &crtc->wm_state;
+	const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
 	struct intel_plane *plane;
 	int level;
 
@@ -1148,7 +1145,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
 		/* normal watermarks */
 		for (level = 0; level < wm_state->num_levels; level++) {
 			int wm = vlv_compute_wm_level(crtc->config, state, level);
-			int max_wm = plane->wm.fifo_size;
+			int max_wm = fifo_state->plane[plane->id];
 
 			/* hack */
 			if (WARN_ON(level == 0 && wm > max_wm))
@@ -1192,32 +1189,16 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
 
 static void vlv_pipe_set_fifo_size(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_plane *plane;
-	int sprite0_start = 0, sprite1_start = 0, fifo_size = 0;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
+	int sprite0_start, sprite1_start, fifo_size;
 
-	for_each_intel_plane_on_crtc(dev, crtc, plane) {
-		switch (plane->id) {
-		case PLANE_PRIMARY:
-			sprite0_start = plane->wm.fifo_size;
-			break;
-		case PLANE_SPRITE0:
-			sprite1_start = sprite0_start + plane->wm.fifo_size;
-			break;
-		case PLANE_SPRITE1:
-			fifo_size = sprite1_start + plane->wm.fifo_size;
-			break;
-		case PLANE_CURSOR:
-			WARN_ON(plane->wm.fifo_size != 63);
-			break;
-		default:
-			MISSING_CASE(plane->id);
-			break;
-		}
-	}
+	sprite0_start = fifo_state->plane[PLANE_PRIMARY];
+	sprite1_start = fifo_state->plane[PLANE_SPRITE0] + sprite0_start;
+	fifo_size = fifo_state->plane[PLANE_SPRITE1] + sprite1_start;
 
-	WARN_ON(fifo_size != 512 - 1);
+	WARN_ON(fifo_state->plane[PLANE_CURSOR] != 63);
+	WARN_ON(fifo_size != 511);
 
 	DRM_DEBUG_KMS("Pipe %c FIFO split %d / %d / %d\n",
 		      pipe_name(crtc->pipe), sprite0_start,
@@ -4532,14 +4513,14 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct vlv_wm_values *wm = &dev_priv->wm.vlv;
-	struct intel_plane *plane;
+	struct intel_crtc *crtc;
 	enum pipe pipe;
 	u32 val;
 
 	vlv_read_wm_values(dev_priv, wm);
 
-	for_each_intel_plane(dev, plane)
-		plane->wm.fifo_size = vlv_get_fifo_size(plane);
+	for_each_intel_crtc(dev, crtc)
+		vlv_get_fifo_size(crtc);
 
 	wm->cxsr = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 	wm->level = VLV_WM_LEVEL_PM2;
-- 
2.7.4

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

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

* [PATCH 03/14] drm/i915: Move vlv wms from crtc->wm_state to crtc->wm.active.vlv
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
  2016-12-12 20:35 ` [PATCH 01/14] drm/i915: Track visible planes in a bitmask ville.syrjala
  2016-12-12 20:35 ` [PATCH 02/14] drm/i915: Track plane fifo sizes under intel_crtc ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-12 20:35 ` [PATCH 04/14] drm/i915: Plop vlv wm state into crtc_state ville.syrjala
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

In an effort to make the vlv/chv wm code look and behave more like the
ilk+ code, let's move the current active wms next to the
corresponding ilk wms.

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  | 10 +++++-----
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 69b6f45e3eed..db3089b383a6 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -732,6 +732,7 @@ struct intel_crtc {
 		/* watermarks currently being used  */
 		union {
 			struct intel_pipe_wm ilk;
+			struct vlv_wm_state vlv;
 		} active;
 
 		/* allow CxSR on this pipe */
@@ -751,8 +752,6 @@ struct intel_crtc {
 
 	/* scalers available on this crtc */
 	int num_scalers;
-
-	struct vlv_wm_state wm_state;
 };
 
 struct intel_plane_wm_parameters {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 26af87f82608..d5b08d9ef180 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1013,7 +1013,7 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
 
 static void vlv_compute_fifo(struct intel_crtc *crtc)
 {
-	struct vlv_wm_state *wm_state = &crtc->wm_state;
+	struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
 	struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
 	struct drm_device *dev = crtc->base.dev;
 	struct intel_plane *plane;
@@ -1089,7 +1089,7 @@ static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
 
 static void vlv_invert_wms(struct intel_crtc *crtc)
 {
-	struct vlv_wm_state *wm_state = &crtc->wm_state;
+	struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
 	int level;
 
 	for (level = 0; level < wm_state->num_levels; level++) {
@@ -1117,7 +1117,7 @@ static void vlv_invert_wms(struct intel_crtc *crtc)
 static void vlv_compute_wm(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	struct vlv_wm_state *wm_state = &crtc->wm_state;
+	struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
 	const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
 	struct intel_plane *plane;
 	int level;
@@ -1280,7 +1280,7 @@ static void vlv_merge_wm(struct drm_i915_private *dev_priv,
 	wm->cxsr = true;
 
 	for_each_intel_crtc(&dev_priv->drm, crtc) {
-		const struct vlv_wm_state *wm_state = &crtc->wm_state;
+		const struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
 
 		if (!crtc->active)
 			continue;
@@ -1299,7 +1299,7 @@ static void vlv_merge_wm(struct drm_i915_private *dev_priv,
 		wm->level = VLV_WM_LEVEL_PM2;
 
 	for_each_intel_crtc(&dev_priv->drm, crtc) {
-		struct vlv_wm_state *wm_state = &crtc->wm_state;
+		const struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
 		enum pipe pipe = crtc->pipe;
 
 		if (!crtc->active)
-- 
2.7.4

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

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

* [PATCH 04/14] drm/i915: Plop vlv wm state into crtc_state
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (2 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 03/14] drm/i915: Move vlv wms from crtc->wm_state to crtc->wm.active.vlv ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-12 20:35 ` [PATCH 05/14] drm/i915: Plop vlv/chv fifo sizes into crtc state ville.syrjala
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Relocate the vlv/chv wm state to live under intel_crtc_state. Note
that for now this just behaves as a temporary storage. But it'll be
easier to conver the thing over to properly pre-computing the state
when it's already in the right place.

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

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index db3089b383a6..63f1b59ef90f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -480,6 +480,22 @@ struct skl_pipe_wm {
 	uint32_t linetime;
 };
 
+enum vlv_wm_level {
+	VLV_WM_LEVEL_PM2,
+	VLV_WM_LEVEL_PM5,
+	VLV_WM_LEVEL_DDR_DVFS,
+	NUM_VLV_WM_LEVELS,
+};
+
+struct vlv_wm_state {
+	struct vlv_pipe_wm wm[NUM_VLV_WM_LEVELS];
+	struct vlv_sr_wm sr[NUM_VLV_WM_LEVELS];
+	uint8_t num_active_planes;
+	uint8_t num_levels;
+	uint8_t level;
+	bool cxsr;
+};
+
 struct intel_crtc_wm_state {
 	union {
 		struct {
@@ -504,6 +520,11 @@ struct intel_crtc_wm_state {
 			struct skl_pipe_wm optimal;
 			struct skl_ddb_entry ddb;
 		} skl;
+
+		struct {
+			/* inverted optimal watermarks */
+			struct vlv_wm_state optimal;
+		} vlv;
 	};
 
 	/*
@@ -674,15 +695,6 @@ struct intel_crtc_state {
 	u8 active_planes;
 };
 
-struct vlv_wm_state {
-	struct vlv_pipe_wm wm[3];
-	struct vlv_sr_wm sr[3];
-	uint8_t num_active_planes;
-	uint8_t num_levels;
-	uint8_t level;
-	bool cxsr;
-};
-
 struct vlv_fifo_state {
 	uint16_t plane[I915_MAX_PLANES];
 };
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d5b08d9ef180..3e421dea03b4 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -935,12 +935,6 @@ static void vlv_write_wm_values(struct drm_i915_private *dev_priv,
 
 #undef FW_WM_VLV
 
-enum vlv_wm_level {
-	VLV_WM_LEVEL_PM2,
-	VLV_WM_LEVEL_PM5,
-	VLV_WM_LEVEL_DDR_DVFS,
-};
-
 /* latency must be in 0.1us units. */
 static unsigned int vlv_wm_method2(unsigned int pixel_rate,
 				   unsigned int pipe_htotal,
@@ -1011,9 +1005,10 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
 	return min_t(int, wm, USHRT_MAX);
 }
 
-static void vlv_compute_fifo(struct intel_crtc *crtc)
+static void vlv_compute_fifo(struct intel_crtc_state *crtc_state)
 {
-	struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
 	struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
 	struct drm_device *dev = crtc->base.dev;
 	struct intel_plane *plane;
@@ -1087,9 +1082,10 @@ static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
 		return fifo_size - wm;
 }
 
-static void vlv_invert_wms(struct intel_crtc *crtc)
+static void vlv_invert_wms(struct intel_crtc_state *crtc_state)
 {
-	struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
 	int level;
 
 	for (level = 0; level < wm_state->num_levels; level++) {
@@ -1114,10 +1110,11 @@ static void vlv_invert_wms(struct intel_crtc *crtc)
 	}
 }
 
-static void vlv_compute_wm(struct intel_crtc *crtc)
+static void vlv_compute_wm(struct intel_crtc_state *crtc_state)
 {
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
+	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
 	const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
 	struct intel_plane *plane;
 	int level;
@@ -1129,7 +1126,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
 
 	wm_state->num_active_planes = 0;
 
-	vlv_compute_fifo(crtc);
+	vlv_compute_fifo(crtc_state);
 
 	if (wm_state->num_active_planes != 1)
 		wm_state->cxsr = false;
@@ -1144,7 +1141,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
 
 		/* normal watermarks */
 		for (level = 0; level < wm_state->num_levels; level++) {
-			int wm = vlv_compute_wm_level(crtc->config, state, level);
+			int wm = vlv_compute_wm_level(crtc_state, state, level);
 			int max_wm = fifo_state->plane[plane->id];
 
 			/* hack */
@@ -1181,7 +1178,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
 		memset(&wm_state->sr[level], 0, sizeof(wm_state->sr[level]));
 	}
 
-	vlv_invert_wms(crtc);
+	vlv_invert_wms(crtc_state);
 }
 
 #define VLV_FIFO(plane, value) \
@@ -1329,11 +1326,14 @@ static bool is_enabling(int old, int new, int threshold)
 static void vlv_update_wm(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct intel_crtc_state *crtc_state =
+		to_intel_crtc_state(crtc->base.state);
 	enum pipe pipe = crtc->pipe;
 	struct vlv_wm_values *old_wm = &dev_priv->wm.vlv;
 	struct vlv_wm_values new_wm = {};
 
-	vlv_compute_wm(crtc);
+	vlv_compute_wm(crtc_state);
+	crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
 	vlv_merge_wm(dev_priv, &new_wm);
 
 	if (memcmp(old_wm, &new_wm, sizeof(new_wm)) == 0) {
-- 
2.7.4

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

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

* [PATCH 05/14] drm/i915: Plop vlv/chv fifo sizes into crtc state
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (3 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 04/14] drm/i915: Plop vlv wm state into crtc_state ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-12 20:35 ` [PATCH 06/14] drm/i915: Compute VLV/CHV FIFO sizes based on the PM2 watermarks ville.syrjala
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Move the vlv/chv FIFO size tracking into the crtc_state. As with the wms
for now this just acts as temporary storage.

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

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 63f1b59ef90f..ebe1f797e9d1 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -496,6 +496,10 @@ struct vlv_wm_state {
 	bool cxsr;
 };
 
+struct vlv_fifo_state {
+	u16 plane[I915_MAX_PLANES];
+};
+
 struct intel_crtc_wm_state {
 	union {
 		struct {
@@ -522,6 +526,7 @@ struct intel_crtc_wm_state {
 		} skl;
 
 		struct {
+			struct vlv_fifo_state fifo_state;
 			/* inverted optimal watermarks */
 			struct vlv_wm_state optimal;
 		} vlv;
@@ -695,10 +700,6 @@ struct intel_crtc_state {
 	u8 active_planes;
 };
 
-struct vlv_fifo_state {
-	uint16_t plane[I915_MAX_PLANES];
-};
-
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
@@ -749,8 +750,6 @@ struct intel_crtc {
 
 		/* allow CxSR on this pipe */
 		bool cxsr_allowed;
-
-		struct vlv_fifo_state fifo_state;
 	} wm;
 
 	int scanline_offset;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 3e421dea03b4..56ec9bfe760e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -393,10 +393,11 @@ static const int pessimal_latency_ns = 5000;
 #define VLV_FIFO_START(dsparb, dsparb2, lo_shift, hi_shift) \
 	((((dsparb) >> (lo_shift)) & 0xff) | ((((dsparb2) >> (hi_shift)) & 0x1) << 8))
 
-static void vlv_get_fifo_size(struct intel_crtc *crtc)
+static void vlv_get_fifo_size(struct intel_crtc_state *crtc_state)
 {
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
+	struct vlv_fifo_state *fifo_state = &crtc_state->wm.vlv.fifo_state;
 	enum pipe pipe = crtc->pipe;
 	int sprite0_start, sprite1_start;
 
@@ -1009,7 +1010,7 @@ static void vlv_compute_fifo(struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
-	struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
+	struct vlv_fifo_state *fifo_state = &crtc_state->wm.vlv.fifo_state;
 	struct drm_device *dev = crtc->base.dev;
 	struct intel_plane *plane;
 	unsigned int total_rate = 0;
@@ -1086,11 +1087,12 @@ static void vlv_invert_wms(struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
+	const struct vlv_fifo_state *fifo_state =
+		&crtc_state->wm.vlv.fifo_state;
 	int level;
 
 	for (level = 0; level < wm_state->num_levels; level++) {
 		struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-		const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
 		const int sr_fifo_size =
 			INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
 		enum plane_id plane_id;
@@ -1115,7 +1117,8 @@ static void vlv_compute_wm(struct intel_crtc_state *crtc_state)
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
-	const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
+	const struct vlv_fifo_state *fifo_state =
+		&crtc_state->wm.vlv.fifo_state;
 	struct intel_plane *plane;
 	int level;
 
@@ -1184,10 +1187,12 @@ static void vlv_compute_wm(struct intel_crtc_state *crtc_state)
 #define VLV_FIFO(plane, value) \
 	(((value) << DSPARB_ ## plane ## _SHIFT_VLV) & DSPARB_ ## plane ## _MASK_VLV)
 
-static void vlv_pipe_set_fifo_size(struct intel_crtc *crtc)
+static void vlv_pipe_set_fifo_size(const struct intel_crtc_state *crtc_state)
 {
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
+	const struct vlv_fifo_state *fifo_state =
+		&crtc_state->wm.vlv.fifo_state;
 	int sprite0_start, sprite1_start, fifo_size;
 
 	sprite0_start = fifo_state->plane[PLANE_PRIMARY];
@@ -1338,8 +1343,7 @@ static void vlv_update_wm(struct intel_crtc *crtc)
 
 	if (memcmp(old_wm, &new_wm, sizeof(new_wm)) == 0) {
 		/* FIXME should be part of crtc atomic commit */
-		vlv_pipe_set_fifo_size(crtc);
-
+		vlv_pipe_set_fifo_size(crtc_state);
 		return;
 	}
 
@@ -1353,7 +1357,7 @@ static void vlv_update_wm(struct intel_crtc *crtc)
 		_intel_set_memory_cxsr(dev_priv, false);
 
 	/* FIXME should be part of crtc atomic commit */
-	vlv_pipe_set_fifo_size(crtc);
+	vlv_pipe_set_fifo_size(crtc_state);
 
 	vlv_write_wm_values(dev_priv, &new_wm);
 
@@ -4520,7 +4524,7 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 	vlv_read_wm_values(dev_priv, wm);
 
 	for_each_intel_crtc(dev, crtc)
-		vlv_get_fifo_size(crtc);
+		vlv_get_fifo_size(to_intel_crtc_state(crtc->base.state));
 
 	wm->cxsr = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 	wm->level = VLV_WM_LEVEL_PM2;
-- 
2.7.4

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

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

* [PATCH 06/14] drm/i915: Compute VLV/CHV FIFO sizes based on the PM2 watermarks
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (4 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 05/14] drm/i915: Plop vlv/chv fifo sizes into crtc state ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-12 20:35 ` [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way ville.syrjala
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Let's compute the watermarks first and the FIFO size second. This way we
can make sure the FIFO split is the most accommodating to the watermarks.
Previously we could have potentially computed a FIFO split that couldn't
accommodate the PM2 watermarks simply due to a bad split even if the
total FIFO size would have been sufficient.

It'll also allow us to avoid recomputing the wms for all planes whenever
the FIFO split would change. Thus we don't have to add any extra planes
to the state when the FIFO needs to be repartitioned.

To help with this we'll keep around copies of the non-inverted
watermarks in the crtc state. For now that doesn't help too much, but
once we start to do the watermark computation only for the planes
that change we'll need the non-inverted values around for the other
planes.

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

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ebe1f797e9d1..0e199db26bda 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -526,6 +526,8 @@ struct intel_crtc_wm_state {
 		} skl;
 
 		struct {
+			/* non-inverted optimal watermarks */
+			struct vlv_pipe_wm noninverted[NUM_VLV_WM_LEVELS];
 			struct vlv_fifo_state fifo_state;
 			/* inverted optimal watermarks */
 			struct vlv_wm_state optimal;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 56ec9bfe760e..233e63224649 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1006,73 +1006,70 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
 	return min_t(int, wm, USHRT_MAX);
 }
 
-static void vlv_compute_fifo(struct intel_crtc_state *crtc_state)
+static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
-	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
+	const struct vlv_pipe_wm *noninverted =
+		&crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2];
 	struct vlv_fifo_state *fifo_state = &crtc_state->wm.vlv.fifo_state;
-	struct drm_device *dev = crtc->base.dev;
-	struct intel_plane *plane;
-	unsigned int total_rate = 0;
-	const int fifo_size = 512 - 1;
+	unsigned int active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
+	int num_active_planes = hweight32(active_planes);
+	const int fifo_size = 511;
 	int fifo_extra, fifo_left = fifo_size;
+	unsigned int total_rate;
+	enum plane_id plane_id;
 
-	for_each_intel_plane_on_crtc(dev, crtc, plane) {
-		struct intel_plane_state *state =
-			to_intel_plane_state(plane->base.state);
+	total_rate = noninverted->plane[PLANE_PRIMARY] +
+		noninverted->plane[PLANE_SPRITE0] +
+		noninverted->plane[PLANE_SPRITE1];
 
-		if (plane->id == PLANE_CURSOR)
-			continue;
+	if (total_rate > fifo_size)
+		return -EINVAL;
 
-		if (state->base.visible) {
-			wm_state->num_active_planes++;
-			total_rate += drm_format_plane_cpp(state->base.fb->pixel_format, 0);
-		}
-	}
+	if (total_rate == 0)
+		total_rate = 1;
 
-	for_each_intel_plane_on_crtc(dev, crtc, plane) {
-		struct intel_plane_state *state =
-			to_intel_plane_state(plane->base.state);
+	for_each_plane_id_on_crtc(crtc, plane_id) {
 		unsigned int rate;
 
-		if (plane->id == PLANE_CURSOR) {
-			fifo_state->plane[plane->id] = 63;
+		if ((active_planes & BIT(plane_id)) == 0) {
+			fifo_state->plane[plane_id] = 0;
 			continue;
 		}
 
-		if (!state->base.visible) {
-			fifo_state->plane[plane->id] = 0;
-			continue;
-		}
-
-		rate = drm_format_plane_cpp(state->base.fb->pixel_format, 0);
-		fifo_state->plane[plane->id] = fifo_size * rate / total_rate;
-		fifo_left -= fifo_state->plane[plane->id];
+		rate = noninverted->plane[plane_id];
+		fifo_state->plane[plane_id] = fifo_size * rate / total_rate;
+		fifo_left -= fifo_state->plane[plane_id];
 	}
 
-	fifo_extra = DIV_ROUND_UP(fifo_left, wm_state->num_active_planes ?: 1);
+	fifo_state->plane[PLANE_CURSOR] = 63;
+
+	fifo_extra = DIV_ROUND_UP(fifo_left, num_active_planes ?: 1);
 
 	/* spread the remainder evenly */
-	for_each_intel_plane_on_crtc(dev, crtc, plane) {
+	for_each_plane_id_on_crtc(crtc, plane_id) {
 		int plane_extra;
 
 		if (fifo_left == 0)
 			break;
 
-		if (plane->id == PLANE_CURSOR)
-			continue;
-
-		/* give it all to the first plane if none are active */
-		if (fifo_state->plane[plane->id] == 0 &&
-		    wm_state->num_active_planes)
+		if ((active_planes & BIT(plane_id)) == 0)
 			continue;
 
 		plane_extra = min(fifo_extra, fifo_left);
-		fifo_state->plane[plane->id] += plane_extra;
+		fifo_state->plane[plane_id] += plane_extra;
 		fifo_left -= plane_extra;
 	}
 
-	WARN_ON(fifo_left != 0);
+	WARN_ON(active_planes != 0 && fifo_left != 0);
+
+	/* give it all to the first plane if none are active */
+	if (active_planes == 0) {
+		WARN_ON(fifo_left != fifo_size);
+		fifo_state->plane[PLANE_PRIMARY] = fifo_left;
+	}
+
+	return 0;
 }
 
 static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
@@ -1117,35 +1114,33 @@ static void vlv_compute_wm(struct intel_crtc_state *crtc_state)
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
-	const struct vlv_fifo_state *fifo_state =
-		&crtc_state->wm.vlv.fifo_state;
 	struct intel_plane *plane;
 	int level;
 
 	memset(wm_state, 0, sizeof(*wm_state));
+	memset(crtc_state->wm.vlv.noninverted, 0,
+	       sizeof(crtc_state->wm.vlv.noninverted));
 
 	wm_state->cxsr = crtc->pipe != PIPE_C && crtc->wm.cxsr_allowed;
 	wm_state->num_levels = dev_priv->wm.max_level + 1;
 
 	wm_state->num_active_planes = 0;
 
-	vlv_compute_fifo(crtc_state);
-
 	if (wm_state->num_active_planes != 1)
 		wm_state->cxsr = false;
 
 	for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
 		struct intel_plane_state *state =
 			to_intel_plane_state(plane->base.state);
-		int level;
 
 		if (!state->base.visible)
 			continue;
 
-		/* normal watermarks */
 		for (level = 0; level < wm_state->num_levels; level++) {
+			struct vlv_pipe_wm *noninverted =
+				&crtc_state->wm.vlv.noninverted[level];
 			int wm = vlv_compute_wm_level(crtc_state, state, level);
-			int max_wm = fifo_state->plane[plane->id];
+			int max_wm = plane->id == PLANE_CURSOR ? 63 : 511;
 
 			/* hack */
 			if (WARN_ON(level == 0 && wm > max_wm))
@@ -1154,25 +1149,24 @@ static void vlv_compute_wm(struct intel_crtc_state *crtc_state)
 			if (wm > max_wm)
 				break;
 
-			wm_state->wm[level].plane[plane->id] = wm;
+			noninverted->plane[plane->id] = wm;
 		}
 
 		wm_state->num_levels = level;
+	}
 
-		if (!wm_state->cxsr)
-			continue;
-
-		/* maxfifo watermarks */
-		if (plane->id == PLANE_CURSOR) {
-			for (level = 0; level < wm_state->num_levels; level++)
-				wm_state->sr[level].cursor =
-					wm_state->wm[level].plane[PLANE_CURSOR];
-		} else {
-			for (level = 0; level < wm_state->num_levels; level++)
-				wm_state->sr[level].plane =
-					max(wm_state->sr[level].plane,
-					    wm_state->wm[level].plane[plane->id]);
-		}
+	vlv_compute_fifo(crtc_state);
+
+	for (level = 0; level < wm_state->num_levels; level++) {
+		struct vlv_pipe_wm *noninverted =
+			&crtc_state->wm.vlv.noninverted[level];
+
+		wm_state->wm[level] = *noninverted;
+
+		wm_state->sr[level].plane = max3(noninverted->plane[PLANE_PRIMARY],
+						 noninverted->plane[PLANE_SPRITE0],
+						 noninverted->plane[PLANE_SPRITE1]);
+		wm_state->sr[level].cursor = noninverted->plane[PLANE_CURSOR];
 	}
 
 	/* clear any (partially) filled invalid levels */
-- 
2.7.4

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

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

* [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (5 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 06/14] drm/i915: Compute VLV/CHV FIFO sizes based on the PM2 watermarks ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-15 15:30   ` Maarten Lankhorst
  2016-12-12 20:35 ` [PATCH 08/14] drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not needed ville.syrjala
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Start computing the vlv/chv watermarks the atomic way, from the
.compute_pipe_wm() hook. We'll recompute the actual watermarks
for only planes that are part of the state, the other planes will
keep their watermark from the last time it was computed.

And the actual watermark programming will happen from the
.initial_watermarks() hook. For now we'll just compute the
optimal watermarks, and we'll hook up the intermediate
watermarks properly later.

The DSPARB registers responsible for the FIFO paritioning are
double buffered, so they will be programming from
intel_begin_crtc_commit().

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

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 20bc04d5e617..f23698f99685 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -493,6 +493,14 @@ struct i915_hotplug {
 	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
 		for_each_if ((1 << (domain)) & (mask))
 
+#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \
+	for ((__i) = 0; \
+	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
+		     ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
+		      (plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \
+	     (__i)++) \
+		for_each_if (plane_state)
+
 struct drm_i915_private;
 struct i915_mm_struct;
 struct i915_mmu_object;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3f027341b0f3..8d80873b6643 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6736,6 +6736,8 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
 				   struct drm_atomic_state *old_state)
 {
+	struct intel_atomic_state *old_intel_state =
+		to_intel_atomic_state(old_state);
 	struct drm_crtc *crtc = pipe_config->base.crtc;
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
@@ -6780,7 +6782,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
 
 	intel_color_load_luts(&pipe_config->base);
 
-	intel_update_watermarks(intel_crtc);
+	dev_priv->display.initial_watermarks(old_intel_state,
+					     pipe_config);
 	intel_enable_pipe(intel_crtc);
 
 	assert_vblank_disabled(crtc);
@@ -6897,6 +6900,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
 
 	if (!IS_GEN2(dev_priv))
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+
+	if (!dev_priv->display.initial_watermarks)
+		intel_update_watermarks(intel_crtc);
 }
 
 static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
@@ -12980,10 +12986,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 static void
 clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
 {
+	struct drm_i915_private *dev_priv =
+		to_i915(crtc_state->base.crtc->dev);
 	struct drm_crtc_state tmp_state;
 	struct intel_crtc_scaler_state scaler_state;
 	struct intel_dpll_hw_state dpll_hw_state;
 	struct intel_shared_dpll *shared_dpll;
+	struct intel_crtc_wm_state wm_state;
 	bool force_thru;
 
 	/* FIXME: before the switch to atomic started, a new pipe_config was
@@ -12996,6 +13005,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
 	shared_dpll = crtc_state->shared_dpll;
 	dpll_hw_state = crtc_state->dpll_hw_state;
 	force_thru = crtc_state->pch_pfit.force_thru;
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		wm_state = crtc_state->wm;
 
 	memset(crtc_state, 0, sizeof *crtc_state);
 
@@ -13004,6 +13015,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
 	crtc_state->shared_dpll = shared_dpll;
 	crtc_state->dpll_hw_state = dpll_hw_state;
 	crtc_state->pch_pfit.force_thru = force_thru;
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		crtc_state->wm = wm_state;
 }
 
 static int
@@ -14497,12 +14510,12 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 				/*
 				 * Make sure we don't call initial_watermarks
 				 * for ILK-style watermark updates.
+				 *
+				 * No clue what this is supposed to achieve.
 				 */
-				if (dev_priv->display.atomic_update_watermarks)
+				if (INTEL_GEN(dev_priv) >= 9)
 					dev_priv->display.initial_watermarks(intel_state,
 									     to_intel_crtc_state(crtc->state));
-				else
-					intel_update_watermarks(intel_crtc);
 			}
 		}
 	}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0e199db26bda..66668c18a47a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -490,9 +490,7 @@ enum vlv_wm_level {
 struct vlv_wm_state {
 	struct vlv_pipe_wm wm[NUM_VLV_WM_LEVELS];
 	struct vlv_sr_wm sr[NUM_VLV_WM_LEVELS];
-	uint8_t num_active_planes;
 	uint8_t num_levels;
-	uint8_t level;
 	bool cxsr;
 };
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 233e63224649..f68b46eed224 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1072,6 +1072,28 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
 	return 0;
 }
 
+static int vlv_num_wm_levels(struct drm_i915_private *dev_priv)
+{
+	return dev_priv->wm.max_level + 1;
+}
+
+/* mark all levels starting from 'level' as invalid */
+static void vlv_invalidate_wms(struct intel_crtc *crtc,
+			       struct vlv_wm_state *wm_state, int level)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+	for (; level < vlv_num_wm_levels(dev_priv); level++) {
+		enum plane_id plane_id;
+
+		for_each_plane_id_on_crtc(crtc, plane_id)
+			wm_state->wm[level].plane[plane_id] = USHRT_MAX;
+
+		wm_state->sr[level].cursor = USHRT_MAX;
+		wm_state->sr[level].plane = USHRT_MAX;
+	}
+}
+
 static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
 {
 	if (wm > fifo_size)
@@ -1080,108 +1102,162 @@ static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
 		return fifo_size - wm;
 }
 
-static void vlv_invert_wms(struct intel_crtc_state *crtc_state)
+/* starting from 'level' set all higher levels to 'value' */
+static void vlv_plane_wm_set(struct intel_crtc_state *crtc_state,
+			     int level, enum plane_id plane_id, u16 value)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+	int num_levels = vlv_num_wm_levels(dev_priv);
+
+	for (; level < num_levels; level++) {
+		struct vlv_pipe_wm *noninverted =
+			&crtc_state->wm.vlv.noninverted[level];
+
+		noninverted->plane[plane_id] = value;
+	}
+}
+
+static void vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
+				 const struct intel_plane_state *plane_state)
+{
+	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+	enum plane_id plane_id = plane->id;
+	int num_levels = vlv_num_wm_levels(to_i915(plane->base.dev));
+	int level;
+
+	if (!plane_state->base.visible) {
+		vlv_plane_wm_set(crtc_state, 0, plane_id, 0);
+		return;
+	}
+
+	for (level = 0; level < num_levels; level++) {
+		struct vlv_pipe_wm *noninverted =
+			&crtc_state->wm.vlv.noninverted[level];
+		int wm = vlv_compute_wm_level(crtc_state, plane_state, level);
+		int max_wm = plane_id == PLANE_CURSOR ? 63 : 511;
+
+		/* FIXME just bail */
+		if (WARN_ON(level == 0 && wm > max_wm))
+			wm = max_wm;
+
+		if (wm > max_wm)
+			break;
+
+		noninverted->plane[plane_id] = wm;
+	}
+
+	/* mark all higher levels as invalid */
+	vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
+
+	DRM_DEBUG_KMS("%s wms: [0]=%d,[1]=%d,[2]=%d\n",
+		      plane->base.name,
+		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2].plane[plane_id],
+		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM5].plane[plane_id],
+		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_DDR_DVFS].plane[plane_id]);
+}
+
+static bool vlv_plane_wm_is_valid(const struct intel_crtc_state *crtc_state,
+				  enum plane_id plane_id, int level)
+{
+	const struct vlv_pipe_wm *noninverted =
+		&crtc_state->wm.vlv.noninverted[level];
+	const struct vlv_fifo_state *fifo_state =
+		&crtc_state->wm.vlv.fifo_state;
+
+	return noninverted->plane[plane_id] <= fifo_state->plane[plane_id];
+}
+
+static bool vlv_crtc_wm_is_valid(const struct intel_crtc_state *crtc_state, int level)
+{
+	return vlv_plane_wm_is_valid(crtc_state, PLANE_PRIMARY, level) &&
+		vlv_plane_wm_is_valid(crtc_state, PLANE_SPRITE0, level) &&
+		vlv_plane_wm_is_valid(crtc_state, PLANE_SPRITE1, level) &&
+		vlv_plane_wm_is_valid(crtc_state, PLANE_CURSOR, level);
+}
+
+static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct intel_atomic_state *state =
+		to_intel_atomic_state(crtc_state->base.state);
 	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
 	const struct vlv_fifo_state *fifo_state =
 		&crtc_state->wm.vlv.fifo_state;
-	int level;
+	int num_active_planes = hweight32(crtc_state->active_planes &
+					  ~BIT(PLANE_CURSOR));
+	struct intel_plane_state *plane_state;
+	struct intel_plane *plane;
+	enum plane_id plane_id;
+	int level, ret, i;
+
+	for_each_intel_plane_in_state(state, plane, plane_state, i) {
+		const struct intel_plane_state *old_plane_state =
+			to_intel_plane_state(plane->base.state);
+
+		if (plane_state->base.crtc != &crtc->base &&
+		    old_plane_state->base.crtc != &crtc->base)
+			continue;
+
+		vlv_plane_wm_compute(crtc_state, plane_state);
+	}
+
+	/* initially allow all levels */
+	wm_state->num_levels = vlv_num_wm_levels(dev_priv);
+	/*
+	 * Note that enabling cxsr with no primary/sprite planes
+	 * enabled can wedge the pipe. Hence we only allow cxsr
+	 * with exactly one enabled primary/sprite plane.
+	 */
+	wm_state->cxsr = crtc->pipe != PIPE_C &&
+		crtc->wm.cxsr_allowed && num_active_planes == 1;
+
+	ret = vlv_compute_fifo(crtc_state);
+	if (ret)
+		return ret;
 
 	for (level = 0; level < wm_state->num_levels; level++) {
-		struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-		const int sr_fifo_size =
-			INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
-		enum plane_id plane_id;
+		const struct vlv_pipe_wm *noninverted =
+			&crtc_state->wm.vlv.noninverted[level];
+		const int sr_fifo_size = INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
+
+		if (!vlv_crtc_wm_is_valid(crtc_state, level))
+			break;
+
+		for_each_plane_id_on_crtc(crtc, plane_id) {
+			wm_state->wm[level].plane[plane_id] =
+				vlv_invert_wm_value(noninverted->plane[plane_id],
+						    fifo_state->plane[plane_id]);
+		}
 
 		wm_state->sr[level].plane =
-			vlv_invert_wm_value(wm_state->sr[level].plane,
+			vlv_invert_wm_value(max3(noninverted->plane[PLANE_PRIMARY],
+						 noninverted->plane[PLANE_SPRITE0],
+						 noninverted->plane[PLANE_SPRITE1]),
 					    sr_fifo_size);
+
 		wm_state->sr[level].cursor =
-			vlv_invert_wm_value(wm_state->sr[level].cursor,
+			vlv_invert_wm_value(noninverted->plane[PLANE_CURSOR],
 					    63);
-
-		for_each_plane_id_on_crtc(crtc, plane_id) {
-			wm_state->wm[level].plane[plane_id] =
-				vlv_invert_wm_value(wm_state->wm[level].plane[plane_id],
-						    fifo_state->plane[plane_id]);
-		}
-	}
-}
-
-static void vlv_compute_wm(struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
-	struct intel_plane *plane;
-	int level;
-
-	memset(wm_state, 0, sizeof(*wm_state));
-	memset(crtc_state->wm.vlv.noninverted, 0,
-	       sizeof(crtc_state->wm.vlv.noninverted));
-
-	wm_state->cxsr = crtc->pipe != PIPE_C && crtc->wm.cxsr_allowed;
-	wm_state->num_levels = dev_priv->wm.max_level + 1;
-
-	wm_state->num_active_planes = 0;
-
-	if (wm_state->num_active_planes != 1)
-		wm_state->cxsr = false;
-
-	for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
-		struct intel_plane_state *state =
-			to_intel_plane_state(plane->base.state);
-
-		if (!state->base.visible)
-			continue;
-
-		for (level = 0; level < wm_state->num_levels; level++) {
-			struct vlv_pipe_wm *noninverted =
-				&crtc_state->wm.vlv.noninverted[level];
-			int wm = vlv_compute_wm_level(crtc_state, state, level);
-			int max_wm = plane->id == PLANE_CURSOR ? 63 : 511;
-
-			/* hack */
-			if (WARN_ON(level == 0 && wm > max_wm))
-				wm = max_wm;
-
-			if (wm > max_wm)
-				break;
-
-			noninverted->plane[plane->id] = wm;
-		}
-
-		wm_state->num_levels = level;
 	}
 
-	vlv_compute_fifo(crtc_state);
+	if (level == 0)
+		return -EINVAL;
 
-	for (level = 0; level < wm_state->num_levels; level++) {
-		struct vlv_pipe_wm *noninverted =
-			&crtc_state->wm.vlv.noninverted[level];
+	/* limit to only levels we can actually handle */
+	wm_state->num_levels = level;
 
-		wm_state->wm[level] = *noninverted;
-
-		wm_state->sr[level].plane = max3(noninverted->plane[PLANE_PRIMARY],
-						 noninverted->plane[PLANE_SPRITE0],
-						 noninverted->plane[PLANE_SPRITE1]);
-		wm_state->sr[level].cursor = noninverted->plane[PLANE_CURSOR];
-	}
-
-	/* clear any (partially) filled invalid levels */
-	for (level = wm_state->num_levels; level < dev_priv->wm.max_level + 1; level++) {
-		memset(&wm_state->wm[level], 0, sizeof(wm_state->wm[level]));
-		memset(&wm_state->sr[level], 0, sizeof(wm_state->sr[level]));
-	}
+	/* invalidate the higher levels */
+	vlv_invalidate_wms(crtc, wm_state, level);
 
-	vlv_invert_wms(crtc_state);
+	return 0;
 }
 
 #define VLV_FIFO(plane, value) \
 	(((value) << DSPARB_ ## plane ## _SHIFT_VLV) & DSPARB_ ## plane ## _MASK_VLV)
 
-static void vlv_pipe_set_fifo_size(const struct intel_crtc_state *crtc_state)
+static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
+				   struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
@@ -1196,10 +1272,6 @@ static void vlv_pipe_set_fifo_size(const struct intel_crtc_state *crtc_state)
 	WARN_ON(fifo_state->plane[PLANE_CURSOR] != 63);
 	WARN_ON(fifo_size != 511);
 
-	DRM_DEBUG_KMS("Pipe %c FIFO split %d / %d / %d\n",
-		      pipe_name(crtc->pipe), sprite0_start,
-		      sprite1_start, fifo_size);
-
 	spin_lock(&dev_priv->wm.dsparb_lock);
 
 	switch (crtc->pipe) {
@@ -1298,11 +1370,8 @@ static void vlv_merge_wm(struct drm_i915_private *dev_priv,
 		const struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
 		enum pipe pipe = crtc->pipe;
 
-		if (!crtc->active)
-			continue;
-
 		wm->pipe[pipe] = wm_state->wm[wm->level];
-		if (wm->cxsr)
+		if (crtc->active && wm->cxsr)
 			wm->sr = wm_state->sr[wm->level];
 
 		wm->ddl[pipe].plane[PLANE_PRIMARY] = DDL_PRECISION_HIGH | 2;
@@ -1322,24 +1391,15 @@ static bool is_enabling(int old, int new, int threshold)
 	return old < threshold && new >= threshold;
 }
 
-static void vlv_update_wm(struct intel_crtc *crtc)
+static void vlv_program_watermarks(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	struct intel_crtc_state *crtc_state =
-		to_intel_crtc_state(crtc->base.state);
-	enum pipe pipe = crtc->pipe;
 	struct vlv_wm_values *old_wm = &dev_priv->wm.vlv;
 	struct vlv_wm_values new_wm = {};
 
-	vlv_compute_wm(crtc_state);
-	crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
 	vlv_merge_wm(dev_priv, &new_wm);
 
-	if (memcmp(old_wm, &new_wm, sizeof(new_wm)) == 0) {
-		/* FIXME should be part of crtc atomic commit */
-		vlv_pipe_set_fifo_size(crtc_state);
+	if (memcmp(old_wm, &new_wm, sizeof(new_wm)) == 0)
 		return;
-	}
 
 	if (is_disabling(old_wm->level, new_wm.level, VLV_WM_LEVEL_DDR_DVFS))
 		chv_set_memory_dvfs(dev_priv, false);
@@ -1350,17 +1410,8 @@ static void vlv_update_wm(struct intel_crtc *crtc)
 	if (is_disabling(old_wm->cxsr, new_wm.cxsr, true))
 		_intel_set_memory_cxsr(dev_priv, false);
 
-	/* FIXME should be part of crtc atomic commit */
-	vlv_pipe_set_fifo_size(crtc_state);
-
 	vlv_write_wm_values(dev_priv, &new_wm);
 
-	DRM_DEBUG_KMS("Setting FIFO watermarks - %c: plane=%d, cursor=%d, "
-		      "sprite0=%d, sprite1=%d, SR: plane=%d, cursor=%d level=%d cxsr=%d\n",
-		      pipe_name(pipe), new_wm.pipe[pipe].plane[PLANE_PRIMARY], new_wm.pipe[pipe].plane[PLANE_CURSOR],
-		      new_wm.pipe[pipe].plane[PLANE_SPRITE0], new_wm.pipe[pipe].plane[PLANE_SPRITE1],
-		      new_wm.sr.plane, new_wm.sr.cursor, new_wm.level, new_wm.cxsr);
-
 	if (is_enabling(old_wm->cxsr, new_wm.cxsr, true))
 		_intel_set_memory_cxsr(dev_priv, true);
 
@@ -1373,6 +1424,18 @@ static void vlv_update_wm(struct intel_crtc *crtc)
 	*old_wm = new_wm;
 }
 
+static void vlv_initial_watermarks(struct intel_atomic_state *state,
+				   struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+
+	mutex_lock(&dev_priv->wm.wm_mutex);
+	crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
+	vlv_program_watermarks(dev_priv);
+	mutex_unlock(&dev_priv->wm.wm_mutex);
+}
+
 #define single_plane_enabled(mask) is_power_of_2(mask)
 
 static void g4x_update_wm(struct intel_crtc *crtc)
@@ -4512,14 +4575,10 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct vlv_wm_values *wm = &dev_priv->wm.vlv;
 	struct intel_crtc *crtc;
-	enum pipe pipe;
 	u32 val;
 
 	vlv_read_wm_values(dev_priv, wm);
 
-	for_each_intel_crtc(dev, crtc)
-		vlv_get_fifo_size(to_intel_crtc_state(crtc->base.state));
-
 	wm->cxsr = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 	wm->level = VLV_WM_LEVEL_PM2;
 
@@ -4557,13 +4616,51 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 		mutex_unlock(&dev_priv->rps.hw_lock);
 	}
 
-	for_each_pipe(dev_priv, pipe)
+	for_each_intel_crtc(dev, crtc) {
+		struct intel_crtc_state *crtc_state =
+			to_intel_crtc_state(crtc->base.state);
+		struct vlv_wm_state *active = &crtc->wm.active.vlv;
+		const struct vlv_fifo_state *fifo_state =
+			&crtc_state->wm.vlv.fifo_state;
+		enum pipe pipe = crtc->pipe;
+		enum plane_id plane_id;
+		int level;
+
+		vlv_get_fifo_size(crtc_state);
+
+		active->num_levels = wm->level + 1;
+		active->cxsr = wm->cxsr;
+
+		/* FIXME sanitize things more */
+		for (level = 0; level < active->num_levels; level++) {
+			struct vlv_pipe_wm *noninverted =
+				&crtc_state->wm.vlv.noninverted[level];
+
+			active->sr[level].plane = wm->sr.plane;
+			active->sr[level].cursor = wm->sr.cursor;
+
+			for_each_plane_id_on_crtc(crtc, plane_id) {
+				active->wm[level].plane[plane_id] = wm->pipe[pipe].plane[plane_id];
+
+				noninverted->plane[plane_id] =
+					vlv_invert_wm_value(active->wm[level].plane[plane_id],
+							    fifo_state->plane[plane_id]);
+			}
+		}
+
+		for_each_plane_id_on_crtc(crtc, plane_id)
+			vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
+		vlv_invalidate_wms(crtc, active, level);
+
+		crtc_state->wm.vlv.optimal = *active;
+
 		DRM_DEBUG_KMS("Initial watermarks: pipe %c, plane=%d, cursor=%d, sprite0=%d, sprite1=%d\n",
 			      pipe_name(pipe),
 			      wm->pipe[pipe].plane[PLANE_PRIMARY],
 			      wm->pipe[pipe].plane[PLANE_CURSOR],
 			      wm->pipe[pipe].plane[PLANE_SPRITE0],
 			      wm->pipe[pipe].plane[PLANE_SPRITE1]);
+	}
 
 	DRM_DEBUG_KMS("Initial watermarks: SR plane=%d, SR cursor=%d level=%d cxsr=%d\n",
 		      wm->sr.plane, wm->sr.cursor, wm->level, wm->cxsr);
@@ -7691,7 +7788,9 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
 		}
 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		vlv_setup_wm_latency(dev_priv);
-		dev_priv->display.update_wm = vlv_update_wm;
+		dev_priv->display.compute_pipe_wm = vlv_compute_pipe_wm;
+		dev_priv->display.initial_watermarks = vlv_initial_watermarks;
+		dev_priv->display.atomic_update_watermarks = vlv_atomic_update_fifo;
 	} else if (IS_PINEVIEW(dev_priv)) {
 		if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),
 					    dev_priv->is_ddr3,
-- 
2.7.4

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

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

* [PATCH 08/14] drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not needed
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (6 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-15 15:37   ` Maarten Lankhorst
  2016-12-12 20:35 ` [PATCH 09/14] drm/i915: Compute proper intermediate wms for vlv/cvh ville.syrjala
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Check whether anything relevant has actually change when we compute new
watermarks for each plane in the state. If the watermarks for no
primary/sprite planes changed we don't have to recompute the FIFO split
or reprogram the DSBARB registers. And even the cursor watermarks didn't
change we can skip the merge+invert step between all the planes on
the pipe as well.

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

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index c5a166752eda..df33f270b459 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -99,6 +99,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
 	crtc_state->update_wm_pre = false;
 	crtc_state->update_wm_post = false;
 	crtc_state->fb_changed = false;
+	crtc_state->fifo_changed = false;
 	crtc_state->wm.need_postvbl_update = false;
 	crtc_state->fb_bits = 0;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 66668c18a47a..a92857864ee8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -560,6 +560,7 @@ struct intel_crtc_state {
 	bool disable_cxsr;
 	bool update_wm_pre, update_wm_post; /* watermarks are updated */
 	bool fb_changed; /* fb on any of the planes is changed */
+	bool fifo_changed; /* FIFO split is changed */
 
 	/* Pipe source size (ie. panel fitter input size)
 	 * All planes will be positioned inside this space,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f68b46eed224..c7cc62cf51f6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1103,31 +1103,36 @@ static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
 }
 
 /* starting from 'level' set all higher levels to 'value' */
-static void vlv_plane_wm_set(struct intel_crtc_state *crtc_state,
+static bool vlv_plane_wm_set(struct intel_crtc_state *crtc_state,
 			     int level, enum plane_id plane_id, u16 value)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
 	int num_levels = vlv_num_wm_levels(dev_priv);
+	bool dirty = false;
 
 	for (; level < num_levels; level++) {
 		struct vlv_pipe_wm *noninverted =
 			&crtc_state->wm.vlv.noninverted[level];
 
+		dirty |= noninverted->plane[plane_id] != value;
 		noninverted->plane[plane_id] = value;
 	}
+
+	return dirty;
 }
 
-static void vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
+static bool vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
 				 const struct intel_plane_state *plane_state)
 {
 	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
 	enum plane_id plane_id = plane->id;
 	int num_levels = vlv_num_wm_levels(to_i915(plane->base.dev));
 	int level;
+	bool dirty = false;
 
 	if (!plane_state->base.visible) {
-		vlv_plane_wm_set(crtc_state, 0, plane_id, 0);
-		return;
+		dirty |= vlv_plane_wm_set(crtc_state, 0, plane_id, 0);
+		goto out;
 	}
 
 	for (level = 0; level < num_levels; level++) {
@@ -1143,17 +1148,22 @@ static void vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
 		if (wm > max_wm)
 			break;
 
+		dirty |= noninverted->plane[plane_id] != wm;
 		noninverted->plane[plane_id] = wm;
 	}
 
 	/* mark all higher levels as invalid */
-	vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
+	dirty |= vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
 
-	DRM_DEBUG_KMS("%s wms: [0]=%d,[1]=%d,[2]=%d\n",
-		      plane->base.name,
-		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2].plane[plane_id],
-		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM5].plane[plane_id],
-		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_DDR_DVFS].plane[plane_id]);
+out:
+	if (dirty)
+		DRM_DEBUG_KMS("%s wms: [0]=%d,[1]=%d,[2]=%d\n",
+			      plane->base.name,
+			      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2].plane[plane_id],
+			      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM5].plane[plane_id],
+			      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_DDR_DVFS].plane[plane_id]);
+
+	return dirty;
 }
 
 static bool vlv_plane_wm_is_valid(const struct intel_crtc_state *crtc_state,
@@ -1186,10 +1196,12 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
 		&crtc_state->wm.vlv.fifo_state;
 	int num_active_planes = hweight32(crtc_state->active_planes &
 					  ~BIT(PLANE_CURSOR));
+	bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->base);
 	struct intel_plane_state *plane_state;
 	struct intel_plane *plane;
 	enum plane_id plane_id;
 	int level, ret, i;
+	unsigned int dirty = 0;
 
 	for_each_intel_plane_in_state(state, plane, plane_state, i) {
 		const struct intel_plane_state *old_plane_state =
@@ -1199,7 +1211,37 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
 		    old_plane_state->base.crtc != &crtc->base)
 			continue;
 
-		vlv_plane_wm_compute(crtc_state, plane_state);
+		if (vlv_plane_wm_compute(crtc_state, plane_state))
+			dirty |= BIT(plane->id);
+	}
+
+	/*
+	 * DSPARB registers may have been reset due to the
+	 * power well being turned off. Make sure we restore
+	 * them to a consistent state even if no primary/sprite
+	 * planes are initially active.
+	 */
+	if (needs_modeset)
+		crtc_state->fifo_changed = true;
+
+	if (!dirty)
+		return 0;
+
+	/* cursor changes don't warrant a FIFO recompute */
+	if (dirty & ~BIT(PLANE_CURSOR)) {
+		const struct intel_crtc_state *old_crtc_state =
+			to_intel_crtc_state(crtc->base.state);
+		const struct vlv_fifo_state *old_fifo_state =
+			&old_crtc_state->wm.vlv.fifo_state;
+
+		ret = vlv_compute_fifo(crtc_state);
+		if (ret)
+			return ret;
+
+		if (needs_modeset ||
+		    memcmp(old_fifo_state, fifo_state,
+			   sizeof(*fifo_state)) != 0)
+			crtc_state->fifo_changed = true;
 	}
 
 	/* initially allow all levels */
@@ -1212,10 +1254,6 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
 	wm_state->cxsr = crtc->pipe != PIPE_C &&
 		crtc->wm.cxsr_allowed && num_active_planes == 1;
 
-	ret = vlv_compute_fifo(crtc_state);
-	if (ret)
-		return ret;
-
 	for (level = 0; level < wm_state->num_levels; level++) {
 		const struct vlv_pipe_wm *noninverted =
 			&crtc_state->wm.vlv.noninverted[level];
@@ -1265,6 +1303,9 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
 		&crtc_state->wm.vlv.fifo_state;
 	int sprite0_start, sprite1_start, fifo_size;
 
+	if (!crtc_state->fifo_changed)
+		return;
+
 	sprite0_start = fifo_state->plane[PLANE_PRIMARY];
 	sprite1_start = fifo_state->plane[PLANE_SPRITE0] + sprite0_start;
 	fifo_size = fifo_state->plane[PLANE_SPRITE1] + sprite1_start;
@@ -4631,6 +4672,8 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 		active->num_levels = wm->level + 1;
 		active->cxsr = wm->cxsr;
 
+		vlv_get_fifo_size(crtc_state);
+
 		/* FIXME sanitize things more */
 		for (level = 0; level < active->num_levels; level++) {
 			struct vlv_pipe_wm *noninverted =
-- 
2.7.4

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

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

* [PATCH 09/14] drm/i915: Compute proper intermediate wms for vlv/cvh
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (7 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 08/14] drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not needed ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-12 20:35 ` [PATCH 10/14] drm/i915: Nuke crtc->wm.cxsr_allowed ville.syrjala
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Since the watermark registers arent double buffered on VLV/CHV, we'll
need to play around with intermediate watermarks same was as we do on
ILK-BDW.

The watermark registers on VLV/CHV contain inverted values, so to find
the intermediate watermark value we just take the minimum of the
active and optimal values. This also means that, unlike ILK-BDW,
there's no chance that we'd fail to find a working intermediate
watermarks. As long as both the active and optimal watermarks are valid
the intermediate watermarks will come out valid as well.

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  | 59 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a92857864ee8..f66b3ce89ec4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -527,7 +527,8 @@ struct intel_crtc_wm_state {
 			/* non-inverted optimal watermarks */
 			struct vlv_pipe_wm noninverted[NUM_VLV_WM_LEVELS];
 			struct vlv_fifo_state fifo_state;
-			/* inverted optimal watermarks */
+			/* inverted intermediate and optimal watermarks */
+			struct vlv_wm_state intermediate;
 			struct vlv_wm_state optimal;
 		} vlv;
 	};
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c7cc62cf51f6..c4f395370e9d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1379,6 +1379,45 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
 
 #undef VLV_FIFO
 
+static int vlv_compute_intermediate_wm(struct drm_device *dev,
+				       struct intel_crtc *crtc,
+				       struct intel_crtc_state *crtc_state)
+{
+	struct vlv_wm_state *intermediate = &crtc_state->wm.vlv.intermediate;
+	const struct vlv_wm_state *optimal = &crtc_state->wm.vlv.optimal;
+	const struct vlv_wm_state *active = &crtc->wm.active.vlv;
+	int level;
+
+	intermediate->num_levels = min(optimal->num_levels, active->num_levels);
+	intermediate->cxsr = optimal->cxsr & active->cxsr;
+
+	for (level = 0; level < intermediate->num_levels; level++) {
+		enum plane_id plane_id;
+
+		for_each_plane_id_on_crtc(crtc, plane_id) {
+			intermediate->wm[level].plane[plane_id] =
+				min(optimal->wm[level].plane[plane_id],
+				    active->wm[level].plane[plane_id]);
+		}
+
+		intermediate->sr[level].plane = min(optimal->sr[level].plane,
+						    active->sr[level].plane);
+		intermediate->sr[level].cursor = min(optimal->sr[level].cursor,
+						     active->sr[level].cursor);
+	}
+
+	vlv_invalidate_wms(crtc, intermediate, level);
+
+	/*
+	 * If our intermediate WM are identical to the final WM, then we can
+	 * omit the post-vblank programming; only update if it's different.
+	 */
+	if (memcmp(intermediate, optimal, sizeof(*intermediate)) == 0)
+		crtc_state->wm.need_postvbl_update = false;
+
+	return 0;
+}
+
 static void vlv_merge_wm(struct drm_i915_private *dev_priv,
 			 struct vlv_wm_values *wm)
 {
@@ -1472,7 +1511,22 @@ static void vlv_initial_watermarks(struct intel_atomic_state *state,
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 
 	mutex_lock(&dev_priv->wm.wm_mutex);
-	crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
+	crtc->wm.active.vlv = crtc_state->wm.vlv.intermediate;
+	vlv_program_watermarks(dev_priv);
+	mutex_unlock(&dev_priv->wm.wm_mutex);
+}
+
+static void vlv_optimize_watermarks(struct intel_atomic_state *state,
+				    struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
+
+	if (!crtc_state->wm.need_postvbl_update)
+		return;
+
+	mutex_lock(&dev_priv->wm.wm_mutex);
+	intel_crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
 	vlv_program_watermarks(dev_priv);
 	mutex_unlock(&dev_priv->wm.wm_mutex);
 }
@@ -4696,6 +4750,7 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 		vlv_invalidate_wms(crtc, active, level);
 
 		crtc_state->wm.vlv.optimal = *active;
+		crtc_state->wm.vlv.intermediate = *active;
 
 		DRM_DEBUG_KMS("Initial watermarks: pipe %c, plane=%d, cursor=%d, sprite0=%d, sprite1=%d\n",
 			      pipe_name(pipe),
@@ -7832,7 +7887,9 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		vlv_setup_wm_latency(dev_priv);
 		dev_priv->display.compute_pipe_wm = vlv_compute_pipe_wm;
+		dev_priv->display.compute_intermediate_wm = vlv_compute_intermediate_wm;
 		dev_priv->display.initial_watermarks = vlv_initial_watermarks;
+		dev_priv->display.optimize_watermarks = vlv_optimize_watermarks;
 		dev_priv->display.atomic_update_watermarks = vlv_atomic_update_fifo;
 	} else if (IS_PINEVIEW(dev_priv)) {
 		if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),
-- 
2.7.4

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

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

* [PATCH 10/14] drm/i915: Nuke crtc->wm.cxsr_allowed
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (8 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 09/14] drm/i915: Compute proper intermediate wms for vlv/cvh ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-12 20:35 ` [PATCH 11/14] drm/i915: Only use update_wm_{pre, post} for pre-ilk platforms ville.syrjala
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Remove crtc->wm.cxsr_allowed and just rely on crtc_state->disable_cxsr
instead. This was used only by vlv/chv to indicate whether to enable
cxsr in the wm computation. That doesn't really work anymore, and as far
as the optimal watermarks go we'll just consider the number of planes
and the current pipe, and for the intermediate watermarks we'll also
start to consider disable_cxsr which is set appropriately when planes
are being enabled/disabled.

We'll also flip over the crtc_state->wm.need_postvbl_update setup so
that it's the wm code that will set it. Previously the generic code set
it up, and then the wm code cleared it again if it thought it's not
needed after all.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8d80873b6643..14feac6855e8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5066,8 +5066,6 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
 
 	intel_frontbuffer_flip(to_i915(crtc->base.dev), pipe_config->fb_bits);
 
-	crtc->wm.cxsr_allowed = true;
-
 	if (pipe_config->update_wm_post && pipe_config->base.active)
 		intel_update_watermarks(crtc);
 
@@ -5114,22 +5112,18 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
 			intel_pre_disable_primary(&crtc->base);
 	}
 
-	if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev_priv)) {
-		crtc->wm.cxsr_allowed = false;
-
-		/*
-		 * Vblank time updates from the shadow to live plane control register
-		 * are blocked if the memory self-refresh mode is active at that
-		 * moment. So to make sure the plane gets truly disabled, disable
-		 * first the self-refresh mode. The self-refresh enable bit in turn
-		 * will be checked/applied by the HW only at the next frame start
-		 * event which is after the vblank start event, so we need to have a
-		 * wait-for-vblank between disabling the plane and the pipe.
-		 */
-		if (old_crtc_state->base.active &&
-		    intel_set_memory_cxsr(dev_priv, false))
-			intel_wait_for_vblank(dev_priv, crtc->pipe);
-	}
+	/*
+	 * Vblank time updates from the shadow to live plane control register
+	 * are blocked if the memory self-refresh mode is active at that
+	 * moment. So to make sure the plane gets truly disabled, disable
+	 * first the self-refresh mode. The self-refresh enable bit in turn
+	 * will be checked/applied by the HW only at the next frame start
+	 * event which is after the vblank start event, so we need to have a
+	 * wait-for-vblank between disabling the plane and the pipe.
+	 */
+	if (HAS_GMCH_DISPLAY(dev_priv) && old_crtc_state->base.active &&
+	    pipe_config->disable_cxsr && intel_set_memory_cxsr(dev_priv, false))
+		intel_wait_for_vblank(dev_priv, crtc->pipe);
 
 	/*
 	 * IVB workaround: must disable low power watermarks for at least
@@ -12552,11 +12546,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 		pipe_config->update_wm_post = true;
 	}
 
-	/* Pre-gen9 platforms need two-step watermark updates */
-	if ((pipe_config->update_wm_pre || pipe_config->update_wm_post) &&
-	    INTEL_GEN(dev_priv) < 9 && dev_priv->display.optimize_watermarks)
-		to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
-
 	if (visible || was_visible)
 		pipe_config->fb_bits |= plane->frontbuffer_bit;
 
@@ -14330,12 +14319,7 @@ static bool needs_vblank_wait(struct intel_crtc_state *crtc_state)
 	if (crtc_state->update_wm_post)
 		return true;
 
-	/*
-	 * cxsr is re-enabled after vblank.
-	 * This is already handled by crtc_state->update_wm_post,
-	 * but added for clarity.
-	 */
-	if (crtc_state->disable_cxsr)
+	if (crtc_state->wm.need_postvbl_update)
 		return true;
 
 	return false;
@@ -15438,8 +15422,6 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
 	intel_crtc->cursor_cntl = ~0;
 	intel_crtc->cursor_size = ~0;
 
-	intel_crtc->wm.cxsr_allowed = true;
-
 	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
 	       dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
 	dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = intel_crtc;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f66b3ce89ec4..8474dced7912 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -749,9 +749,6 @@ struct intel_crtc {
 			struct intel_pipe_wm ilk;
 			struct vlv_wm_state vlv;
 		} active;
-
-		/* allow CxSR on this pipe */
-		bool cxsr_allowed;
 	} wm;
 
 	int scanline_offset;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c4f395370e9d..3896a14217f5 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1251,8 +1251,7 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
 	 * enabled can wedge the pipe. Hence we only allow cxsr
 	 * with exactly one enabled primary/sprite plane.
 	 */
-	wm_state->cxsr = crtc->pipe != PIPE_C &&
-		crtc->wm.cxsr_allowed && num_active_planes == 1;
+	wm_state->cxsr = crtc->pipe != PIPE_C && num_active_planes == 1;
 
 	for (level = 0; level < wm_state->num_levels; level++) {
 		const struct vlv_pipe_wm *noninverted =
@@ -1389,7 +1388,8 @@ static int vlv_compute_intermediate_wm(struct drm_device *dev,
 	int level;
 
 	intermediate->num_levels = min(optimal->num_levels, active->num_levels);
-	intermediate->cxsr = optimal->cxsr & active->cxsr;
+	intermediate->cxsr = optimal->cxsr && active->cxsr &&
+		!crtc_state->disable_cxsr;
 
 	for (level = 0; level < intermediate->num_levels; level++) {
 		enum plane_id plane_id;
@@ -1412,8 +1412,8 @@ static int vlv_compute_intermediate_wm(struct drm_device *dev,
 	 * If our intermediate WM are identical to the final WM, then we can
 	 * omit the post-vblank programming; only update if it's different.
 	 */
-	if (memcmp(intermediate, optimal, sizeof(*intermediate)) == 0)
-		crtc_state->wm.need_postvbl_update = false;
+	if (memcmp(intermediate, optimal, sizeof(*intermediate)) != 0)
+		crtc_state->wm.need_postvbl_update = true;
 
 	return 0;
 }
@@ -2632,8 +2632,8 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev,
 	 * If our intermediate WM are identical to the final WM, then we can
 	 * omit the post-vblank programming; only update if it's different.
 	 */
-	if (memcmp(a, &newstate->wm.ilk.optimal, sizeof(*a)) == 0)
-		newstate->wm.need_postvbl_update = false;
+	if (memcmp(a, &newstate->wm.ilk.optimal, sizeof(*a)) != 0)
+		newstate->wm.need_postvbl_update = true;
 
 	return 0;
 }
-- 
2.7.4

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

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

* [PATCH 11/14] drm/i915: Only use update_wm_{pre, post} for pre-ilk platforms
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (9 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 10/14] drm/i915: Nuke crtc->wm.cxsr_allowed ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-12 20:35 ` [PATCH 12/14] drm/i915: Sanitize VLV/CHV watermarks properly ville.syrjala
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Now that vlv/chv have more proper wm programming support, let's reduce
the the update_wm_{pre,post} flags to only cover the pre-ilk platforms.
When we finally convert those as well we can drop these flags entirely.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 14feac6855e8..9d788504cbda 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12529,21 +12529,25 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 			 turn_off, turn_on, mode_changed);
 
 	if (turn_on) {
-		pipe_config->update_wm_pre = true;
+		if (INTEL_GEN(dev_priv) < 5)
+			pipe_config->update_wm_pre = true;
 
 		/* must disable cxsr around plane enable/disable */
 		if (plane->id != PLANE_CURSOR)
 			pipe_config->disable_cxsr = true;
 	} else if (turn_off) {
-		pipe_config->update_wm_post = true;
+		if (INTEL_GEN(dev_priv) < 5)
+			pipe_config->update_wm_post = true;
 
 		/* must disable cxsr around plane enable/disable */
 		if (plane->id != PLANE_CURSOR)
 			pipe_config->disable_cxsr = true;
 	} else if (intel_wm_need_update(&plane->base, plane_state)) {
-		/* FIXME bollocks */
-		pipe_config->update_wm_pre = true;
-		pipe_config->update_wm_post = true;
+		if (INTEL_GEN(dev_priv) < 5) {
+			/* FIXME bollocks */
+			pipe_config->update_wm_pre = true;
+			pipe_config->update_wm_post = true;
+		}
 	}
 
 	if (visible || was_visible)
-- 
2.7.4

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

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

* [PATCH 12/14] drm/i915: Sanitize VLV/CHV watermarks properly
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (10 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 11/14] drm/i915: Only use update_wm_{pre, post} for pre-ilk platforms ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-12 20:35 ` [PATCH 13/14] drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun ville.syrjala
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Clear out the watermark for all disabled planes to 0. This is required
to avoid falsely thinking that the inherited watermarks are bogus in
case the watermark is actually higher than the FIFO size.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9d788504cbda..c16dc0bff2d4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3541,7 +3541,8 @@ __intel_display_resume(struct drm_device *dev,
 	}
 
 	/* ignore any reset values/BIOS leftovers in the WM registers */
-	to_intel_atomic_state(state)->skip_intermediate_wm = true;
+	if (!HAS_GMCH_DISPLAY(to_i915(dev)))
+		to_intel_atomic_state(state)->skip_intermediate_wm = true;
 
 	ret = drm_atomic_commit(state);
 
@@ -16495,7 +16496,8 @@ static void sanitize_watermarks(struct drm_device *dev)
 	 * intermediate watermarks (since we don't trust the current
 	 * watermarks).
 	 */
-	intel_state->skip_intermediate_wm = true;
+	if (!HAS_GMCH_DISPLAY(dev_priv))
+		intel_state->skip_intermediate_wm = true;
 
 	ret = intel_atomic_check(dev, state);
 	if (ret) {
@@ -16656,7 +16658,8 @@ int intel_modeset_init(struct drm_device *dev)
 	 * Note that we need to do this after reconstructing the BIOS fb's
 	 * since the watermark calculation done here will use pstate->fb.
 	 */
-	sanitize_watermarks(dev);
+	if (!HAS_GMCH_DISPLAY(dev_priv))
+		sanitize_watermarks(dev);
 
 	return 0;
 }
@@ -17104,12 +17107,14 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
 		pll->on = false;
 	}
 
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		vlv_wm_get_hw_state(dev);
-	else if (IS_GEN9(dev_priv))
+		vlv_wm_sanitize(dev_priv);
+	} else if (IS_GEN9(dev_priv)) {
 		skl_wm_get_hw_state(dev);
-	else if (HAS_PCH_SPLIT(dev_priv))
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		ilk_wm_get_hw_state(dev);
+	}
 
 	for_each_intel_crtc(dev, crtc) {
 		unsigned long put_domains;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 8474dced7912..5c7fb508c40d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1767,6 +1767,7 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
 			  struct skl_ddb_allocation *ddb /* out */);
 void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
 			      struct skl_pipe_wm *out);
+void vlv_wm_sanitize(struct drm_i915_private *dev_priv);
 bool intel_can_enable_sagv(struct drm_atomic_state *state);
 int intel_enable_sagv(struct drm_i915_private *dev_priv);
 int intel_disable_sagv(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 3896a14217f5..fa882cdcac52 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4728,7 +4728,6 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 
 		vlv_get_fifo_size(crtc_state);
 
-		/* FIXME sanitize things more */
 		for (level = 0; level < active->num_levels; level++) {
 			struct vlv_pipe_wm *noninverted =
 				&crtc_state->wm.vlv.noninverted[level];
@@ -4764,6 +4763,55 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
 		      wm->sr.plane, wm->sr.cursor, wm->level, wm->cxsr);
 }
 
+void vlv_wm_sanitize(struct drm_i915_private *dev_priv)
+{
+	struct intel_plane *plane;
+	struct intel_crtc *crtc;
+
+	mutex_lock(&dev_priv->wm.wm_mutex);
+
+	for_each_intel_plane(&dev_priv->drm, plane) {
+		struct intel_crtc *crtc =
+			intel_get_crtc_for_pipe(dev_priv, plane->pipe);
+		struct intel_crtc_state *crtc_state =
+			to_intel_crtc_state(crtc->base.state);
+		struct intel_plane_state *plane_state =
+			to_intel_plane_state(plane->base.state);
+		struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
+		const struct vlv_fifo_state *fifo_state =
+			&crtc_state->wm.vlv.fifo_state;
+		enum plane_id plane_id = plane->id;
+		int level;
+
+		if (plane_state->base.visible)
+			continue;
+
+		for (level = 0; level < wm_state->num_levels; level++) {
+			struct vlv_pipe_wm *noninverted =
+				&crtc_state->wm.vlv.noninverted[level];
+
+			noninverted->plane[plane_id] = 0;
+
+			wm_state->wm[level].plane[plane_id] =
+				vlv_invert_wm_value(noninverted->plane[plane_id],
+						    fifo_state->plane[plane_id]);
+		}
+	}
+
+	for_each_intel_crtc(&dev_priv->drm, crtc) {
+		struct intel_crtc_state *crtc_state =
+			to_intel_crtc_state(crtc->base.state);
+
+		crtc_state->wm.vlv.intermediate =
+			crtc_state->wm.vlv.optimal;
+		crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
+	}
+
+	vlv_program_watermarks(dev_priv);
+
+	mutex_unlock(&dev_priv->wm.wm_mutex);
+}
+
 void ilk_wm_get_hw_state(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-- 
2.7.4

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

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

* [PATCH 13/14] drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (11 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 12/14] drm/i915: Sanitize VLV/CHV watermarks properly ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-15 15:34   ` Maarten Lankhorst
  2016-12-12 20:35 ` [PATCH 14/14] drm/i915: Kill level 0 wm hack for VLV/CHV ville.syrjala
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

On VLV/CHV enabling sprite0 when sprite1 has already been enabled may
lead to an underrun. This only happens when sprite0 FIFO size is zero
prior to enabling it. Hence an effective workaround is to always
allocate at least one cacheline for sprite0 when sprite1 is active.

I've not observed this sort of failure during any other type of plane
enable/disable sequence.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index fa882cdcac52..75a5bde43723 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1006,6 +1006,12 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
 	return min_t(int, wm, USHRT_MAX);
 }
 
+static bool vlv_need_sprite0_fifo_workaround(unsigned int active_planes)
+{
+	return (active_planes & (BIT(PLANE_SPRITE0) |
+				 BIT(PLANE_SPRITE1))) == BIT(PLANE_SPRITE1);
+}
+
 static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
@@ -1016,12 +1022,25 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
 	int num_active_planes = hweight32(active_planes);
 	const int fifo_size = 511;
 	int fifo_extra, fifo_left = fifo_size;
+	int sprite0_fifo_extra = 0;
 	unsigned int total_rate;
 	enum plane_id plane_id;
 
+	/*
+	 * When enabling sprite0 after sprite1 has already been enabled
+	 * we tend to get an underrun unless sprite0 already has some
+	 * FIFO space allcoated. Hence we always allocate at least one
+	 * cacheline for sprite0 whenever sprite1 is enabled.
+	 *
+	 * All other plane enable sequences appear immune to this problem.
+	 */
+	if (vlv_need_sprite0_fifo_workaround(active_planes))
+		sprite0_fifo_extra = 1;
+
 	total_rate = noninverted->plane[PLANE_PRIMARY] +
 		noninverted->plane[PLANE_SPRITE0] +
-		noninverted->plane[PLANE_SPRITE1];
+		noninverted->plane[PLANE_SPRITE1] +
+		sprite0_fifo_extra;
 
 	if (total_rate > fifo_size)
 		return -EINVAL;
@@ -1042,6 +1061,9 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
 		fifo_left -= fifo_state->plane[plane_id];
 	}
 
+	fifo_state->plane[PLANE_SPRITE0] += sprite0_fifo_extra;
+	fifo_left -= sprite0_fifo_extra;
+
 	fifo_state->plane[PLANE_CURSOR] = 63;
 
 	fifo_extra = DIV_ROUND_UP(fifo_left, num_active_planes ?: 1);
-- 
2.7.4

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

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

* [PATCH 14/14] drm/i915: Kill level 0 wm hack for VLV/CHV
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (12 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 13/14] drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-15 17:10   ` Maarten Lankhorst
  2016-12-12 20:35 ` [PATCH i-g-t] tests: Add kms_plane_blinker ville.syrjala
  2016-12-12 21:15 ` ✗ Fi.CI.BAT: warning for drm/i915: VLV/CHV two-stage watermarks Patchwork
  15 siblings, 1 reply; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

We now compute the watermarks correctly, so just return an error if we
can't support the configuration.

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

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 75a5bde43723..f3aed64e7086 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1163,10 +1163,6 @@ static bool vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
 		int wm = vlv_compute_wm_level(crtc_state, plane_state, level);
 		int max_wm = plane_id == PLANE_CURSOR ? 63 : 511;
 
-		/* FIXME just bail */
-		if (WARN_ON(level == 0 && wm > max_wm))
-			wm = max_wm;
-
 		if (wm > max_wm)
 			break;
 
-- 
2.7.4

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

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

* [PATCH i-g-t] tests: Add kms_plane_blinker
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (13 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH 14/14] drm/i915: Kill level 0 wm hack for VLV/CHV ville.syrjala
@ 2016-12-12 20:35 ` ville.syrjala
  2016-12-15 15:17   ` Maarten Lankhorst
  2016-12-12 21:15 ` ✗ Fi.CI.BAT: warning for drm/i915: VLV/CHV two-stage watermarks Patchwork
  15 siblings, 1 reply; 47+ messages in thread
From: ville.syrjala @ 2016-12-12 20:35 UTC (permalink / raw)
  To: intel-gfx

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

Add a test to try out all the different plane enable/disable
order permutations.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 tests/Makefile.sources    |   1 +
 tests/kms_plane_blinker.c | 529 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 530 insertions(+)
 create mode 100644 tests/kms_plane_blinker.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 04dd2d58612f..9c60bb90335d 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -110,6 +110,7 @@ TESTS_progs_M = \
 	kms_pipe_color \
 	kms_pipe_crc_basic \
 	kms_plane \
+	kms_plane_blinker \
 	kms_plane_multiple \
 	kms_properties \
 	kms_psr_sink_crc \
diff --git a/tests/kms_plane_blinker.c b/tests/kms_plane_blinker.c
new file mode 100644
index 000000000000..c6dace1121b5
--- /dev/null
+++ b/tests/kms_plane_blinker.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "igt.h"
+
+IGT_TEST_DESCRIPTION("Test all plane enable/disable sequence permutations.");
+
+#define __FAC_0 1
+#define __FAC_1 1
+#define __FAC_2 (2*__FAC_1)
+#define __FAC_3 (3*__FAC_2)
+#define __FAC_4 (4*__FAC_3)
+#define _FAC(n) __FAC_ ## n
+#define FAC(n) _FAC(n)
+
+#define __SUB_4_0 4
+#define __SUB_4_1 3
+#define __SUB_4_2 2
+#define __SUB_4_3 1
+#define __SUB_4_4 0
+#define _SUB(a,b) __SUB_ ## a ## _ ## b
+#define SUB(a,b) _SUB(a,b)
+
+#define C(k,n) (FAC(k) / (FAC(SUB(k, n)) * FAC(n)))
+
+/* all combinations */
+#define NUM_REF_CRCS (C(4,0) + C(4,1) + C(4,2) + C(4,3) + C(4,4))
+
+typedef struct {
+	int drm_fd;
+	igt_display_t display;
+	igt_output_t *output;
+	enum pipe pipe;
+	igt_pipe_crc_t *pipe_crc;
+	igt_crc_t ref_crc[NUM_REF_CRCS];
+	uint8_t ref_crc_active_planes[NUM_REF_CRCS];
+	int num_ref_crcs;
+	uint32_t devid;
+	unsigned int delay_us;
+	unsigned int timeout_ms;
+	struct igt_fb ref_fb;
+	struct igt_fb fb[4];
+	igt_plane_t *plane[4];
+	uint8_t num_planes;
+	uint8_t active_plane[4];
+	uint8_t num_active_planes;
+} data_t;
+
+static unsigned int gettime_ms(void)
+{
+	struct timespec ts;
+
+	clock_gettime(CLOCK_MONOTONIC, &ts);
+
+	return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+}
+
+static const struct {
+	float r, g, b;
+} colors[] = {
+	{ 1.0f, 0.0f, 0.0f },
+	{ 0.0f, 1.0f, 0.0f },
+	{ 0.0f, 0.0f, 1.0f },
+	{ 0.0f, 1.0f, 1.0f },
+	{ 1.0f, 0.0f, 1.0f },
+	{ 1.0f, 1.0f, 0.0f },
+};
+
+static uint32_t plane_format(data_t *data, int plane)
+{
+	if (plane == data->num_planes - 1)
+		return DRM_FORMAT_ARGB8888;
+	else
+		return DRM_FORMAT_XRGB8888;
+}
+
+static int plane_x(int plane)
+{
+	return plane * 100;
+}
+
+static int plane_y(int plane)
+{
+	return plane * 100;
+}
+
+static int plane_width(data_t *data, int plane)
+{
+	drmModeModeInfo *mode = igt_output_get_mode(data->output);
+
+	if (plane == 0)
+		return mode->hdisplay;
+	else if (plane == data->num_planes - 1)
+		return 64;
+	else
+		return mode->hdisplay / 2;
+}
+
+static int plane_height(data_t *data, int plane)
+{
+	drmModeModeInfo *mode = igt_output_get_mode(data->output);
+
+	if (plane == 0)
+		return mode->vdisplay;
+	else if (plane == data->num_planes - 1)
+		return 64;
+	else
+		return mode->vdisplay / 2;
+}
+
+static igt_crc_t *find_ref_crc(data_t *data, uint8_t active_planes)
+{
+	int i;
+
+	for (i = 0; i < data->num_ref_crcs; i++) {
+		if (data->ref_crc_active_planes[i] == active_planes)
+			return &data->ref_crc[i];
+	}
+
+	return NULL;
+}
+
+static void generate_ref_crc(data_t *data, int num_active_planes)
+{
+	drmModeModeInfo *mode;
+	cairo_t *cr;
+	int i;
+
+	mode = igt_output_get_mode(data->output);
+
+	data->ref_crc_active_planes[data->num_ref_crcs] = 0;
+
+	cr = igt_get_cairo_ctx(data->drm_fd, &data->ref_fb);
+
+	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
+			0.0, 0.0, 0.0);
+
+	for (i = 0; i < num_active_planes; i++) {
+		int plane = data->active_plane[i];
+		int w, h;
+		int x, y;
+
+		data->ref_crc_active_planes[data->num_ref_crcs] |= 1 << plane;
+
+		x = plane_x(plane);
+		y = plane_y(plane);
+		w = plane_width(data, plane);
+		h = plane_height(data, plane);
+
+		cairo_save(cr);
+		cairo_rectangle(cr, x, y, w, h);
+		cairo_clip(cr);
+
+		igt_paint_color(cr, x, y, w, h,
+				colors[plane].r, colors[plane].g, colors[plane].b);
+		cairo_translate(cr, x, y);
+		igt_paint_test_pattern(cr, w, h);
+		cairo_restore(cr);
+	}
+
+	igt_assert(cairo_status(cr) == 0);
+	cairo_destroy(cr);
+
+	igt_wait_for_vblank(data->drm_fd, data->pipe);
+
+	igt_assert(data->num_ref_crcs < NUM_REF_CRCS);
+	igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc[data->num_ref_crcs]);
+	data->num_ref_crcs++;
+}
+
+static void do_combination(data_t *data, int plane, int idx,
+			   int num_active_planes)
+{
+	if (idx == num_active_planes) {
+		generate_ref_crc(data, num_active_planes);
+		return;
+	}
+
+	for (; plane < data->num_planes; plane++) {
+		data->active_plane[idx] = plane;
+		do_combination(data, plane + 1, idx + 1, num_active_planes);
+	}
+}
+
+static bool igt_crc_equal(const igt_crc_t *a, const igt_crc_t *b)
+{
+	return a->n_words == b->n_words &&
+		memcmp(a->crc, b->crc, sizeof(a->crc[0]) * a->n_words) == 0;
+}
+
+static void generate_ref_crcs(data_t *data)
+{
+	int num_active_planes, i, j;
+
+	data->num_ref_crcs = 0;
+
+	/* ref crc for 0 active planes */
+	for (num_active_planes = 0;
+	     num_active_planes <= data->num_active_planes;
+	     num_active_planes++)
+		do_combination(data, 0, 0, num_active_planes);
+
+	for (i = 0; i < data->num_ref_crcs; i++) {
+		for (j = i + 1; j < data->num_ref_crcs; j++) {
+			if (igt_crc_equal(&data->ref_crc[i], &data->ref_crc[j]))
+				break;
+		}
+		if (j < data->num_ref_crcs) {
+			igt_warn("reference CRCs not unique\n");
+			break;
+		}
+	}
+}
+
+static bool prepare_crtc(data_t *data)
+{
+	igt_display_t *display = &data->display;
+	drmModeModeInfo *mode;
+	int i;
+
+	/* select the pipe we want to use */
+	igt_output_set_pipe(data->output, data->pipe);
+	igt_display_commit(display);
+
+	if (!data->output->valid) {
+		igt_output_set_pipe(data->output, PIPE_ANY);
+		igt_display_commit(display);
+		return false;
+	}
+
+	mode = igt_output_get_mode(data->output);
+
+	igt_create_color_fb(data->drm_fd,
+			    mode->hdisplay, mode->vdisplay,
+			    DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
+			    1.0, 1.0, 1.0,
+			    &data->ref_fb);
+
+	for (i = 0; i < data->num_planes; i++) {
+		igt_create_color_pattern_fb(data->drm_fd,
+					    plane_width(data, i), plane_height(data, i),
+					    plane_format(data, i), LOCAL_DRM_FORMAT_MOD_NONE,
+					    colors[i].r, colors[i].g, colors[i].b,
+					    &data->fb[i]);
+
+		data->plane[i] = igt_output_get_plane(data->output, i);
+	}
+
+	igt_plane_set_fb(data->plane[0], &data->ref_fb);
+	igt_display_commit(display);
+
+	/* create the pipe_crc object for this pipe */
+	if (data->pipe_crc)
+		igt_pipe_crc_free(data->pipe_crc);
+	data->pipe_crc = igt_pipe_crc_new_nonblock(data->pipe,
+						   INTEL_PIPE_CRC_SOURCE_AUTO);
+
+	generate_ref_crcs(data);
+
+	igt_plane_set_fb(data->plane[0], NULL);
+	igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+	igt_remove_fb(data->drm_fd, &data->ref_fb);
+
+	return true;
+}
+
+#define NCRC 10
+
+static void check_crcs(data_t *data, uint8_t active_planes,
+		       igt_crc_t *last_ref_crc,
+		       igt_crc_t *ref_crc)
+{
+	igt_crc_t *crc;
+	int i, n;
+
+	n = igt_pipe_crc_get_crcs(data->pipe_crc, NCRC, &crc);
+
+	for (i = 0; i < n; i++) {
+		if (!igt_crc_equal(&crc[i], last_ref_crc))
+			break;
+	}
+	for (; i < n; i++)
+		igt_assert_crc_equal(&crc[i], ref_crc);
+
+	free(crc);
+}
+
+static void do_test(data_t *data)
+{
+	igt_display_t *display = &data->display;
+	igt_crc_t *last_ref_crc;
+	unsigned int start;
+	int num;
+
+	igt_info(" Testing planes: none -> ");
+	for (num = 1; num < data->num_active_planes; num++) {
+		int idx;
+
+		igt_info("%d", data->active_plane[0]);
+		for (idx = 1; idx < num; idx++)
+			igt_info(",%d", data->active_plane[idx]);
+		igt_info(" -> ");
+	}
+	for (; num > 0; num--) {
+		int idx;
+
+		igt_info("%d", data->active_plane[0]);
+		for (idx = 1; idx < num; idx++)
+			igt_info(",%d", data->active_plane[idx]);
+		igt_info(" -> ");
+	}
+	igt_info("none\n");
+
+	start = gettime_ms();
+
+	last_ref_crc = find_ref_crc(data, 0);
+
+	igt_pipe_crc_start(data->pipe_crc);
+
+	do {
+		int idx;
+		uint8_t active_planes = 0;
+
+		for (idx = 0; idx < data->num_active_planes; idx++) {
+			int plane = data->active_plane[idx];
+			igt_crc_t *ref_crc;
+
+			active_planes |= 1 << plane;
+
+			ref_crc = find_ref_crc(data, active_planes);
+			igt_assert(ref_crc);
+
+			igt_plane_set_fb(data->plane[plane], &data->fb[plane]);
+			igt_plane_set_position(data->plane[plane],
+					       plane_x(plane), plane_y(plane));
+			igt_display_commit2(display, COMMIT_UNIVERSAL);
+			usleep(data->delay_us);
+
+			check_crcs(data, active_planes, last_ref_crc, ref_crc);
+			last_ref_crc = ref_crc;
+		}
+
+		igt_assert(active_planes != 0);
+
+		for (idx = data->num_active_planes - 1; idx >= 0; idx--) {
+			int plane = data->active_plane[idx];
+			igt_crc_t *ref_crc;
+
+			active_planes &= ~(1 << plane);
+
+			ref_crc = find_ref_crc(data, active_planes);
+			igt_assert(ref_crc);
+
+			igt_plane_set_fb(data->plane[plane], NULL);
+			igt_display_commit2(display, COMMIT_UNIVERSAL);
+			usleep(data->delay_us);
+
+			check_crcs(data, active_planes, last_ref_crc, ref_crc);
+			last_ref_crc = ref_crc;
+		}
+
+		igt_assert(active_planes == 0);
+	} while (data->timeout_ms > 0 &&
+		 gettime_ms() - start < data->timeout_ms);
+
+	igt_pipe_crc_stop(data->pipe_crc);
+}
+
+static void do_permutation(data_t *data,
+			   unsigned int available_planes,
+			   int idx)
+{
+	int plane;
+
+	if (idx == data->num_active_planes) {
+		do_test(data);
+		return;
+	}
+
+	for (plane = 0; plane < data->num_planes; plane++) {
+		if (!(available_planes & (1 << plane)))
+			continue;
+
+		data->active_plane[idx] = plane;
+		do_permutation(data,
+			       available_planes & ~(1 << plane),
+			       idx + 1);
+	}
+}
+
+static void test_permutations(data_t *data)
+{
+	do_permutation(data, (1 << data->num_planes) - 1, 0);
+}
+
+static void cleanup_crtc(data_t *data)
+{
+	igt_display_t *display = &data->display;
+	int i;
+
+	igt_pipe_crc_free(data->pipe_crc);
+	data->pipe_crc = NULL;
+
+	for (i = 0; i < data->num_planes; i++) {
+		igt_remove_fb(data->drm_fd, &data->fb[i]);
+		igt_plane_set_fb(data->plane[i], NULL);
+	}
+
+	igt_output_set_pipe(data->output, PIPE_ANY);
+	igt_display_commit(display);
+}
+
+static void test(data_t *data)
+{
+	igt_display_t *display = &data->display;
+	int valid_tests = 0;
+
+	igt_require(data->pipe <= display->n_pipes);
+	igt_require(data->num_active_planes <= display->pipes[data->pipe].n_planes);
+
+	data->num_planes = data->display.pipes[data->pipe].n_planes;
+
+	for_each_connected_output(display, data->output) {
+		if (!prepare_crtc(data))
+			continue;
+
+		valid_tests++;
+
+		igt_info("Beginning %s on pipe %s, connector %s\n",
+			 igt_subtest_name(),
+			 kmstest_pipe_name(data->pipe),
+			 igt_output_name(data->output));
+
+		test_permutations(data);
+
+		igt_info("\n%s on pipe %s, connector %s: PASSED\n\n",
+			 igt_subtest_name(),
+			 kmstest_pipe_name(data->pipe),
+			 igt_output_name(data->output));
+
+		cleanup_crtc(data);
+	}
+
+	igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
+}
+
+static int opt_handler(int opt, int opt_index, void *_data)
+{
+	data_t *data = _data;
+
+	switch (opt) {
+	case 'd':
+		data->delay_us = strtoull(optarg, NULL, 0) * 1000;
+		break;
+	case 't':
+		data->timeout_ms = strtoull(optarg, NULL, 0);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static data_t data;
+
+int main(int argc, char *argv[])
+{
+	static const struct option long_opts[] = {
+		{ .name = "delay", .val = 'd', .has_arg = required_argument },
+		{ .name = "timeout", .val = 't', .has_arg = required_argument },
+		{}
+	};
+        static const char *help_str =
+		"  --delay\t\tDelay (in ms) between each plane enable/disable\n"
+		"  --timeout\t\tTimeout (in ms) per connector for each subtest\n";
+
+	data.timeout_ms = 100;
+	data.delay_us = 20000;
+
+	igt_subtest_init_parse_opts(&argc, argv, "", long_opts, help_str,
+                                    opt_handler, &data);
+
+	data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
+	data.devid = intel_get_drm_devid(data.drm_fd);
+
+	igt_require_pipe_crc();
+
+	kmstest_set_vt_graphics_mode();
+
+	igt_display_init(&data.display, data.drm_fd);
+	igt_require(data.display.has_universal_planes);
+
+	for (data.pipe = PIPE_A; data.pipe <= PIPE_C; data.pipe++) {
+		for (data.num_active_planes = 1;
+		     data.num_active_planes <= 4; data.num_active_planes++) {
+			igt_subtest_f("pipe-%s-%d-planes",
+				      kmstest_pipe_name(data.pipe), data.num_active_planes) {
+				test(&data);
+			}
+		}
+	}
+
+	igt_display_fini(&data.display);
+
+	igt_exit();
+}
-- 
2.7.4

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

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

* ✗ Fi.CI.BAT: warning for drm/i915: VLV/CHV two-stage watermarks
  2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
                   ` (14 preceding siblings ...)
  2016-12-12 20:35 ` [PATCH i-g-t] tests: Add kms_plane_blinker ville.syrjala
@ 2016-12-12 21:15 ` Patchwork
  2016-12-13  7:42   ` Saarinen, Jani
  15 siblings, 1 reply; 47+ messages in thread
From: Patchwork @ 2016-12-12 21:15 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: VLV/CHV two-stage watermarks
URL   : https://patchwork.freedesktop.org/series/16712/
State : warning

== Summary ==

Series 16712v1 drm/i915: VLV/CHV two-stage watermarks
https://patchwork.freedesktop.org/api/1.0/series/16712/revisions/1/mbox/

Test drv_module_reload:
        Subgroup basic-reload-inject:
                pass       -> DMESG-WARN (fi-ilk-650)

fi-bdw-5557u     total:247  pass:233  dwarn:0   dfail:0   fail:0   skip:14 
fi-bsw-n3050     total:247  pass:208  dwarn:0   dfail:0   fail:0   skip:39 
fi-byt-j1900     total:247  pass:220  dwarn:0   dfail:0   fail:0   skip:27 
fi-byt-n2820     total:247  pass:216  dwarn:0   dfail:0   fail:0   skip:31 
fi-hsw-4770      total:247  pass:228  dwarn:0   dfail:0   fail:0   skip:19 
fi-hsw-4770r     total:247  pass:228  dwarn:0   dfail:0   fail:0   skip:19 
fi-ilk-650       total:247  pass:194  dwarn:1   dfail:0   fail:0   skip:52 
fi-ivb-3520m     total:247  pass:226  dwarn:0   dfail:0   fail:0   skip:21 
fi-ivb-3770      total:247  pass:226  dwarn:0   dfail:0   fail:0   skip:21 
fi-kbl-7500u     total:247  pass:226  dwarn:0   dfail:0   fail:0   skip:21 
fi-skl-6260u     total:247  pass:234  dwarn:0   dfail:0   fail:0   skip:13 
fi-skl-6700hq    total:247  pass:227  dwarn:0   dfail:0   fail:0   skip:20 
fi-skl-6700k     total:247  pass:224  dwarn:3   dfail:0   fail:0   skip:20 
fi-skl-6770hq    total:247  pass:234  dwarn:0   dfail:0   fail:0   skip:13 
fi-snb-2520m     total:247  pass:216  dwarn:0   dfail:0   fail:0   skip:31 
fi-snb-2600      total:247  pass:215  dwarn:0   dfail:0   fail:0   skip:32 

ac15a853c56c1a95a992f39ca2c1579e68b73a71 drm-tip: 2016y-12m-12d-15h-25m-32s UTC integration manifest
8adda35 drm/i915: Kill level 0 wm hack for VLV/CHV
f97c869 drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
7d57fef drm/i915: Sanitize VLV/CHV watermarks properly
bbc58e0 drm/i915: Only use update_wm_{pre, post} for pre-ilk platforms
a22a58b drm/i915: Nuke crtc->wm.cxsr_allowed
1d53011 drm/i915: Compute proper intermediate wms for vlv/cvh
5b4eb52 drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not needed
ef4eac9 drm/i915: Compute vlv/chv wms the atomic way
3bb2ec4 drm/i915: Compute VLV/CHV FIFO sizes based on the PM2 watermarks
1e2c256 drm/i915: Plop vlv/chv fifo sizes into crtc state
d00a73d drm/i915: Plop vlv wm state into crtc_state
a2fb13c drm/i915: Move vlv wms from crtc->wm_state to crtc->wm.active.vlv
cd6e5e3 drm/i915: Track plane fifo sizes under intel_crtc
e414e82 drm/i915: Track visible planes in a bitmask

== Logs ==

For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3270/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: ✗ Fi.CI.BAT: warning for drm/i915: VLV/CHV two-stage watermarks
  2016-12-12 21:15 ` ✗ Fi.CI.BAT: warning for drm/i915: VLV/CHV two-stage watermarks Patchwork
@ 2016-12-13  7:42   ` Saarinen, Jani
  2016-12-13  8:40     ` Chris Wilson
  0 siblings, 1 reply; 47+ messages in thread
From: Saarinen, Jani @ 2016-12-13  7:42 UTC (permalink / raw)
  To: intel-gfx, ville.syrjala

> == Series Details ==
> 
> Series: drm/i915: VLV/CHV two-stage watermarks
> URL   : https://patchwork.freedesktop.org/series/16712/
> State : warning
> 
> == Summary ==
> 
> Series 16712v1 drm/i915: VLV/CHV two-stage watermarks
> https://patchwork.freedesktop.org/api/1.0/series/16712/revisions/1/mbox/
> 
> Test drv_module_reload:
>         Subgroup basic-reload-inject:
>                 pass       -> DMESG-WARN (fi-ilk-650)
Still known issue: WARN_ON(dev_priv->gt.awake)
Did we had bug about this?

> 
> fi-ilk-650       total:247  pass:194  dwarn:1   dfail:0   fail:0   skip:52
 
> ac15a853c56c1a95a992f39ca2c1579e68b73a71 drm-tip: 2016y-12m-12d-15h-
> 25m-32s UTC integration manifest
> 8adda35 drm/i915: Kill level 0 wm hack for VLV/CHV
> f97c869 drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
> 7d57fef drm/i915: Sanitize VLV/CHV watermarks properly
> bbc58e0 drm/i915: Only use update_wm_{pre, post} for pre-ilk platforms
> a22a58b drm/i915: Nuke crtc->wm.cxsr_allowed
> 1d53011 drm/i915: Compute proper intermediate wms for vlv/cvh
> 5b4eb52 drm/i915: Skip useless watermark/FIFO related work on VLV/CHV
> when not needed
> ef4eac9 drm/i915: Compute vlv/chv wms the atomic way
> 3bb2ec4 drm/i915: Compute VLV/CHV FIFO sizes based on the PM2
> watermarks
> 1e2c256 drm/i915: Plop vlv/chv fifo sizes into crtc state d00a73d drm/i915:
> Plop vlv wm state into crtc_state a2fb13c drm/i915: Move vlv wms from crtc-
> >wm_state to crtc->wm.active.vlv
> cd6e5e3 drm/i915: Track plane fifo sizes under intel_crtc
> e414e82 drm/i915: Track visible planes in a bitmask
> 
> == Logs ==
> 
> For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3270/


Jani Saarinen
Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo


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

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

* Re: ✗ Fi.CI.BAT:  warning for drm/i915: VLV/CHV two-stage watermarks
  2016-12-13  7:42   ` Saarinen, Jani
@ 2016-12-13  8:40     ` Chris Wilson
  0 siblings, 0 replies; 47+ messages in thread
From: Chris Wilson @ 2016-12-13  8:40 UTC (permalink / raw)
  To: Saarinen, Jani; +Cc: intel-gfx

On Tue, Dec 13, 2016 at 07:42:54AM +0000, Saarinen, Jani wrote:
> > == Series Details ==
> > 
> > Series: drm/i915: VLV/CHV two-stage watermarks
> > URL   : https://patchwork.freedesktop.org/series/16712/
> > State : warning
> > 
> > == Summary ==
> > 
> > Series 16712v1 drm/i915: VLV/CHV two-stage watermarks
> > https://patchwork.freedesktop.org/api/1.0/series/16712/revisions/1/mbox/
> > 
> > Test drv_module_reload:
> >         Subgroup basic-reload-inject:
> >                 pass       -> DMESG-WARN (fi-ilk-650)
> Still known issue: WARN_ON(dev_priv->gt.awake)
> Did we had bug about this?

Yes, same symptoms, likely a slightly different bug (i.e. a bug in the
previous fix).
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 01/14] drm/i915: Track visible planes in a bitmask
  2016-12-12 20:35 ` [PATCH 01/14] drm/i915: Track visible planes in a bitmask ville.syrjala
@ 2016-12-15 14:56   ` Maarten Lankhorst
  2016-12-15 15:02     ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 14:56 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> In a lot of place we wish to know which planes on the crtc are actually
> visible, or how many of them there are. Let's start tracking that in a
> bitmask in the crtc state.
>
> We already track enabled planes (ie. ones with an fb and crtc specified by
> the user) but that's not quite the same thing as enabled planes may
> still end up being invisible due to clipping and whatnot.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_atomic_plane.c |  6 +++
>  drivers/gpu/drm/i915/intel_display.c      | 79 +++++++++++++++++++++----------
>  drivers/gpu/drm/i915/intel_drv.h          |  3 ++
>  3 files changed, 64 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
> index dbe9fb41ae53..7ec12edda4d4 100644
> --- a/drivers/gpu/drm/i915/intel_atomic_plane.c
> +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
> @@ -181,6 +181,12 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
>  	if (ret)
>  		return ret;
>  
> +	/* FIXME pre-g4x don't work like this */
> +	if (intel_state->base.visible)
> +		crtc_state->active_planes |= BIT(intel_plane->id);
> +	else
> +		crtc_state->active_planes &= ~BIT(intel_plane->id);
> +
>  	return intel_plane_atomic_calc_changes(&crtc_state->base, state);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index bc1af87789bc..3f027341b0f3 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2741,6 +2741,29 @@ update_state_fb(struct drm_plane *plane)
>  }
>  
>  static void
> +intel_set_plane_visible(struct intel_crtc_state *crtc_state,
> +			struct intel_plane_state *plane_state,
> +			bool visible)
> +{
> +	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
> +
> +	plane_state->base.visible = visible;
> +
> +	/* FIXME pre-g4x don't work like this */
> +	if (visible) {
> +		crtc_state->base.plane_mask |= BIT(drm_plane_index(&plane->base));
> +		crtc_state->active_planes |= BIT(plane->id);
> +	} else {
> +		crtc_state->base.plane_mask &= ~BIT(drm_plane_index(&plane->base));
> +		crtc_state->active_planes &= ~BIT(plane->id);
> +	}
> +
> +	DRM_DEBUG_KMS("%s active planes 0x%x\n",
> +		      crtc_state->base.crtc->name,
> +		      crtc_state->active_planes);
> +}
> +
> +static void
>  intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
>  			     struct intel_initial_plane_config *plane_config)
>  {
> @@ -2798,8 +2821,9 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
>  	 * simplest solution is to just disable the primary plane now and
>  	 * pretend the BIOS never had it enabled.
>  	 */
> -	to_intel_plane_state(plane_state)->base.visible = false;
> -	crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
> +	intel_set_plane_visible(to_intel_crtc_state(crtc_state),
> +				to_intel_plane_state(plane_state),
> +				false);
>  	intel_pre_disable_primary_noatomic(&intel_crtc->base);
>  	intel_plane->disable_plane(primary, &intel_crtc->base);
>  
> @@ -2826,7 +2850,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
>  	drm_framebuffer_reference(fb);
>  	primary->fb = primary->state->fb = fb;
>  	primary->crtc = primary->state->crtc = &intel_crtc->base;
> -	intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
> +
> +	intel_set_plane_visible(to_intel_crtc_state(intel_crtc->base.state),
> +				to_intel_plane_state(primary->state),
> +				true);
> +
>  	atomic_or(to_intel_plane(primary)->frontbuffer_bit,
>  		  &obj->frontbuffer_bits);
>  }
> @@ -12440,11 +12468,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>  	struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
>  	struct drm_crtc *crtc = crtc_state->crtc;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	struct drm_plane *plane = plane_state->plane;
> +	struct intel_plane *plane = to_intel_plane(plane_state->plane);
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct intel_plane_state *old_plane_state =
> -		to_intel_plane_state(plane->state);
> +		to_intel_plane_state(plane->base.state);
>  	bool mode_changed = needs_modeset(crtc_state);
>  	bool was_crtc_enabled = crtc->state->active;
>  	bool is_crtc_enabled = crtc_state->active;
> @@ -12452,7 +12480,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>  	struct drm_framebuffer *fb = plane_state->fb;
>  	int ret;
>  
> -	if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
> +	if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_CURSOR) {
>  		ret = skl_update_scaler_plane(
>  			to_intel_crtc_state(crtc_state),
>  			to_intel_plane_state(plane_state));
> @@ -12476,8 +12504,10 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>  	 * per-plane wm computation to the .check_plane() hook, and
>  	 * only combine the results from all planes in the current place?
>  	 */
> -	if (!is_crtc_enabled)
> +	if (!is_crtc_enabled) {
>  		to_intel_plane_state(plane_state)->base.visible = visible = false;
> +		to_intel_crtc_state(crtc_state)->active_planes &= ~BIT(plane->id);
> +	}
>  
>  	if (!was_visible && !visible)
>  		return 0;
> @@ -12489,13 +12519,12 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>  	turn_on = visible && (!was_visible || mode_changed);
>  
>  	DRM_DEBUG_ATOMIC("[CRTC:%d:%s] has [PLANE:%d:%s] with fb %i\n",
> -			 intel_crtc->base.base.id,
> -			 intel_crtc->base.name,
> -			 plane->base.id, plane->name,
> +			 intel_crtc->base.base.id, intel_crtc->base.name,
> +			 plane->base.base.id, plane->base.name,
>  			 fb ? fb->base.id : -1);
>  
>  	DRM_DEBUG_ATOMIC("[PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
> -			 plane->base.id, plane->name,
> +			 plane->base.base.id, plane->base.name,
>  			 was_visible, visible,
>  			 turn_off, turn_on, mode_changed);
>  
> @@ -12503,15 +12532,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>  		pipe_config->update_wm_pre = true;
>  
>  		/* must disable cxsr around plane enable/disable */
> -		if (plane->type != DRM_PLANE_TYPE_CURSOR)
> +		if (plane->id != PLANE_CURSOR)
>  			pipe_config->disable_cxsr = true;
>  	} else if (turn_off) {
>  		pipe_config->update_wm_post = true;
>  
>  		/* must disable cxsr around plane enable/disable */
> -		if (plane->type != DRM_PLANE_TYPE_CURSOR)
> +		if (plane->id != PLANE_CURSOR)
>  			pipe_config->disable_cxsr = true;
> -	} else if (intel_wm_need_update(plane, plane_state)) {
> +	} else if (intel_wm_need_update(&plane->base, plane_state)) {
>  		/* FIXME bollocks */
>  		pipe_config->update_wm_pre = true;
>  		pipe_config->update_wm_post = true;
> @@ -12523,7 +12552,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>  		to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
>  
>  	if (visible || was_visible)
> -		pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit;
> +		pipe_config->fb_bits |= plane->frontbuffer_bit;
>  
>  	/*
>  	 * WaCxSRDisabledForSpriteScaling:ivb
> @@ -12531,7 +12560,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>  	 * cstate->update_wm was already set above, so this flag will
>  	 * take effect when we commit and program watermarks.
>  	 */
> -	if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) &&
> +	if (plane->id == PLANE_SPRITE0 && IS_IVYBRIDGE(dev_priv) &&
>  	    needs_scaling(to_intel_plane_state(plane_state)) &&
>  	    !needs_scaling(old_plane_state))
>  		pipe_config->disable_lp_wm = true;
> @@ -16876,15 +16905,14 @@ static bool primary_get_hw_state(struct intel_plane *plane)
>  /* FIXME read out full plane state for all planes */
>  static void readout_plane_state(struct intel_crtc *crtc)
>  {
> -	struct drm_plane *primary = crtc->base.primary;
> -	struct intel_plane_state *plane_state =
> -		to_intel_plane_state(primary->state);
> +	struct intel_plane *primary = to_intel_plane(crtc->base.primary);
> +	bool visible;
>  
> -	plane_state->base.visible = crtc->active &&
> -		primary_get_hw_state(to_intel_plane(primary));
> +	visible = crtc->active && primary_get_hw_state(primary);
>  
> -	if (plane_state->base.visible)
> -		crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
> +	intel_set_plane_visible(to_intel_crtc_state(crtc->base.state),
> +				to_intel_plane_state(primary->base.state),
> +				visible);
>  }
>  
>  static void intel_modeset_readout_hw_state(struct drm_device *dev)
> @@ -17171,7 +17199,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
>  			c->primary->fb = NULL;
>  			c->primary->crtc = c->primary->state->crtc = NULL;
>  			update_state_fb(c->primary);
> -			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
> +
> +			intel_set_plane_visible(to_intel_crtc_state(c->state),
> +						to_intel_plane_state(c->primary->state),
> +						false);
>  		}
>  	}
>  }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 8f4ddca0f521..20ba8f48bc3b 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -669,6 +669,9 @@ struct intel_crtc_state {
>  
>  	/* Gamma mode programmed on the pipe */
>  	uint32_t gamma_mode;
> +
> +	/* bitmask of visible planes (enum plane_id) */
> +	u8 active_planes;
Can we change this to uint32_t 1<<drm_plane_index like the other masks?

plane_mask, connector_mask and encoder_mask use 1 << index.
Perhaps name it active_planes_mask too.

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

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

* Re: [PATCH 02/14] drm/i915: Track plane fifo sizes under intel_crtc
  2016-12-12 20:35 ` [PATCH 02/14] drm/i915: Track plane fifo sizes under intel_crtc ville.syrjala
@ 2016-12-15 14:58   ` Maarten Lankhorst
  2017-02-16 17:48     ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 14:58 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Track the plane fifo sizes under intel_crtc instead of under each
> intel_plane. Avoids looping over the planes in a bunch of places,
> and later we'll move this tracking into the crtc state properly.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_drv.h |   7 ++-
>  drivers/gpu/drm/i915/intel_pm.c  | 115 ++++++++++++++++-----------------------
>  2 files changed, 54 insertions(+), 68 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 20ba8f48bc3b..69b6f45e3eed 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -683,6 +683,10 @@ struct vlv_wm_state {
>  	bool cxsr;
>  };
>  
> +struct vlv_fifo_state {
> +	uint16_t plane[I915_MAX_PLANES];
> +};
> +
>  struct intel_crtc {
>  	struct drm_crtc base;
>  	enum pipe pipe;
> @@ -732,6 +736,8 @@ struct intel_crtc {
>  
>  		/* allow CxSR on this pipe */
>  		bool cxsr_allowed;
> +
> +		struct vlv_fifo_state fifo_state;
>  	} wm;
>  
>  	int scanline_offset;
> @@ -765,7 +771,6 @@ struct intel_plane_wm_parameters {
>  	bool scaled;
>  	u64 tiling;
>  	unsigned int rotation;
> -	uint16_t fifo_size;
>  };
intel_plane_wm_parameters can be removed entirely, fifo_size was the only member still being used there.
>  struct intel_plane {
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 06e55967f180..26af87f82608 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -393,15 +393,14 @@ static const int pessimal_latency_ns = 5000;
>  #define VLV_FIFO_START(dsparb, dsparb2, lo_shift, hi_shift) \
>  	((((dsparb) >> (lo_shift)) & 0xff) | ((((dsparb2) >> (hi_shift)) & 0x1) << 8))
>  
> -static int vlv_get_fifo_size(struct intel_plane *plane)
> +static void vlv_get_fifo_size(struct intel_crtc *crtc)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -	int sprite0_start, sprite1_start, size;
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +	struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
> +	enum pipe pipe = crtc->pipe;
> +	int sprite0_start, sprite1_start;
>  
> -	if (plane->id == PLANE_CURSOR)
> -		return 63;
> -
> -	switch (plane->pipe) {
> +	switch (pipe) {
>  		uint32_t dsparb, dsparb2, dsparb3;
>  	case PIPE_A:
>  		dsparb = I915_READ(DSPARB);
> @@ -422,26 +421,21 @@ static int vlv_get_fifo_size(struct intel_plane *plane)
>  		sprite1_start = VLV_FIFO_START(dsparb3, dsparb2, 8, 20);
>  		break;
>  	default:
> -		return 0;
> +		MISSING_CASE(pipe);
> +		return;
>  	}
>  
> -	switch (plane->id) {
> -	case PLANE_PRIMARY:
> -		size = sprite0_start;
> -		break;
> -	case PLANE_SPRITE0:
> -		size = sprite1_start - sprite0_start;
> -		break;
> -	case PLANE_SPRITE1:
> -		size = 512 - 1 - sprite1_start;
> -		break;
> -	default:
> -		return 0;
> -	}
> -
> -	DRM_DEBUG_KMS("%s FIFO size: %d\n", plane->base.name, size);
> +	fifo_state->plane[PLANE_PRIMARY] = sprite0_start;
> +	fifo_state->plane[PLANE_SPRITE0] = sprite1_start - sprite0_start;
> +	fifo_state->plane[PLANE_SPRITE1] = 511 - sprite1_start;
> +	fifo_state->plane[PLANE_CURSOR] = 63;
>  
> -	return size;
> +	DRM_DEBUG_KMS("Pipe %c FIFO size: %d/%d/%d/%d\n",
> +		      pipe_name(pipe),
> +		      fifo_state->plane[PLANE_PRIMARY],
> +		      fifo_state->plane[PLANE_SPRITE0],
> +		      fifo_state->plane[PLANE_SPRITE1],
> +		      fifo_state->plane[PLANE_CURSOR]);
>  }
>  
>  static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv, int plane)
> @@ -1019,8 +1013,9 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
>  
>  static void vlv_compute_fifo(struct intel_crtc *crtc)
>  {
> -	struct drm_device *dev = crtc->base.dev;
>  	struct vlv_wm_state *wm_state = &crtc->wm_state;
> +	struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
> +	struct drm_device *dev = crtc->base.dev;
>  	struct intel_plane *plane;
>  	unsigned int total_rate = 0;
>  	const int fifo_size = 512 - 1;
> @@ -1030,7 +1025,7 @@ static void vlv_compute_fifo(struct intel_crtc *crtc)
>  		struct intel_plane_state *state =
>  			to_intel_plane_state(plane->base.state);
>  
> -		if (plane->base.type == DRM_PLANE_TYPE_CURSOR)
> +		if (plane->id == PLANE_CURSOR)
>  			continue;
>  
>  		if (state->base.visible) {
> @@ -1044,19 +1039,19 @@ static void vlv_compute_fifo(struct intel_crtc *crtc)
>  			to_intel_plane_state(plane->base.state);
>  		unsigned int rate;
>  
> -		if (plane->base.type == DRM_PLANE_TYPE_CURSOR) {
> -			plane->wm.fifo_size = 63;
> +		if (plane->id == PLANE_CURSOR) {
> +			fifo_state->plane[plane->id] = 63;
>  			continue;
>  		}
>  
>  		if (!state->base.visible) {
> -			plane->wm.fifo_size = 0;
> +			fifo_state->plane[plane->id] = 0;
>  			continue;
>  		}
>  
>  		rate = drm_format_plane_cpp(state->base.fb->pixel_format, 0);
> -		plane->wm.fifo_size = fifo_size * rate / total_rate;
> -		fifo_left -= plane->wm.fifo_size;
> +		fifo_state->plane[plane->id] = fifo_size * rate / total_rate;
> +		fifo_left -= fifo_state->plane[plane->id];
>  	}
>  
>  	fifo_extra = DIV_ROUND_UP(fifo_left, wm_state->num_active_planes ?: 1);
> @@ -1068,16 +1063,16 @@ static void vlv_compute_fifo(struct intel_crtc *crtc)
>  		if (fifo_left == 0)
>  			break;
>  
> -		if (plane->base.type == DRM_PLANE_TYPE_CURSOR)
> +		if (plane->id == PLANE_CURSOR)
>  			continue;
>  
>  		/* give it all to the first plane if none are active */
> -		if (plane->wm.fifo_size == 0 &&
> +		if (fifo_state->plane[plane->id] == 0 &&
>  		    wm_state->num_active_planes)
>  			continue;
>  
>  		plane_extra = min(fifo_extra, fifo_left);
> -		plane->wm.fifo_size += plane_extra;
> +		fifo_state->plane[plane->id] += plane_extra;
>  		fifo_left -= plane_extra;
>  	}
>  
> @@ -1099,9 +1094,10 @@ static void vlv_invert_wms(struct intel_crtc *crtc)
>  
>  	for (level = 0; level < wm_state->num_levels; level++) {
>  		struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +		const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
>  		const int sr_fifo_size =
>  			INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
> -		struct intel_plane *plane;
> +		enum plane_id plane_id;
>  
>  		wm_state->sr[level].plane =
>  			vlv_invert_wm_value(wm_state->sr[level].plane,
> @@ -1110,10 +1106,10 @@ static void vlv_invert_wms(struct intel_crtc *crtc)
>  			vlv_invert_wm_value(wm_state->sr[level].cursor,
>  					    63);
>  
> -		for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
> -			wm_state->wm[level].plane[plane->id] =
> -				vlv_invert_wm_value(wm_state->wm[level].plane[plane->id],
> -						    plane->wm.fifo_size);
> +		for_each_plane_id_on_crtc(crtc, plane_id) {
> +			wm_state->wm[level].plane[plane_id] =
> +				vlv_invert_wm_value(wm_state->wm[level].plane[plane_id],
> +						    fifo_state->plane[plane_id]);
>  		}
>  	}
>  }
> @@ -1122,6 +1118,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>  	struct vlv_wm_state *wm_state = &crtc->wm_state;
> +	const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
>  	struct intel_plane *plane;
>  	int level;
>  
> @@ -1148,7 +1145,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
>  		/* normal watermarks */
>  		for (level = 0; level < wm_state->num_levels; level++) {
>  			int wm = vlv_compute_wm_level(crtc->config, state, level);
> -			int max_wm = plane->wm.fifo_size;
> +			int max_wm = fifo_state->plane[plane->id];
>  
>  			/* hack */
>  			if (WARN_ON(level == 0 && wm > max_wm))
> @@ -1192,32 +1189,16 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
>  
>  static void vlv_pipe_set_fifo_size(struct intel_crtc *crtc)
>  {
> -	struct drm_device *dev = crtc->base.dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -	struct intel_plane *plane;
> -	int sprite0_start = 0, sprite1_start = 0, fifo_size = 0;
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +	const struct vlv_fifo_state *fifo_state = &crtc->wm.fifo_state;
> +	int sprite0_start, sprite1_start, fifo_size;
>  
> -	for_each_intel_plane_on_crtc(dev, crtc, plane) {
> -		switch (plane->id) {
> -		case PLANE_PRIMARY:
> -			sprite0_start = plane->wm.fifo_size;
> -			break;
> -		case PLANE_SPRITE0:
> -			sprite1_start = sprite0_start + plane->wm.fifo_size;
> -			break;
> -		case PLANE_SPRITE1:
> -			fifo_size = sprite1_start + plane->wm.fifo_size;
> -			break;
> -		case PLANE_CURSOR:
> -			WARN_ON(plane->wm.fifo_size != 63);
> -			break;
> -		default:
> -			MISSING_CASE(plane->id);
> -			break;
> -		}
> -	}
> +	sprite0_start = fifo_state->plane[PLANE_PRIMARY];
> +	sprite1_start = fifo_state->plane[PLANE_SPRITE0] + sprite0_start;
> +	fifo_size = fifo_state->plane[PLANE_SPRITE1] + sprite1_start;
>  
> -	WARN_ON(fifo_size != 512 - 1);
> +	WARN_ON(fifo_state->plane[PLANE_CURSOR] != 63);
> +	WARN_ON(fifo_size != 511);
>  
>  	DRM_DEBUG_KMS("Pipe %c FIFO split %d / %d / %d\n",
>  		      pipe_name(crtc->pipe), sprite0_start,
> @@ -4532,14 +4513,14 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct vlv_wm_values *wm = &dev_priv->wm.vlv;
> -	struct intel_plane *plane;
> +	struct intel_crtc *crtc;
>  	enum pipe pipe;
>  	u32 val;
>  
>  	vlv_read_wm_values(dev_priv, wm);
>  
> -	for_each_intel_plane(dev, plane)
> -		plane->wm.fifo_size = vlv_get_fifo_size(plane);
> +	for_each_intel_crtc(dev, crtc)
> +		vlv_get_fifo_size(crtc);
>  
>  	wm->cxsr = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
>  	wm->level = VLV_WM_LEVEL_PM2;


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

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

* Re: [PATCH 01/14] drm/i915: Track visible planes in a bitmask
  2016-12-15 14:56   ` Maarten Lankhorst
@ 2016-12-15 15:02     ` Ville Syrjälä
  2016-12-15 17:11       ` Maarten Lankhorst
  0 siblings, 1 reply; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 15:02 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 03:56:03PM +0100, Maarten Lankhorst wrote:
> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > In a lot of place we wish to know which planes on the crtc are actually
> > visible, or how many of them there are. Let's start tracking that in a
> > bitmask in the crtc state.
> >
> > We already track enabled planes (ie. ones with an fb and crtc specified by
> > the user) but that's not quite the same thing as enabled planes may
> > still end up being invisible due to clipping and whatnot.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_atomic_plane.c |  6 +++
> >  drivers/gpu/drm/i915/intel_display.c      | 79 +++++++++++++++++++++----------
> >  drivers/gpu/drm/i915/intel_drv.h          |  3 ++
> >  3 files changed, 64 insertions(+), 24 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
> > index dbe9fb41ae53..7ec12edda4d4 100644
> > --- a/drivers/gpu/drm/i915/intel_atomic_plane.c
> > +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
> > @@ -181,6 +181,12 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
> >  	if (ret)
> >  		return ret;
> >  
> > +	/* FIXME pre-g4x don't work like this */
> > +	if (intel_state->base.visible)
> > +		crtc_state->active_planes |= BIT(intel_plane->id);
> > +	else
> > +		crtc_state->active_planes &= ~BIT(intel_plane->id);
> > +
> >  	return intel_plane_atomic_calc_changes(&crtc_state->base, state);
> >  }
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index bc1af87789bc..3f027341b0f3 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2741,6 +2741,29 @@ update_state_fb(struct drm_plane *plane)
> >  }
> >  
> >  static void
> > +intel_set_plane_visible(struct intel_crtc_state *crtc_state,
> > +			struct intel_plane_state *plane_state,
> > +			bool visible)
> > +{
> > +	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
> > +
> > +	plane_state->base.visible = visible;
> > +
> > +	/* FIXME pre-g4x don't work like this */
> > +	if (visible) {
> > +		crtc_state->base.plane_mask |= BIT(drm_plane_index(&plane->base));
> > +		crtc_state->active_planes |= BIT(plane->id);
> > +	} else {
> > +		crtc_state->base.plane_mask &= ~BIT(drm_plane_index(&plane->base));
> > +		crtc_state->active_planes &= ~BIT(plane->id);
> > +	}
> > +
> > +	DRM_DEBUG_KMS("%s active planes 0x%x\n",
> > +		      crtc_state->base.crtc->name,
> > +		      crtc_state->active_planes);
> > +}
> > +
> > +static void
> >  intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
> >  			     struct intel_initial_plane_config *plane_config)
> >  {
> > @@ -2798,8 +2821,9 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
> >  	 * simplest solution is to just disable the primary plane now and
> >  	 * pretend the BIOS never had it enabled.
> >  	 */
> > -	to_intel_plane_state(plane_state)->base.visible = false;
> > -	crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
> > +	intel_set_plane_visible(to_intel_crtc_state(crtc_state),
> > +				to_intel_plane_state(plane_state),
> > +				false);
> >  	intel_pre_disable_primary_noatomic(&intel_crtc->base);
> >  	intel_plane->disable_plane(primary, &intel_crtc->base);
> >  
> > @@ -2826,7 +2850,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
> >  	drm_framebuffer_reference(fb);
> >  	primary->fb = primary->state->fb = fb;
> >  	primary->crtc = primary->state->crtc = &intel_crtc->base;
> > -	intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
> > +
> > +	intel_set_plane_visible(to_intel_crtc_state(intel_crtc->base.state),
> > +				to_intel_plane_state(primary->state),
> > +				true);
> > +
> >  	atomic_or(to_intel_plane(primary)->frontbuffer_bit,
> >  		  &obj->frontbuffer_bits);
> >  }
> > @@ -12440,11 +12468,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >  	struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
> >  	struct drm_crtc *crtc = crtc_state->crtc;
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > -	struct drm_plane *plane = plane_state->plane;
> > +	struct intel_plane *plane = to_intel_plane(plane_state->plane);
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct intel_plane_state *old_plane_state =
> > -		to_intel_plane_state(plane->state);
> > +		to_intel_plane_state(plane->base.state);
> >  	bool mode_changed = needs_modeset(crtc_state);
> >  	bool was_crtc_enabled = crtc->state->active;
> >  	bool is_crtc_enabled = crtc_state->active;
> > @@ -12452,7 +12480,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >  	struct drm_framebuffer *fb = plane_state->fb;
> >  	int ret;
> >  
> > -	if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
> > +	if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_CURSOR) {
> >  		ret = skl_update_scaler_plane(
> >  			to_intel_crtc_state(crtc_state),
> >  			to_intel_plane_state(plane_state));
> > @@ -12476,8 +12504,10 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >  	 * per-plane wm computation to the .check_plane() hook, and
> >  	 * only combine the results from all planes in the current place?
> >  	 */
> > -	if (!is_crtc_enabled)
> > +	if (!is_crtc_enabled) {
> >  		to_intel_plane_state(plane_state)->base.visible = visible = false;
> > +		to_intel_crtc_state(crtc_state)->active_planes &= ~BIT(plane->id);
> > +	}
> >  
> >  	if (!was_visible && !visible)
> >  		return 0;
> > @@ -12489,13 +12519,12 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >  	turn_on = visible && (!was_visible || mode_changed);
> >  
> >  	DRM_DEBUG_ATOMIC("[CRTC:%d:%s] has [PLANE:%d:%s] with fb %i\n",
> > -			 intel_crtc->base.base.id,
> > -			 intel_crtc->base.name,
> > -			 plane->base.id, plane->name,
> > +			 intel_crtc->base.base.id, intel_crtc->base.name,
> > +			 plane->base.base.id, plane->base.name,
> >  			 fb ? fb->base.id : -1);
> >  
> >  	DRM_DEBUG_ATOMIC("[PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
> > -			 plane->base.id, plane->name,
> > +			 plane->base.base.id, plane->base.name,
> >  			 was_visible, visible,
> >  			 turn_off, turn_on, mode_changed);
> >  
> > @@ -12503,15 +12532,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >  		pipe_config->update_wm_pre = true;
> >  
> >  		/* must disable cxsr around plane enable/disable */
> > -		if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > +		if (plane->id != PLANE_CURSOR)
> >  			pipe_config->disable_cxsr = true;
> >  	} else if (turn_off) {
> >  		pipe_config->update_wm_post = true;
> >  
> >  		/* must disable cxsr around plane enable/disable */
> > -		if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > +		if (plane->id != PLANE_CURSOR)
> >  			pipe_config->disable_cxsr = true;
> > -	} else if (intel_wm_need_update(plane, plane_state)) {
> > +	} else if (intel_wm_need_update(&plane->base, plane_state)) {
> >  		/* FIXME bollocks */
> >  		pipe_config->update_wm_pre = true;
> >  		pipe_config->update_wm_post = true;
> > @@ -12523,7 +12552,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >  		to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
> >  
> >  	if (visible || was_visible)
> > -		pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit;
> > +		pipe_config->fb_bits |= plane->frontbuffer_bit;
> >  
> >  	/*
> >  	 * WaCxSRDisabledForSpriteScaling:ivb
> > @@ -12531,7 +12560,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >  	 * cstate->update_wm was already set above, so this flag will
> >  	 * take effect when we commit and program watermarks.
> >  	 */
> > -	if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) &&
> > +	if (plane->id == PLANE_SPRITE0 && IS_IVYBRIDGE(dev_priv) &&
> >  	    needs_scaling(to_intel_plane_state(plane_state)) &&
> >  	    !needs_scaling(old_plane_state))
> >  		pipe_config->disable_lp_wm = true;
> > @@ -16876,15 +16905,14 @@ static bool primary_get_hw_state(struct intel_plane *plane)
> >  /* FIXME read out full plane state for all planes */
> >  static void readout_plane_state(struct intel_crtc *crtc)
> >  {
> > -	struct drm_plane *primary = crtc->base.primary;
> > -	struct intel_plane_state *plane_state =
> > -		to_intel_plane_state(primary->state);
> > +	struct intel_plane *primary = to_intel_plane(crtc->base.primary);
> > +	bool visible;
> >  
> > -	plane_state->base.visible = crtc->active &&
> > -		primary_get_hw_state(to_intel_plane(primary));
> > +	visible = crtc->active && primary_get_hw_state(primary);
> >  
> > -	if (plane_state->base.visible)
> > -		crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
> > +	intel_set_plane_visible(to_intel_crtc_state(crtc->base.state),
> > +				to_intel_plane_state(primary->base.state),
> > +				visible);
> >  }
> >  
> >  static void intel_modeset_readout_hw_state(struct drm_device *dev)
> > @@ -17171,7 +17199,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
> >  			c->primary->fb = NULL;
> >  			c->primary->crtc = c->primary->state->crtc = NULL;
> >  			update_state_fb(c->primary);
> > -			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
> > +
> > +			intel_set_plane_visible(to_intel_crtc_state(c->state),
> > +						to_intel_plane_state(c->primary->state),
> > +						false);
> >  		}
> >  	}
> >  }
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 8f4ddca0f521..20ba8f48bc3b 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -669,6 +669,9 @@ struct intel_crtc_state {
> >  
> >  	/* Gamma mode programmed on the pipe */
> >  	uint32_t gamma_mode;
> > +
> > +	/* bitmask of visible planes (enum plane_id) */
> > +	u8 active_planes;
> Can we change this to uint32_t 1<<drm_plane_index like the other masks?
> 
> plane_mask, connector_mask and encoder_mask use 1 << index.
> Perhaps name it active_planes_mask too.

The way I use it wouldn't lend itself well to that. I don't have any
plane structs around in a bunch of the places where this gets used.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH i-g-t] tests: Add kms_plane_blinker
  2016-12-12 20:35 ` [PATCH i-g-t] tests: Add kms_plane_blinker ville.syrjala
@ 2016-12-15 15:17   ` Maarten Lankhorst
  2016-12-15 15:23     ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 15:17 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Add a test to try out all the different plane enable/disable
> order permutations.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Didn't look through the test, but sounds like

kms_atomic_transitions.plane-*-transition-* ?

Although that one tests a few more edge cases like modeset disable and nonblocking updates..

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

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

* Re: [PATCH i-g-t] tests: Add kms_plane_blinker
  2016-12-15 15:17   ` Maarten Lankhorst
@ 2016-12-15 15:23     ` Ville Syrjälä
  2016-12-15 15:28       ` Maarten Lankhorst
  0 siblings, 1 reply; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 15:23 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 04:17:45PM +0100, Maarten Lankhorst wrote:
> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Add a test to try out all the different plane enable/disable
> > order permutations.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Didn't look through the test, but sounds like
> 
> kms_atomic_transitions.plane-*-transition-* ?
> 
> Although that one tests a few more edge cases like modeset disable and nonblocking updates..

I don't immediately see where it would try all the permutations, nor can
I see any crc_nonblock() stuff so doesn't seem like it could even spot
transient errors.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH i-g-t] tests: Add kms_plane_blinker
  2016-12-15 15:23     ` Ville Syrjälä
@ 2016-12-15 15:28       ` Maarten Lankhorst
  2016-12-15 15:36         ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 15:28 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

Op 15-12-16 om 16:23 schreef Ville Syrjälä:
> On Thu, Dec 15, 2016 at 04:17:45PM +0100, Maarten Lankhorst wrote:
>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> Add a test to try out all the different plane enable/disable
>>> order permutations.
>>>
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Didn't look through the test, but sounds like
>>
>> kms_atomic_transitions.plane-*-transition-* ?
>>
>> Although that one tests a few more edge cases like modeset disable and nonblocking updates..
> I don't immediately see where it would try all the permutations, nor can
> I see any crc_nonblock() stuff so doesn't seem like it could even spot
> transient errors.
>
I haven't done any crc test there yet, but the double loop in run_transition_test handles all combinations of planes.

~Maarten

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

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

* Re: [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way
  2016-12-12 20:35 ` [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way ville.syrjala
@ 2016-12-15 15:30   ` Maarten Lankhorst
  2016-12-15 15:38     ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 15:30 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Start computing the vlv/chv watermarks the atomic way, from the
> .compute_pipe_wm() hook. We'll recompute the actual watermarks
> for only planes that are part of the state, the other planes will
> keep their watermark from the last time it was computed.
>
> And the actual watermark programming will happen from the
> .initial_watermarks() hook. For now we'll just compute the
> optimal watermarks, and we'll hook up the intermediate
> watermarks properly later.
>
> The DSPARB registers responsible for the FIFO paritioning are
> double buffered, so they will be programming from
> intel_begin_crtc_commit().
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |   8 +
>  drivers/gpu/drm/i915/intel_display.c |  21 ++-
>  drivers/gpu/drm/i915/intel_drv.h     |   2 -
>  drivers/gpu/drm/i915/intel_pm.c      | 327 +++++++++++++++++++++++------------
>  4 files changed, 238 insertions(+), 120 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 20bc04d5e617..f23698f99685 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -493,6 +493,14 @@ struct i915_hotplug {
>  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
>  		for_each_if ((1 << (domain)) & (mask))
>  
> +#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \
> +	for ((__i) = 0; \
> +	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
> +		     ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
> +		      (plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \
> +	     (__i)++) \
> +		for_each_if (plane_state)
> +
>  struct drm_i915_private;
>  struct i915_mm_struct;
>  struct i915_mmu_object;
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3f027341b0f3..8d80873b6643 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6736,6 +6736,8 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>  static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
>  				   struct drm_atomic_state *old_state)
>  {
> +	struct intel_atomic_state *old_intel_state =
> +		to_intel_atomic_state(old_state);
>  	struct drm_crtc *crtc = pipe_config->base.crtc;
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> @@ -6780,7 +6782,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
>  
>  	intel_color_load_luts(&pipe_config->base);
>  
> -	intel_update_watermarks(intel_crtc);
> +	dev_priv->display.initial_watermarks(old_intel_state,
> +					     pipe_config);
>  	intel_enable_pipe(intel_crtc);
>  
>  	assert_vblank_disabled(crtc);
> @@ -6897,6 +6900,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
>  
>  	if (!IS_GEN2(dev_priv))
>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
> +
> +	if (!dev_priv->display.initial_watermarks)
> +		intel_update_watermarks(intel_crtc);
>  }
>  
>  static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
> @@ -12980,10 +12986,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
>  static void
>  clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>  {
> +	struct drm_i915_private *dev_priv =
> +		to_i915(crtc_state->base.crtc->dev);
>  	struct drm_crtc_state tmp_state;
>  	struct intel_crtc_scaler_state scaler_state;
>  	struct intel_dpll_hw_state dpll_hw_state;
>  	struct intel_shared_dpll *shared_dpll;
> +	struct intel_crtc_wm_state wm_state;
>  	bool force_thru;
>  
>  	/* FIXME: before the switch to atomic started, a new pipe_config was
> @@ -12996,6 +13005,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>  	shared_dpll = crtc_state->shared_dpll;
>  	dpll_hw_state = crtc_state->dpll_hw_state;
>  	force_thru = crtc_state->pch_pfit.force_thru;
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		wm_state = crtc_state->wm;
>  
>  	memset(crtc_state, 0, sizeof *crtc_state);
>  
> @@ -13004,6 +13015,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>  	crtc_state->shared_dpll = shared_dpll;
>  	crtc_state->dpll_hw_state = dpll_hw_state;
>  	crtc_state->pch_pfit.force_thru = force_thru;
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		crtc_state->wm = wm_state;
Is this required? In skl we throw away everything and rebuild using drm_atomic_crtc_state_for_each_plane_state.
>  
>  static int
> @@ -14497,12 +14510,12 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
>  				/*
>  				 * Make sure we don't call initial_watermarks
>  				 * for ILK-style watermark updates.
> +				 *
> +				 * No clue what this is supposed to achieve.
>  				 */
> -				if (dev_priv->display.atomic_update_watermarks)
> +				if (INTEL_GEN(dev_priv) >= 9)
>  					dev_priv->display.initial_watermarks(intel_state,
>  									     to_intel_crtc_state(crtc->state));
> -				else
> -					intel_update_watermarks(intel_crtc);
>  			}
>  		}
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 0e199db26bda..66668c18a47a 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -490,9 +490,7 @@ enum vlv_wm_level {
>  struct vlv_wm_state {
>  	struct vlv_pipe_wm wm[NUM_VLV_WM_LEVELS];
>  	struct vlv_sr_wm sr[NUM_VLV_WM_LEVELS];
> -	uint8_t num_active_planes;
>  	uint8_t num_levels;
> -	uint8_t level;
>  	bool cxsr;
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 233e63224649..f68b46eed224 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1072,6 +1072,28 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
>  	return 0;
>  }
>  
> +static int vlv_num_wm_levels(struct drm_i915_private *dev_priv)
> +{
> +	return dev_priv->wm.max_level + 1;
> +}
> +
> +/* mark all levels starting from 'level' as invalid */
> +static void vlv_invalidate_wms(struct intel_crtc *crtc,
> +			       struct vlv_wm_state *wm_state, int level)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +
> +	for (; level < vlv_num_wm_levels(dev_priv); level++) {
> +		enum plane_id plane_id;
> +
> +		for_each_plane_id_on_crtc(crtc, plane_id)
> +			wm_state->wm[level].plane[plane_id] = USHRT_MAX;
> +
> +		wm_state->sr[level].cursor = USHRT_MAX;
> +		wm_state->sr[level].plane = USHRT_MAX;
> +	}
> +}
> +
>  static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
>  {
>  	if (wm > fifo_size)
> @@ -1080,108 +1102,162 @@ static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
>  		return fifo_size - wm;
>  }
>  
> -static void vlv_invert_wms(struct intel_crtc_state *crtc_state)
> +/* starting from 'level' set all higher levels to 'value' */
> +static void vlv_plane_wm_set(struct intel_crtc_state *crtc_state,
> +			     int level, enum plane_id plane_id, u16 value)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
> +	int num_levels = vlv_num_wm_levels(dev_priv);
> +
> +	for (; level < num_levels; level++) {
> +		struct vlv_pipe_wm *noninverted =
> +			&crtc_state->wm.vlv.noninverted[level];
> +
> +		noninverted->plane[plane_id] = value;
> +	}
> +}
> +
> +static void vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
> +				 const struct intel_plane_state *plane_state)
> +{
> +	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
> +	enum plane_id plane_id = plane->id;
> +	int num_levels = vlv_num_wm_levels(to_i915(plane->base.dev));
> +	int level;
> +
> +	if (!plane_state->base.visible) {
> +		vlv_plane_wm_set(crtc_state, 0, plane_id, 0);
> +		return;
> +	}
> +
> +	for (level = 0; level < num_levels; level++) {
> +		struct vlv_pipe_wm *noninverted =
> +			&crtc_state->wm.vlv.noninverted[level];
> +		int wm = vlv_compute_wm_level(crtc_state, plane_state, level);
> +		int max_wm = plane_id == PLANE_CURSOR ? 63 : 511;
> +
> +		/* FIXME just bail */
> +		if (WARN_ON(level == 0 && wm > max_wm))
> +			wm = max_wm;
> +
> +		if (wm > max_wm)
> +			break;
> +
> +		noninverted->plane[plane_id] = wm;
> +	}
> +
> +	/* mark all higher levels as invalid */
> +	vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
> +
> +	DRM_DEBUG_KMS("%s wms: [0]=%d,[1]=%d,[2]=%d\n",
> +		      plane->base.name,
> +		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2].plane[plane_id],
> +		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM5].plane[plane_id],
> +		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_DDR_DVFS].plane[plane_id]);
> +}
> +
> +static bool vlv_plane_wm_is_valid(const struct intel_crtc_state *crtc_state,
> +				  enum plane_id plane_id, int level)
> +{
> +	const struct vlv_pipe_wm *noninverted =
> +		&crtc_state->wm.vlv.noninverted[level];
> +	const struct vlv_fifo_state *fifo_state =
> +		&crtc_state->wm.vlv.fifo_state;
> +
> +	return noninverted->plane[plane_id] <= fifo_state->plane[plane_id];
> +}
> +
> +static bool vlv_crtc_wm_is_valid(const struct intel_crtc_state *crtc_state, int level)
> +{
> +	return vlv_plane_wm_is_valid(crtc_state, PLANE_PRIMARY, level) &&
> +		vlv_plane_wm_is_valid(crtc_state, PLANE_SPRITE0, level) &&
> +		vlv_plane_wm_is_valid(crtc_state, PLANE_SPRITE1, level) &&
> +		vlv_plane_wm_is_valid(crtc_state, PLANE_CURSOR, level);
> +}
> +
> +static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
>  {
>  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +	struct intel_atomic_state *state =
> +		to_intel_atomic_state(crtc_state->base.state);
>  	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
>  	const struct vlv_fifo_state *fifo_state =
>  		&crtc_state->wm.vlv.fifo_state;
> -	int level;
> +	int num_active_planes = hweight32(crtc_state->active_planes &
> +					  ~BIT(PLANE_CURSOR));
> +	struct intel_plane_state *plane_state;
> +	struct intel_plane *plane;
> +	enum plane_id plane_id;
> +	int level, ret, i;
> +
> +	for_each_intel_plane_in_state(state, plane, plane_state, i) {
> +		const struct intel_plane_state *old_plane_state =
> +			to_intel_plane_state(plane->base.state);
> +
> +		if (plane_state->base.crtc != &crtc->base &&
> +		    old_plane_state->base.crtc != &crtc->base)
> +			continue;
> +
> +		vlv_plane_wm_compute(crtc_state, plane_state);
> +	}
> +
> +	/* initially allow all levels */
> +	wm_state->num_levels = vlv_num_wm_levels(dev_priv);
> +	/*
> +	 * Note that enabling cxsr with no primary/sprite planes
> +	 * enabled can wedge the pipe. Hence we only allow cxsr
> +	 * with exactly one enabled primary/sprite plane.
> +	 */
> +	wm_state->cxsr = crtc->pipe != PIPE_C &&
> +		crtc->wm.cxsr_allowed && num_active_planes == 1;
> +
> +	ret = vlv_compute_fifo(crtc_state);
> +	if (ret)
> +		return ret;
>  
>  	for (level = 0; level < wm_state->num_levels; level++) {
> -		struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -		const int sr_fifo_size =
> -			INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
> -		enum plane_id plane_id;
> +		const struct vlv_pipe_wm *noninverted =
> +			&crtc_state->wm.vlv.noninverted[level];
> +		const int sr_fifo_size = INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
> +
> +		if (!vlv_crtc_wm_is_valid(crtc_state, level))
> +			break;
> +
> +		for_each_plane_id_on_crtc(crtc, plane_id) {
> +			wm_state->wm[level].plane[plane_id] =
> +				vlv_invert_wm_value(noninverted->plane[plane_id],
> +						    fifo_state->plane[plane_id]);
> +		}
>  
>  		wm_state->sr[level].plane =
> -			vlv_invert_wm_value(wm_state->sr[level].plane,
> +			vlv_invert_wm_value(max3(noninverted->plane[PLANE_PRIMARY],
> +						 noninverted->plane[PLANE_SPRITE0],
> +						 noninverted->plane[PLANE_SPRITE1]),
>  					    sr_fifo_size);
> +
>  		wm_state->sr[level].cursor =
> -			vlv_invert_wm_value(wm_state->sr[level].cursor,
> +			vlv_invert_wm_value(noninverted->plane[PLANE_CURSOR],
>  					    63);
> -
> -		for_each_plane_id_on_crtc(crtc, plane_id) {
> -			wm_state->wm[level].plane[plane_id] =
> -				vlv_invert_wm_value(wm_state->wm[level].plane[plane_id],
> -						    fifo_state->plane[plane_id]);
> -		}
> -	}
> -}
> -
> -static void vlv_compute_wm(struct intel_crtc_state *crtc_state)
> -{
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
> -	struct intel_plane *plane;
> -	int level;
> -
> -	memset(wm_state, 0, sizeof(*wm_state));
> -	memset(crtc_state->wm.vlv.noninverted, 0,
> -	       sizeof(crtc_state->wm.vlv.noninverted));
> -
> -	wm_state->cxsr = crtc->pipe != PIPE_C && crtc->wm.cxsr_allowed;
> -	wm_state->num_levels = dev_priv->wm.max_level + 1;
> -
> -	wm_state->num_active_planes = 0;
> -
> -	if (wm_state->num_active_planes != 1)
> -		wm_state->cxsr = false;
> -
> -	for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
> -		struct intel_plane_state *state =
> -			to_intel_plane_state(plane->base.state);
> -
> -		if (!state->base.visible)
> -			continue;
> -
> -		for (level = 0; level < wm_state->num_levels; level++) {
> -			struct vlv_pipe_wm *noninverted =
> -				&crtc_state->wm.vlv.noninverted[level];
> -			int wm = vlv_compute_wm_level(crtc_state, state, level);
> -			int max_wm = plane->id == PLANE_CURSOR ? 63 : 511;
> -
> -			/* hack */
> -			if (WARN_ON(level == 0 && wm > max_wm))
> -				wm = max_wm;
> -
> -			if (wm > max_wm)
> -				break;
> -
> -			noninverted->plane[plane->id] = wm;
> -		}
> -
> -		wm_state->num_levels = level;
>  	}
>  
> -	vlv_compute_fifo(crtc_state);
> +	if (level == 0)
> +		return -EINVAL;
>  
> -	for (level = 0; level < wm_state->num_levels; level++) {
> -		struct vlv_pipe_wm *noninverted =
> -			&crtc_state->wm.vlv.noninverted[level];
> +	/* limit to only levels we can actually handle */
> +	wm_state->num_levels = level;
>  
> -		wm_state->wm[level] = *noninverted;
> -
> -		wm_state->sr[level].plane = max3(noninverted->plane[PLANE_PRIMARY],
> -						 noninverted->plane[PLANE_SPRITE0],
> -						 noninverted->plane[PLANE_SPRITE1]);
> -		wm_state->sr[level].cursor = noninverted->plane[PLANE_CURSOR];
> -	}
> -
> -	/* clear any (partially) filled invalid levels */
> -	for (level = wm_state->num_levels; level < dev_priv->wm.max_level + 1; level++) {
> -		memset(&wm_state->wm[level], 0, sizeof(wm_state->wm[level]));
> -		memset(&wm_state->sr[level], 0, sizeof(wm_state->sr[level]));
> -	}
> +	/* invalidate the higher levels */
> +	vlv_invalidate_wms(crtc, wm_state, level);
>  
> -	vlv_invert_wms(crtc_state);
> +	return 0;
>  }
>  
>  #define VLV_FIFO(plane, value) \
>  	(((value) << DSPARB_ ## plane ## _SHIFT_VLV) & DSPARB_ ## plane ## _MASK_VLV)
>  
> -static void vlv_pipe_set_fifo_size(const struct intel_crtc_state *crtc_state)
> +static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
> +				   struct intel_crtc_state *crtc_state)
>  {
>  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
>  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> @@ -1196,10 +1272,6 @@ static void vlv_pipe_set_fifo_size(const struct intel_crtc_state *crtc_state)
>  	WARN_ON(fifo_state->plane[PLANE_CURSOR] != 63);
>  	WARN_ON(fifo_size != 511);
>  
> -	DRM_DEBUG_KMS("Pipe %c FIFO split %d / %d / %d\n",
> -		      pipe_name(crtc->pipe), sprite0_start,
> -		      sprite1_start, fifo_size);
> -
>  	spin_lock(&dev_priv->wm.dsparb_lock);
>  
>  	switch (crtc->pipe) {
> @@ -1298,11 +1370,8 @@ static void vlv_merge_wm(struct drm_i915_private *dev_priv,
>  		const struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
>  		enum pipe pipe = crtc->pipe;
>  
> -		if (!crtc->active)
> -			continue;
> -
>  		wm->pipe[pipe] = wm_state->wm[wm->level];
> -		if (wm->cxsr)
> +		if (crtc->active && wm->cxsr)
>  			wm->sr = wm_state->sr[wm->level];
>  
>  		wm->ddl[pipe].plane[PLANE_PRIMARY] = DDL_PRECISION_HIGH | 2;
> @@ -1322,24 +1391,15 @@ static bool is_enabling(int old, int new, int threshold)
>  	return old < threshold && new >= threshold;
>  }
>  
> -static void vlv_update_wm(struct intel_crtc *crtc)
> +static void vlv_program_watermarks(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -	struct intel_crtc_state *crtc_state =
> -		to_intel_crtc_state(crtc->base.state);
> -	enum pipe pipe = crtc->pipe;
>  	struct vlv_wm_values *old_wm = &dev_priv->wm.vlv;
>  	struct vlv_wm_values new_wm = {};
>  
> -	vlv_compute_wm(crtc_state);
> -	crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
>  	vlv_merge_wm(dev_priv, &new_wm);
>  
> -	if (memcmp(old_wm, &new_wm, sizeof(new_wm)) == 0) {
> -		/* FIXME should be part of crtc atomic commit */
> -		vlv_pipe_set_fifo_size(crtc_state);
> +	if (memcmp(old_wm, &new_wm, sizeof(new_wm)) == 0)
>  		return;
> -	}
>  
>  	if (is_disabling(old_wm->level, new_wm.level, VLV_WM_LEVEL_DDR_DVFS))
>  		chv_set_memory_dvfs(dev_priv, false);
> @@ -1350,17 +1410,8 @@ static void vlv_update_wm(struct intel_crtc *crtc)
>  	if (is_disabling(old_wm->cxsr, new_wm.cxsr, true))
>  		_intel_set_memory_cxsr(dev_priv, false);
>  
> -	/* FIXME should be part of crtc atomic commit */
> -	vlv_pipe_set_fifo_size(crtc_state);
> -
>  	vlv_write_wm_values(dev_priv, &new_wm);
>  
> -	DRM_DEBUG_KMS("Setting FIFO watermarks - %c: plane=%d, cursor=%d, "
> -		      "sprite0=%d, sprite1=%d, SR: plane=%d, cursor=%d level=%d cxsr=%d\n",
> -		      pipe_name(pipe), new_wm.pipe[pipe].plane[PLANE_PRIMARY], new_wm.pipe[pipe].plane[PLANE_CURSOR],
> -		      new_wm.pipe[pipe].plane[PLANE_SPRITE0], new_wm.pipe[pipe].plane[PLANE_SPRITE1],
> -		      new_wm.sr.plane, new_wm.sr.cursor, new_wm.level, new_wm.cxsr);
> -
>  	if (is_enabling(old_wm->cxsr, new_wm.cxsr, true))
>  		_intel_set_memory_cxsr(dev_priv, true);
>  
> @@ -1373,6 +1424,18 @@ static void vlv_update_wm(struct intel_crtc *crtc)
>  	*old_wm = new_wm;
>  }
>  
> +static void vlv_initial_watermarks(struct intel_atomic_state *state,
> +				   struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> +
> +	mutex_lock(&dev_priv->wm.wm_mutex);
> +	crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
> +	vlv_program_watermarks(dev_priv);
> +	mutex_unlock(&dev_priv->wm.wm_mutex);
> +}
> +
>  #define single_plane_enabled(mask) is_power_of_2(mask)
>  
>  static void g4x_update_wm(struct intel_crtc *crtc)
> @@ -4512,14 +4575,10 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct vlv_wm_values *wm = &dev_priv->wm.vlv;
>  	struct intel_crtc *crtc;
> -	enum pipe pipe;
>  	u32 val;
>  
>  	vlv_read_wm_values(dev_priv, wm);
>  
> -	for_each_intel_crtc(dev, crtc)
> -		vlv_get_fifo_size(to_intel_crtc_state(crtc->base.state));
> -
>  	wm->cxsr = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
>  	wm->level = VLV_WM_LEVEL_PM2;
>  
> @@ -4557,13 +4616,51 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
>  		mutex_unlock(&dev_priv->rps.hw_lock);
>  	}
>  
> -	for_each_pipe(dev_priv, pipe)
> +	for_each_intel_crtc(dev, crtc) {
> +		struct intel_crtc_state *crtc_state =
> +			to_intel_crtc_state(crtc->base.state);
> +		struct vlv_wm_state *active = &crtc->wm.active.vlv;
> +		const struct vlv_fifo_state *fifo_state =
> +			&crtc_state->wm.vlv.fifo_state;
> +		enum pipe pipe = crtc->pipe;
> +		enum plane_id plane_id;
> +		int level;
> +
> +		vlv_get_fifo_size(crtc_state);
> +
> +		active->num_levels = wm->level + 1;
> +		active->cxsr = wm->cxsr;
> +
> +		/* FIXME sanitize things more */
> +		for (level = 0; level < active->num_levels; level++) {
> +			struct vlv_pipe_wm *noninverted =
> +				&crtc_state->wm.vlv.noninverted[level];
> +
> +			active->sr[level].plane = wm->sr.plane;
> +			active->sr[level].cursor = wm->sr.cursor;
> +
> +			for_each_plane_id_on_crtc(crtc, plane_id) {
> +				active->wm[level].plane[plane_id] = wm->pipe[pipe].plane[plane_id];
> +
> +				noninverted->plane[plane_id] =
> +					vlv_invert_wm_value(active->wm[level].plane[plane_id],
> +							    fifo_state->plane[plane_id]);
> +			}
> +		}
> +
> +		for_each_plane_id_on_crtc(crtc, plane_id)
> +			vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
> +		vlv_invalidate_wms(crtc, active, level);
> +
> +		crtc_state->wm.vlv.optimal = *active;
> +
>  		DRM_DEBUG_KMS("Initial watermarks: pipe %c, plane=%d, cursor=%d, sprite0=%d, sprite1=%d\n",
>  			      pipe_name(pipe),
>  			      wm->pipe[pipe].plane[PLANE_PRIMARY],
>  			      wm->pipe[pipe].plane[PLANE_CURSOR],
>  			      wm->pipe[pipe].plane[PLANE_SPRITE0],
>  			      wm->pipe[pipe].plane[PLANE_SPRITE1]);
> +	}
>  
>  	DRM_DEBUG_KMS("Initial watermarks: SR plane=%d, SR cursor=%d level=%d cxsr=%d\n",
>  		      wm->sr.plane, wm->sr.cursor, wm->level, wm->cxsr);
> @@ -7691,7 +7788,9 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
>  		}
>  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
>  		vlv_setup_wm_latency(dev_priv);
> -		dev_priv->display.update_wm = vlv_update_wm;
> +		dev_priv->display.compute_pipe_wm = vlv_compute_pipe_wm;
> +		dev_priv->display.initial_watermarks = vlv_initial_watermarks;
> +		dev_priv->display.atomic_update_watermarks = vlv_atomic_update_fifo;
>  	} else if (IS_PINEVIEW(dev_priv)) {
>  		if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),
>  					    dev_priv->is_ddr3,


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

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

* Re: [PATCH 13/14] drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
  2016-12-12 20:35 ` [PATCH 13/14] drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun ville.syrjala
@ 2016-12-15 15:34   ` Maarten Lankhorst
  2016-12-15 15:47     ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 15:34 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> On VLV/CHV enabling sprite0 when sprite1 has already been enabled may
> lead to an underrun. This only happens when sprite0 FIFO size is zero
> prior to enabling it. Hence an effective workaround is to always
> allocate at least one cacheline for sprite0 when sprite1 is active.
>
> I've not observed this sort of failure during any other type of plane
> enable/disable sequence.
>
> Testcase: igt/kms_plane_blinker
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 24 +++++++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index fa882cdcac52..75a5bde43723 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1006,6 +1006,12 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
>  	return min_t(int, wm, USHRT_MAX);
>  }
>  
> +static bool vlv_need_sprite0_fifo_workaround(unsigned int active_planes)
> +{
> +	return (active_planes & (BIT(PLANE_SPRITE0) |
> +				 BIT(PLANE_SPRITE1))) == BIT(PLANE_SPRITE1);
> +}
> +
>  static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
>  {
>  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> @@ -1016,12 +1022,25 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
>  	int num_active_planes = hweight32(active_planes);
>  	const int fifo_size = 511;
>  	int fifo_extra, fifo_left = fifo_size;
> +	int sprite0_fifo_extra = 0;
>  	unsigned int total_rate;
>  	enum plane_id plane_id;
>  
> +	/*
> +	 * When enabling sprite0 after sprite1 has already been enabled
> +	 * we tend to get an underrun unless sprite0 already has some
> +	 * FIFO space allcoated. Hence we always allocate at least one
> +	 * cacheline for sprite0 whenever sprite1 is enabled.
> +	 *
> +	 * All other plane enable sequences appear immune to this problem.
> +	 */
> +	if (vlv_need_sprite0_fifo_workaround(active_planes))
> +		sprite0_fifo_extra = 1;
I don't think you need crtc_state->active_planes just for this, it adds a lot of tracking for something that could be done by

if (noninverted->plane[SPRITE1] && !noninverted->plane[SPRITE0])
/* allocate 1 for sprite 0 */

Maybe drop that patch?
>  	total_rate = noninverted->plane[PLANE_PRIMARY] +
>  		noninverted->plane[PLANE_SPRITE0] +
> -		noninverted->plane[PLANE_SPRITE1];
> +		noninverted->plane[PLANE_SPRITE1] +
> +		sprite0_fifo_extra;
>  
>  	if (total_rate > fifo_size)
>  		return -EINVAL;
> @@ -1042,6 +1061,9 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
>  		fifo_left -= fifo_state->plane[plane_id];
>  	}
>  
> +	fifo_state->plane[PLANE_SPRITE0] += sprite0_fifo_extra;
> +	fifo_left -= sprite0_fifo_extra;
> +
>  	fifo_state->plane[PLANE_CURSOR] = 63;
>  
>  	fifo_extra = DIV_ROUND_UP(fifo_left, num_active_planes ?: 1);


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

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

* Re: [PATCH i-g-t] tests: Add kms_plane_blinker
  2016-12-15 15:28       ` Maarten Lankhorst
@ 2016-12-15 15:36         ` Ville Syrjälä
  2016-12-15 15:41           ` Maarten Lankhorst
  0 siblings, 1 reply; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 15:36 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 04:28:52PM +0100, Maarten Lankhorst wrote:
> Op 15-12-16 om 16:23 schreef Ville Syrjälä:
> > On Thu, Dec 15, 2016 at 04:17:45PM +0100, Maarten Lankhorst wrote:
> >> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> >>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>
> >>> Add a test to try out all the different plane enable/disable
> >>> order permutations.
> >>>
> >>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> Didn't look through the test, but sounds like
> >>
> >> kms_atomic_transitions.plane-*-transition-* ?
> >>
> >> Although that one tests a few more edge cases like modeset disable and nonblocking updates..
> > I don't immediately see where it would try all the permutations, nor can
> > I see any crc_nonblock() stuff so doesn't seem like it could even spot
> > transient errors.
> >
> I haven't done any crc test there yet, but the double loop in run_transition_test handles all combinations of planes.

permutations > combinations

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 08/14] drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not needed
  2016-12-12 20:35 ` [PATCH 08/14] drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not needed ville.syrjala
@ 2016-12-15 15:37   ` Maarten Lankhorst
  2017-02-16 17:54     ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 15:37 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Check whether anything relevant has actually change when we compute new
> watermarks for each plane in the state. If the watermarks for no
> primary/sprite planes changed we don't have to recompute the FIFO split
> or reprogram the DSBARB registers. And even the cursor watermarks didn't
> change we can skip the merge+invert step between all the planes on
> the pipe as well.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_atomic.c |  1 +
>  drivers/gpu/drm/i915/intel_drv.h    |  1 +
>  drivers/gpu/drm/i915/intel_pm.c     | 73 +++++++++++++++++++++++++++++--------
>  3 files changed, 60 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> index c5a166752eda..df33f270b459 100644
> --- a/drivers/gpu/drm/i915/intel_atomic.c
> +++ b/drivers/gpu/drm/i915/intel_atomic.c
> @@ -99,6 +99,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
>  	crtc_state->update_wm_pre = false;
>  	crtc_state->update_wm_post = false;
>  	crtc_state->fb_changed = false;
> +	crtc_state->fifo_changed = false;
>  	crtc_state->wm.need_postvbl_update = false;
>  	crtc_state->fb_bits = 0;
This flag is only used in intel_pm.c, maybe put it in crtc_state->wm.vlv.fifo_changed, and clear it in the beginning of the wm recalculation?
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 66668c18a47a..a92857864ee8 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -560,6 +560,7 @@ struct intel_crtc_state {
>  	bool disable_cxsr;
>  	bool update_wm_pre, update_wm_post; /* watermarks are updated */
>  	bool fb_changed; /* fb on any of the planes is changed */
> +	bool fifo_changed; /* FIFO split is changed */
>  
>  	/* Pipe source size (ie. panel fitter input size)
>  	 * All planes will be positioned inside this space,
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index f68b46eed224..c7cc62cf51f6 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1103,31 +1103,36 @@ static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
>  }
>  
>  /* starting from 'level' set all higher levels to 'value' */
> -static void vlv_plane_wm_set(struct intel_crtc_state *crtc_state,
> +static bool vlv_plane_wm_set(struct intel_crtc_state *crtc_state,
>  			     int level, enum plane_id plane_id, u16 value)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
>  	int num_levels = vlv_num_wm_levels(dev_priv);
> +	bool dirty = false;
>  
>  	for (; level < num_levels; level++) {
>  		struct vlv_pipe_wm *noninverted =
>  			&crtc_state->wm.vlv.noninverted[level];
>  
> +		dirty |= noninverted->plane[plane_id] != value;
>  		noninverted->plane[plane_id] = value;
>  	}
> +
> +	return dirty;
>  }
>  
> -static void vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
> +static bool vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
>  				 const struct intel_plane_state *plane_state)
>  {
>  	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
>  	enum plane_id plane_id = plane->id;
>  	int num_levels = vlv_num_wm_levels(to_i915(plane->base.dev));
>  	int level;
> +	bool dirty = false;
>  
>  	if (!plane_state->base.visible) {
> -		vlv_plane_wm_set(crtc_state, 0, plane_id, 0);
> -		return;
> +		dirty |= vlv_plane_wm_set(crtc_state, 0, plane_id, 0);
> +		goto out;
>  	}
>  
>  	for (level = 0; level < num_levels; level++) {
> @@ -1143,17 +1148,22 @@ static void vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
>  		if (wm > max_wm)
>  			break;
>  
> +		dirty |= noninverted->plane[plane_id] != wm;
>  		noninverted->plane[plane_id] = wm;
>  	}
>  
>  	/* mark all higher levels as invalid */
> -	vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
> +	dirty |= vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
>  
> -	DRM_DEBUG_KMS("%s wms: [0]=%d,[1]=%d,[2]=%d\n",
> -		      plane->base.name,
> -		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2].plane[plane_id],
> -		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM5].plane[plane_id],
> -		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_DDR_DVFS].plane[plane_id]);
> +out:
> +	if (dirty)
> +		DRM_DEBUG_KMS("%s wms: [0]=%d,[1]=%d,[2]=%d\n",
> +			      plane->base.name,
> +			      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2].plane[plane_id],
> +			      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM5].plane[plane_id],
> +			      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_DDR_DVFS].plane[plane_id]);
> +
> +	return dirty;
>  }
>  
>  static bool vlv_plane_wm_is_valid(const struct intel_crtc_state *crtc_state,
> @@ -1186,10 +1196,12 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
>  		&crtc_state->wm.vlv.fifo_state;
>  	int num_active_planes = hweight32(crtc_state->active_planes &
>  					  ~BIT(PLANE_CURSOR));
> +	bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->base);
>  	struct intel_plane_state *plane_state;
>  	struct intel_plane *plane;
>  	enum plane_id plane_id;
>  	int level, ret, i;
> +	unsigned int dirty = 0;
>  
>  	for_each_intel_plane_in_state(state, plane, plane_state, i) {
>  		const struct intel_plane_state *old_plane_state =
> @@ -1199,7 +1211,37 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
>  		    old_plane_state->base.crtc != &crtc->base)
>  			continue;
>  
> -		vlv_plane_wm_compute(crtc_state, plane_state);
> +		if (vlv_plane_wm_compute(crtc_state, plane_state))
> +			dirty |= BIT(plane->id);
> +	}
> +
> +	/*
> +	 * DSPARB registers may have been reset due to the
> +	 * power well being turned off. Make sure we restore
> +	 * them to a consistent state even if no primary/sprite
> +	 * planes are initially active.
> +	 */
> +	if (needs_modeset)
> +		crtc_state->fifo_changed = true;
> +
> +	if (!dirty)
> +		return 0;
> +
> +	/* cursor changes don't warrant a FIFO recompute */
> +	if (dirty & ~BIT(PLANE_CURSOR)) {
> +		const struct intel_crtc_state *old_crtc_state =
> +			to_intel_crtc_state(crtc->base.state);
> +		const struct vlv_fifo_state *old_fifo_state =
> +			&old_crtc_state->wm.vlv.fifo_state;
> +
> +		ret = vlv_compute_fifo(crtc_state);
> +		if (ret)
> +			return ret;
> +
> +		if (needs_modeset ||
> +		    memcmp(old_fifo_state, fifo_state,
> +			   sizeof(*fifo_state)) != 0)
> +			crtc_state->fifo_changed = true;
>  	}
>  
>  	/* initially allow all levels */
> @@ -1212,10 +1254,6 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
>  	wm_state->cxsr = crtc->pipe != PIPE_C &&
>  		crtc->wm.cxsr_allowed && num_active_planes == 1;
>  
> -	ret = vlv_compute_fifo(crtc_state);
> -	if (ret)
> -		return ret;
> -
>  	for (level = 0; level < wm_state->num_levels; level++) {
>  		const struct vlv_pipe_wm *noninverted =
>  			&crtc_state->wm.vlv.noninverted[level];
> @@ -1265,6 +1303,9 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
>  		&crtc_state->wm.vlv.fifo_state;
>  	int sprite0_start, sprite1_start, fifo_size;
>  
> +	if (!crtc_state->fifo_changed)
> +		return;
> +
>  	sprite0_start = fifo_state->plane[PLANE_PRIMARY];
>  	sprite1_start = fifo_state->plane[PLANE_SPRITE0] + sprite0_start;
>  	fifo_size = fifo_state->plane[PLANE_SPRITE1] + sprite1_start;
> @@ -4631,6 +4672,8 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
>  		active->num_levels = wm->level + 1;
>  		active->cxsr = wm->cxsr;
>  
> +		vlv_get_fifo_size(crtc_state);
> +
>  		/* FIXME sanitize things more */
>  		for (level = 0; level < active->num_levels; level++) {
>  			struct vlv_pipe_wm *noninverted =


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

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

* Re: [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way
  2016-12-15 15:30   ` Maarten Lankhorst
@ 2016-12-15 15:38     ` Ville Syrjälä
  2016-12-15 15:45       ` Maarten Lankhorst
  0 siblings, 1 reply; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 15:38 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 04:30:54PM +0100, Maarten Lankhorst wrote:
> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Start computing the vlv/chv watermarks the atomic way, from the
> > .compute_pipe_wm() hook. We'll recompute the actual watermarks
> > for only planes that are part of the state, the other planes will
> > keep their watermark from the last time it was computed.
> >
> > And the actual watermark programming will happen from the
> > .initial_watermarks() hook. For now we'll just compute the
> > optimal watermarks, and we'll hook up the intermediate
> > watermarks properly later.
> >
> > The DSPARB registers responsible for the FIFO paritioning are
> > double buffered, so they will be programming from
> > intel_begin_crtc_commit().
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h      |   8 +
> >  drivers/gpu/drm/i915/intel_display.c |  21 ++-
> >  drivers/gpu/drm/i915/intel_drv.h     |   2 -
> >  drivers/gpu/drm/i915/intel_pm.c      | 327 +++++++++++++++++++++++------------
> >  4 files changed, 238 insertions(+), 120 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 20bc04d5e617..f23698f99685 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -493,6 +493,14 @@ struct i915_hotplug {
> >  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
> >  		for_each_if ((1 << (domain)) & (mask))
> >  
> > +#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \
> > +	for ((__i) = 0; \
> > +	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
> > +		     ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
> > +		      (plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \
> > +	     (__i)++) \
> > +		for_each_if (plane_state)
> > +
> >  struct drm_i915_private;
> >  struct i915_mm_struct;
> >  struct i915_mmu_object;
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 3f027341b0f3..8d80873b6643 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -6736,6 +6736,8 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> >  static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> >  				   struct drm_atomic_state *old_state)
> >  {
> > +	struct intel_atomic_state *old_intel_state =
> > +		to_intel_atomic_state(old_state);
> >  	struct drm_crtc *crtc = pipe_config->base.crtc;
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> > @@ -6780,7 +6782,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> >  
> >  	intel_color_load_luts(&pipe_config->base);
> >  
> > -	intel_update_watermarks(intel_crtc);
> > +	dev_priv->display.initial_watermarks(old_intel_state,
> > +					     pipe_config);
> >  	intel_enable_pipe(intel_crtc);
> >  
> >  	assert_vblank_disabled(crtc);
> > @@ -6897,6 +6900,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
> >  
> >  	if (!IS_GEN2(dev_priv))
> >  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
> > +
> > +	if (!dev_priv->display.initial_watermarks)
> > +		intel_update_watermarks(intel_crtc);
> >  }
> >  
> >  static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
> > @@ -12980,10 +12986,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
> >  static void
> >  clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> >  {
> > +	struct drm_i915_private *dev_priv =
> > +		to_i915(crtc_state->base.crtc->dev);
> >  	struct drm_crtc_state tmp_state;
> >  	struct intel_crtc_scaler_state scaler_state;
> >  	struct intel_dpll_hw_state dpll_hw_state;
> >  	struct intel_shared_dpll *shared_dpll;
> > +	struct intel_crtc_wm_state wm_state;
> >  	bool force_thru;
> >  
> >  	/* FIXME: before the switch to atomic started, a new pipe_config was
> > @@ -12996,6 +13005,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> >  	shared_dpll = crtc_state->shared_dpll;
> >  	dpll_hw_state = crtc_state->dpll_hw_state;
> >  	force_thru = crtc_state->pch_pfit.force_thru;
> > +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> > +		wm_state = crtc_state->wm;
> >  
> >  	memset(crtc_state, 0, sizeof *crtc_state);
> >  
> > @@ -13004,6 +13015,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> >  	crtc_state->shared_dpll = shared_dpll;
> >  	crtc_state->dpll_hw_state = dpll_hw_state;
> >  	crtc_state->pch_pfit.force_thru = force_thru;
> > +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> > +		crtc_state->wm = wm_state;
> Is this required? In skl we throw away everything and rebuild using drm_atomic_crtc_state_for_each_plane_state.

I don't want to add all the planes into the state when not necessary.

> >  
> >  static int
> > @@ -14497,12 +14510,12 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> >  				/*
> >  				 * Make sure we don't call initial_watermarks
> >  				 * for ILK-style watermark updates.
> > +				 *
> > +				 * No clue what this is supposed to achieve.
> >  				 */
> > -				if (dev_priv->display.atomic_update_watermarks)
> > +				if (INTEL_GEN(dev_priv) >= 9)
> >  					dev_priv->display.initial_watermarks(intel_state,
> >  									     to_intel_crtc_state(crtc->state));
> > -				else
> > -					intel_update_watermarks(intel_crtc);
> >  			}
> >  		}
> >  	}
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 0e199db26bda..66668c18a47a 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -490,9 +490,7 @@ enum vlv_wm_level {
> >  struct vlv_wm_state {
> >  	struct vlv_pipe_wm wm[NUM_VLV_WM_LEVELS];
> >  	struct vlv_sr_wm sr[NUM_VLV_WM_LEVELS];
> > -	uint8_t num_active_planes;
> >  	uint8_t num_levels;
> > -	uint8_t level;
> >  	bool cxsr;
> >  };
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 233e63224649..f68b46eed224 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -1072,6 +1072,28 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
> >  	return 0;
> >  }
> >  
> > +static int vlv_num_wm_levels(struct drm_i915_private *dev_priv)
> > +{
> > +	return dev_priv->wm.max_level + 1;
> > +}
> > +
> > +/* mark all levels starting from 'level' as invalid */
> > +static void vlv_invalidate_wms(struct intel_crtc *crtc,
> > +			       struct vlv_wm_state *wm_state, int level)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > +
> > +	for (; level < vlv_num_wm_levels(dev_priv); level++) {
> > +		enum plane_id plane_id;
> > +
> > +		for_each_plane_id_on_crtc(crtc, plane_id)
> > +			wm_state->wm[level].plane[plane_id] = USHRT_MAX;
> > +
> > +		wm_state->sr[level].cursor = USHRT_MAX;
> > +		wm_state->sr[level].plane = USHRT_MAX;
> > +	}
> > +}
> > +
> >  static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
> >  {
> >  	if (wm > fifo_size)
> > @@ -1080,108 +1102,162 @@ static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
> >  		return fifo_size - wm;
> >  }
> >  
> > -static void vlv_invert_wms(struct intel_crtc_state *crtc_state)
> > +/* starting from 'level' set all higher levels to 'value' */
> > +static void vlv_plane_wm_set(struct intel_crtc_state *crtc_state,
> > +			     int level, enum plane_id plane_id, u16 value)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
> > +	int num_levels = vlv_num_wm_levels(dev_priv);
> > +
> > +	for (; level < num_levels; level++) {
> > +		struct vlv_pipe_wm *noninverted =
> > +			&crtc_state->wm.vlv.noninverted[level];
> > +
> > +		noninverted->plane[plane_id] = value;
> > +	}
> > +}
> > +
> > +static void vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
> > +				 const struct intel_plane_state *plane_state)
> > +{
> > +	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
> > +	enum plane_id plane_id = plane->id;
> > +	int num_levels = vlv_num_wm_levels(to_i915(plane->base.dev));
> > +	int level;
> > +
> > +	if (!plane_state->base.visible) {
> > +		vlv_plane_wm_set(crtc_state, 0, plane_id, 0);
> > +		return;
> > +	}
> > +
> > +	for (level = 0; level < num_levels; level++) {
> > +		struct vlv_pipe_wm *noninverted =
> > +			&crtc_state->wm.vlv.noninverted[level];
> > +		int wm = vlv_compute_wm_level(crtc_state, plane_state, level);
> > +		int max_wm = plane_id == PLANE_CURSOR ? 63 : 511;
> > +
> > +		/* FIXME just bail */
> > +		if (WARN_ON(level == 0 && wm > max_wm))
> > +			wm = max_wm;
> > +
> > +		if (wm > max_wm)
> > +			break;
> > +
> > +		noninverted->plane[plane_id] = wm;
> > +	}
> > +
> > +	/* mark all higher levels as invalid */
> > +	vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
> > +
> > +	DRM_DEBUG_KMS("%s wms: [0]=%d,[1]=%d,[2]=%d\n",
> > +		      plane->base.name,
> > +		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2].plane[plane_id],
> > +		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM5].plane[plane_id],
> > +		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_DDR_DVFS].plane[plane_id]);
> > +}
> > +
> > +static bool vlv_plane_wm_is_valid(const struct intel_crtc_state *crtc_state,
> > +				  enum plane_id plane_id, int level)
> > +{
> > +	const struct vlv_pipe_wm *noninverted =
> > +		&crtc_state->wm.vlv.noninverted[level];
> > +	const struct vlv_fifo_state *fifo_state =
> > +		&crtc_state->wm.vlv.fifo_state;
> > +
> > +	return noninverted->plane[plane_id] <= fifo_state->plane[plane_id];
> > +}
> > +
> > +static bool vlv_crtc_wm_is_valid(const struct intel_crtc_state *crtc_state, int level)
> > +{
> > +	return vlv_plane_wm_is_valid(crtc_state, PLANE_PRIMARY, level) &&
> > +		vlv_plane_wm_is_valid(crtc_state, PLANE_SPRITE0, level) &&
> > +		vlv_plane_wm_is_valid(crtc_state, PLANE_SPRITE1, level) &&
> > +		vlv_plane_wm_is_valid(crtc_state, PLANE_CURSOR, level);
> > +}
> > +
> > +static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
> >  {
> >  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> > +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > +	struct intel_atomic_state *state =
> > +		to_intel_atomic_state(crtc_state->base.state);
> >  	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
> >  	const struct vlv_fifo_state *fifo_state =
> >  		&crtc_state->wm.vlv.fifo_state;
> > -	int level;
> > +	int num_active_planes = hweight32(crtc_state->active_planes &
> > +					  ~BIT(PLANE_CURSOR));
> > +	struct intel_plane_state *plane_state;
> > +	struct intel_plane *plane;
> > +	enum plane_id plane_id;
> > +	int level, ret, i;
> > +
> > +	for_each_intel_plane_in_state(state, plane, plane_state, i) {
> > +		const struct intel_plane_state *old_plane_state =
> > +			to_intel_plane_state(plane->base.state);
> > +
> > +		if (plane_state->base.crtc != &crtc->base &&
> > +		    old_plane_state->base.crtc != &crtc->base)
> > +			continue;
> > +
> > +		vlv_plane_wm_compute(crtc_state, plane_state);
> > +	}
> > +
> > +	/* initially allow all levels */
> > +	wm_state->num_levels = vlv_num_wm_levels(dev_priv);
> > +	/*
> > +	 * Note that enabling cxsr with no primary/sprite planes
> > +	 * enabled can wedge the pipe. Hence we only allow cxsr
> > +	 * with exactly one enabled primary/sprite plane.
> > +	 */
> > +	wm_state->cxsr = crtc->pipe != PIPE_C &&
> > +		crtc->wm.cxsr_allowed && num_active_planes == 1;
> > +
> > +	ret = vlv_compute_fifo(crtc_state);
> > +	if (ret)
> > +		return ret;
> >  
> >  	for (level = 0; level < wm_state->num_levels; level++) {
> > -		struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > -		const int sr_fifo_size =
> > -			INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
> > -		enum plane_id plane_id;
> > +		const struct vlv_pipe_wm *noninverted =
> > +			&crtc_state->wm.vlv.noninverted[level];
> > +		const int sr_fifo_size = INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
> > +
> > +		if (!vlv_crtc_wm_is_valid(crtc_state, level))
> > +			break;
> > +
> > +		for_each_plane_id_on_crtc(crtc, plane_id) {
> > +			wm_state->wm[level].plane[plane_id] =
> > +				vlv_invert_wm_value(noninverted->plane[plane_id],
> > +						    fifo_state->plane[plane_id]);
> > +		}
> >  
> >  		wm_state->sr[level].plane =
> > -			vlv_invert_wm_value(wm_state->sr[level].plane,
> > +			vlv_invert_wm_value(max3(noninverted->plane[PLANE_PRIMARY],
> > +						 noninverted->plane[PLANE_SPRITE0],
> > +						 noninverted->plane[PLANE_SPRITE1]),
> >  					    sr_fifo_size);
> > +
> >  		wm_state->sr[level].cursor =
> > -			vlv_invert_wm_value(wm_state->sr[level].cursor,
> > +			vlv_invert_wm_value(noninverted->plane[PLANE_CURSOR],
> >  					    63);
> > -
> > -		for_each_plane_id_on_crtc(crtc, plane_id) {
> > -			wm_state->wm[level].plane[plane_id] =
> > -				vlv_invert_wm_value(wm_state->wm[level].plane[plane_id],
> > -						    fifo_state->plane[plane_id]);
> > -		}
> > -	}
> > -}
> > -
> > -static void vlv_compute_wm(struct intel_crtc_state *crtc_state)
> > -{
> > -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> > -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > -	struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
> > -	struct intel_plane *plane;
> > -	int level;
> > -
> > -	memset(wm_state, 0, sizeof(*wm_state));
> > -	memset(crtc_state->wm.vlv.noninverted, 0,
> > -	       sizeof(crtc_state->wm.vlv.noninverted));
> > -
> > -	wm_state->cxsr = crtc->pipe != PIPE_C && crtc->wm.cxsr_allowed;
> > -	wm_state->num_levels = dev_priv->wm.max_level + 1;
> > -
> > -	wm_state->num_active_planes = 0;
> > -
> > -	if (wm_state->num_active_planes != 1)
> > -		wm_state->cxsr = false;
> > -
> > -	for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
> > -		struct intel_plane_state *state =
> > -			to_intel_plane_state(plane->base.state);
> > -
> > -		if (!state->base.visible)
> > -			continue;
> > -
> > -		for (level = 0; level < wm_state->num_levels; level++) {
> > -			struct vlv_pipe_wm *noninverted =
> > -				&crtc_state->wm.vlv.noninverted[level];
> > -			int wm = vlv_compute_wm_level(crtc_state, state, level);
> > -			int max_wm = plane->id == PLANE_CURSOR ? 63 : 511;
> > -
> > -			/* hack */
> > -			if (WARN_ON(level == 0 && wm > max_wm))
> > -				wm = max_wm;
> > -
> > -			if (wm > max_wm)
> > -				break;
> > -
> > -			noninverted->plane[plane->id] = wm;
> > -		}
> > -
> > -		wm_state->num_levels = level;
> >  	}
> >  
> > -	vlv_compute_fifo(crtc_state);
> > +	if (level == 0)
> > +		return -EINVAL;
> >  
> > -	for (level = 0; level < wm_state->num_levels; level++) {
> > -		struct vlv_pipe_wm *noninverted =
> > -			&crtc_state->wm.vlv.noninverted[level];
> > +	/* limit to only levels we can actually handle */
> > +	wm_state->num_levels = level;
> >  
> > -		wm_state->wm[level] = *noninverted;
> > -
> > -		wm_state->sr[level].plane = max3(noninverted->plane[PLANE_PRIMARY],
> > -						 noninverted->plane[PLANE_SPRITE0],
> > -						 noninverted->plane[PLANE_SPRITE1]);
> > -		wm_state->sr[level].cursor = noninverted->plane[PLANE_CURSOR];
> > -	}
> > -
> > -	/* clear any (partially) filled invalid levels */
> > -	for (level = wm_state->num_levels; level < dev_priv->wm.max_level + 1; level++) {
> > -		memset(&wm_state->wm[level], 0, sizeof(wm_state->wm[level]));
> > -		memset(&wm_state->sr[level], 0, sizeof(wm_state->sr[level]));
> > -	}
> > +	/* invalidate the higher levels */
> > +	vlv_invalidate_wms(crtc, wm_state, level);
> >  
> > -	vlv_invert_wms(crtc_state);
> > +	return 0;
> >  }
> >  
> >  #define VLV_FIFO(plane, value) \
> >  	(((value) << DSPARB_ ## plane ## _SHIFT_VLV) & DSPARB_ ## plane ## _MASK_VLV)
> >  
> > -static void vlv_pipe_set_fifo_size(const struct intel_crtc_state *crtc_state)
> > +static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
> > +				   struct intel_crtc_state *crtc_state)
> >  {
> >  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> >  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > @@ -1196,10 +1272,6 @@ static void vlv_pipe_set_fifo_size(const struct intel_crtc_state *crtc_state)
> >  	WARN_ON(fifo_state->plane[PLANE_CURSOR] != 63);
> >  	WARN_ON(fifo_size != 511);
> >  
> > -	DRM_DEBUG_KMS("Pipe %c FIFO split %d / %d / %d\n",
> > -		      pipe_name(crtc->pipe), sprite0_start,
> > -		      sprite1_start, fifo_size);
> > -
> >  	spin_lock(&dev_priv->wm.dsparb_lock);
> >  
> >  	switch (crtc->pipe) {
> > @@ -1298,11 +1370,8 @@ static void vlv_merge_wm(struct drm_i915_private *dev_priv,
> >  		const struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
> >  		enum pipe pipe = crtc->pipe;
> >  
> > -		if (!crtc->active)
> > -			continue;
> > -
> >  		wm->pipe[pipe] = wm_state->wm[wm->level];
> > -		if (wm->cxsr)
> > +		if (crtc->active && wm->cxsr)
> >  			wm->sr = wm_state->sr[wm->level];
> >  
> >  		wm->ddl[pipe].plane[PLANE_PRIMARY] = DDL_PRECISION_HIGH | 2;
> > @@ -1322,24 +1391,15 @@ static bool is_enabling(int old, int new, int threshold)
> >  	return old < threshold && new >= threshold;
> >  }
> >  
> > -static void vlv_update_wm(struct intel_crtc *crtc)
> > +static void vlv_program_watermarks(struct drm_i915_private *dev_priv)
> >  {
> > -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > -	struct intel_crtc_state *crtc_state =
> > -		to_intel_crtc_state(crtc->base.state);
> > -	enum pipe pipe = crtc->pipe;
> >  	struct vlv_wm_values *old_wm = &dev_priv->wm.vlv;
> >  	struct vlv_wm_values new_wm = {};
> >  
> > -	vlv_compute_wm(crtc_state);
> > -	crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
> >  	vlv_merge_wm(dev_priv, &new_wm);
> >  
> > -	if (memcmp(old_wm, &new_wm, sizeof(new_wm)) == 0) {
> > -		/* FIXME should be part of crtc atomic commit */
> > -		vlv_pipe_set_fifo_size(crtc_state);
> > +	if (memcmp(old_wm, &new_wm, sizeof(new_wm)) == 0)
> >  		return;
> > -	}
> >  
> >  	if (is_disabling(old_wm->level, new_wm.level, VLV_WM_LEVEL_DDR_DVFS))
> >  		chv_set_memory_dvfs(dev_priv, false);
> > @@ -1350,17 +1410,8 @@ static void vlv_update_wm(struct intel_crtc *crtc)
> >  	if (is_disabling(old_wm->cxsr, new_wm.cxsr, true))
> >  		_intel_set_memory_cxsr(dev_priv, false);
> >  
> > -	/* FIXME should be part of crtc atomic commit */
> > -	vlv_pipe_set_fifo_size(crtc_state);
> > -
> >  	vlv_write_wm_values(dev_priv, &new_wm);
> >  
> > -	DRM_DEBUG_KMS("Setting FIFO watermarks - %c: plane=%d, cursor=%d, "
> > -		      "sprite0=%d, sprite1=%d, SR: plane=%d, cursor=%d level=%d cxsr=%d\n",
> > -		      pipe_name(pipe), new_wm.pipe[pipe].plane[PLANE_PRIMARY], new_wm.pipe[pipe].plane[PLANE_CURSOR],
> > -		      new_wm.pipe[pipe].plane[PLANE_SPRITE0], new_wm.pipe[pipe].plane[PLANE_SPRITE1],
> > -		      new_wm.sr.plane, new_wm.sr.cursor, new_wm.level, new_wm.cxsr);
> > -
> >  	if (is_enabling(old_wm->cxsr, new_wm.cxsr, true))
> >  		_intel_set_memory_cxsr(dev_priv, true);
> >  
> > @@ -1373,6 +1424,18 @@ static void vlv_update_wm(struct intel_crtc *crtc)
> >  	*old_wm = new_wm;
> >  }
> >  
> > +static void vlv_initial_watermarks(struct intel_atomic_state *state,
> > +				   struct intel_crtc_state *crtc_state)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
> > +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> > +
> > +	mutex_lock(&dev_priv->wm.wm_mutex);
> > +	crtc->wm.active.vlv = crtc_state->wm.vlv.optimal;
> > +	vlv_program_watermarks(dev_priv);
> > +	mutex_unlock(&dev_priv->wm.wm_mutex);
> > +}
> > +
> >  #define single_plane_enabled(mask) is_power_of_2(mask)
> >  
> >  static void g4x_update_wm(struct intel_crtc *crtc)
> > @@ -4512,14 +4575,10 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct vlv_wm_values *wm = &dev_priv->wm.vlv;
> >  	struct intel_crtc *crtc;
> > -	enum pipe pipe;
> >  	u32 val;
> >  
> >  	vlv_read_wm_values(dev_priv, wm);
> >  
> > -	for_each_intel_crtc(dev, crtc)
> > -		vlv_get_fifo_size(to_intel_crtc_state(crtc->base.state));
> > -
> >  	wm->cxsr = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
> >  	wm->level = VLV_WM_LEVEL_PM2;
> >  
> > @@ -4557,13 +4616,51 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
> >  		mutex_unlock(&dev_priv->rps.hw_lock);
> >  	}
> >  
> > -	for_each_pipe(dev_priv, pipe)
> > +	for_each_intel_crtc(dev, crtc) {
> > +		struct intel_crtc_state *crtc_state =
> > +			to_intel_crtc_state(crtc->base.state);
> > +		struct vlv_wm_state *active = &crtc->wm.active.vlv;
> > +		const struct vlv_fifo_state *fifo_state =
> > +			&crtc_state->wm.vlv.fifo_state;
> > +		enum pipe pipe = crtc->pipe;
> > +		enum plane_id plane_id;
> > +		int level;
> > +
> > +		vlv_get_fifo_size(crtc_state);
> > +
> > +		active->num_levels = wm->level + 1;
> > +		active->cxsr = wm->cxsr;
> > +
> > +		/* FIXME sanitize things more */
> > +		for (level = 0; level < active->num_levels; level++) {
> > +			struct vlv_pipe_wm *noninverted =
> > +				&crtc_state->wm.vlv.noninverted[level];
> > +
> > +			active->sr[level].plane = wm->sr.plane;
> > +			active->sr[level].cursor = wm->sr.cursor;
> > +
> > +			for_each_plane_id_on_crtc(crtc, plane_id) {
> > +				active->wm[level].plane[plane_id] = wm->pipe[pipe].plane[plane_id];
> > +
> > +				noninverted->plane[plane_id] =
> > +					vlv_invert_wm_value(active->wm[level].plane[plane_id],
> > +							    fifo_state->plane[plane_id]);
> > +			}
> > +		}
> > +
> > +		for_each_plane_id_on_crtc(crtc, plane_id)
> > +			vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
> > +		vlv_invalidate_wms(crtc, active, level);
> > +
> > +		crtc_state->wm.vlv.optimal = *active;
> > +
> >  		DRM_DEBUG_KMS("Initial watermarks: pipe %c, plane=%d, cursor=%d, sprite0=%d, sprite1=%d\n",
> >  			      pipe_name(pipe),
> >  			      wm->pipe[pipe].plane[PLANE_PRIMARY],
> >  			      wm->pipe[pipe].plane[PLANE_CURSOR],
> >  			      wm->pipe[pipe].plane[PLANE_SPRITE0],
> >  			      wm->pipe[pipe].plane[PLANE_SPRITE1]);
> > +	}
> >  
> >  	DRM_DEBUG_KMS("Initial watermarks: SR plane=%d, SR cursor=%d level=%d cxsr=%d\n",
> >  		      wm->sr.plane, wm->sr.cursor, wm->level, wm->cxsr);
> > @@ -7691,7 +7788,9 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
> >  		}
> >  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> >  		vlv_setup_wm_latency(dev_priv);
> > -		dev_priv->display.update_wm = vlv_update_wm;
> > +		dev_priv->display.compute_pipe_wm = vlv_compute_pipe_wm;
> > +		dev_priv->display.initial_watermarks = vlv_initial_watermarks;
> > +		dev_priv->display.atomic_update_watermarks = vlv_atomic_update_fifo;
> >  	} else if (IS_PINEVIEW(dev_priv)) {
> >  		if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),
> >  					    dev_priv->is_ddr3,
> 

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH i-g-t] tests: Add kms_plane_blinker
  2016-12-15 15:36         ` Ville Syrjälä
@ 2016-12-15 15:41           ` Maarten Lankhorst
  2016-12-15 16:42             ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 15:41 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

Op 15-12-16 om 16:36 schreef Ville Syrjälä:
> On Thu, Dec 15, 2016 at 04:28:52PM +0100, Maarten Lankhorst wrote:
>> Op 15-12-16 om 16:23 schreef Ville Syrjälä:
>>> On Thu, Dec 15, 2016 at 04:17:45PM +0100, Maarten Lankhorst wrote:
>>>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
>>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>>
>>>>> Add a test to try out all the different plane enable/disable
>>>>> order permutations.
>>>>>
>>>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>> Didn't look through the test, but sounds like
>>>>
>>>> kms_atomic_transitions.plane-*-transition-* ?
>>>>
>>>> Although that one tests a few more edge cases like modeset disable and nonblocking updates..
>>> I don't immediately see where it would try all the permutations, nor can
>>> I see any crc_nonblock() stuff so doesn't seem like it could even spot
>>> transient errors.
>>>
>> I haven't done any crc test there yet, but the double loop in run_transition_test handles all combinations of planes.
> permutations > combinations
>
It permutates too, I used it for some basic wm testing before. :)

~Maarten

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

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

* Re: [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way
  2016-12-15 15:38     ` Ville Syrjälä
@ 2016-12-15 15:45       ` Maarten Lankhorst
  2016-12-15 16:09         ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 15:45 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

Op 15-12-16 om 16:38 schreef Ville Syrjälä:
> On Thu, Dec 15, 2016 at 04:30:54PM +0100, Maarten Lankhorst wrote:
>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> Start computing the vlv/chv watermarks the atomic way, from the
>>> .compute_pipe_wm() hook. We'll recompute the actual watermarks
>>> for only planes that are part of the state, the other planes will
>>> keep their watermark from the last time it was computed.
>>>
>>> And the actual watermark programming will happen from the
>>> .initial_watermarks() hook. For now we'll just compute the
>>> optimal watermarks, and we'll hook up the intermediate
>>> watermarks properly later.
>>>
>>> The DSPARB registers responsible for the FIFO paritioning are
>>> double buffered, so they will be programming from
>>> intel_begin_crtc_commit().
>>>
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> ---
>>>  drivers/gpu/drm/i915/i915_drv.h      |   8 +
>>>  drivers/gpu/drm/i915/intel_display.c |  21 ++-
>>>  drivers/gpu/drm/i915/intel_drv.h     |   2 -
>>>  drivers/gpu/drm/i915/intel_pm.c      | 327 +++++++++++++++++++++++------------
>>>  4 files changed, 238 insertions(+), 120 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>>> index 20bc04d5e617..f23698f99685 100644
>>> --- a/drivers/gpu/drm/i915/i915_drv.h
>>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>>> @@ -493,6 +493,14 @@ struct i915_hotplug {
>>>  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
>>>  		for_each_if ((1 << (domain)) & (mask))
>>>  
>>> +#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \
>>> +	for ((__i) = 0; \
>>> +	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
>>> +		     ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
>>> +		      (plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \
>>> +	     (__i)++) \
>>> +		for_each_if (plane_state)
>>> +
>>>  struct drm_i915_private;
>>>  struct i915_mm_struct;
>>>  struct i915_mmu_object;
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index 3f027341b0f3..8d80873b6643 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -6736,6 +6736,8 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>>>  static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
>>>  				   struct drm_atomic_state *old_state)
>>>  {
>>> +	struct intel_atomic_state *old_intel_state =
>>> +		to_intel_atomic_state(old_state);
>>>  	struct drm_crtc *crtc = pipe_config->base.crtc;
>>>  	struct drm_device *dev = crtc->dev;
>>>  	struct drm_i915_private *dev_priv = to_i915(dev);
>>> @@ -6780,7 +6782,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
>>>  
>>>  	intel_color_load_luts(&pipe_config->base);
>>>  
>>> -	intel_update_watermarks(intel_crtc);
>>> +	dev_priv->display.initial_watermarks(old_intel_state,
>>> +					     pipe_config);
>>>  	intel_enable_pipe(intel_crtc);
>>>  
>>>  	assert_vblank_disabled(crtc);
>>> @@ -6897,6 +6900,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
>>>  
>>>  	if (!IS_GEN2(dev_priv))
>>>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
>>> +
>>> +	if (!dev_priv->display.initial_watermarks)
>>> +		intel_update_watermarks(intel_crtc);
>>>  }
>>>  
>>>  static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
>>> @@ -12980,10 +12986,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
>>>  static void
>>>  clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>>>  {
>>> +	struct drm_i915_private *dev_priv =
>>> +		to_i915(crtc_state->base.crtc->dev);
>>>  	struct drm_crtc_state tmp_state;
>>>  	struct intel_crtc_scaler_state scaler_state;
>>>  	struct intel_dpll_hw_state dpll_hw_state;
>>>  	struct intel_shared_dpll *shared_dpll;
>>> +	struct intel_crtc_wm_state wm_state;
>>>  	bool force_thru;
>>>  
>>>  	/* FIXME: before the switch to atomic started, a new pipe_config was
>>> @@ -12996,6 +13005,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>>>  	shared_dpll = crtc_state->shared_dpll;
>>>  	dpll_hw_state = crtc_state->dpll_hw_state;
>>>  	force_thru = crtc_state->pch_pfit.force_thru;
>>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>>> +		wm_state = crtc_state->wm;
>>>  
>>>  	memset(crtc_state, 0, sizeof *crtc_state);
>>>  
>>> @@ -13004,6 +13015,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>>>  	crtc_state->shared_dpll = shared_dpll;
>>>  	crtc_state->dpll_hw_state = dpll_hw_state;
>>>  	crtc_state->pch_pfit.force_thru = force_thru;
>>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>>> +		crtc_state->wm = wm_state;
>> Is this required? In skl we throw away everything and rebuild using drm_atomic_crtc_state_for_each_plane_state.
> I don't want to add all the planes into the state when not necessary.
It doesn't. It uses the fact that updating planes requires crtc mutex, and only iterates over all planes in crtc_state->planes_mask.
Any planes outside it are disabled so wm values can be considered 0, and roughly does the following:

for_each_plane_in_mask(crtc_state->planes_mask)
if ((!plane_state = drm_atomic_get_existing_state(state, plane_state)) plane_state = plane->state;

plane_state must be const, but that's no problem for wm calculations.

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

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

* Re: [PATCH 13/14] drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
  2016-12-15 15:34   ` Maarten Lankhorst
@ 2016-12-15 15:47     ` Ville Syrjälä
  2016-12-15 16:13       ` Maarten Lankhorst
  0 siblings, 1 reply; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 15:47 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 04:34:58PM +0100, Maarten Lankhorst wrote:
> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > On VLV/CHV enabling sprite0 when sprite1 has already been enabled may
> > lead to an underrun. This only happens when sprite0 FIFO size is zero
> > prior to enabling it. Hence an effective workaround is to always
> > allocate at least one cacheline for sprite0 when sprite1 is active.
> >
> > I've not observed this sort of failure during any other type of plane
> > enable/disable sequence.
> >
> > Testcase: igt/kms_plane_blinker
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 24 +++++++++++++++++++++++-
> >  1 file changed, 23 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index fa882cdcac52..75a5bde43723 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -1006,6 +1006,12 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
> >  	return min_t(int, wm, USHRT_MAX);
> >  }
> >  
> > +static bool vlv_need_sprite0_fifo_workaround(unsigned int active_planes)
> > +{
> > +	return (active_planes & (BIT(PLANE_SPRITE0) |
> > +				 BIT(PLANE_SPRITE1))) == BIT(PLANE_SPRITE1);
> > +}
> > +
> >  static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
> >  {
> >  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> > @@ -1016,12 +1022,25 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
> >  	int num_active_planes = hweight32(active_planes);
> >  	const int fifo_size = 511;
> >  	int fifo_extra, fifo_left = fifo_size;
> > +	int sprite0_fifo_extra = 0;
> >  	unsigned int total_rate;
> >  	enum plane_id plane_id;
> >  
> > +	/*
> > +	 * When enabling sprite0 after sprite1 has already been enabled
> > +	 * we tend to get an underrun unless sprite0 already has some
> > +	 * FIFO space allcoated. Hence we always allocate at least one
> > +	 * cacheline for sprite0 whenever sprite1 is enabled.
> > +	 *
> > +	 * All other plane enable sequences appear immune to this problem.
> > +	 */
> > +	if (vlv_need_sprite0_fifo_workaround(active_planes))
> > +		sprite0_fifo_extra = 1;
> I don't think you need crtc_state->active_planes just for this, it adds a lot of tracking for something that could be done by
> 
> if (noninverted->plane[SPRITE1] && !noninverted->plane[SPRITE0])
> /* allocate 1 for sprite 0 */
> 
> Maybe drop that patch?

We'll want it for other things outside of the vlv watermark code as
well. So figured this is a good excuse for getting the ball rolling,

> >  	total_rate = noninverted->plane[PLANE_PRIMARY] +
> >  		noninverted->plane[PLANE_SPRITE0] +
> > -		noninverted->plane[PLANE_SPRITE1];
> > +		noninverted->plane[PLANE_SPRITE1] +
> > +		sprite0_fifo_extra;
> >  
> >  	if (total_rate > fifo_size)
> >  		return -EINVAL;
> > @@ -1042,6 +1061,9 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
> >  		fifo_left -= fifo_state->plane[plane_id];
> >  	}
> >  
> > +	fifo_state->plane[PLANE_SPRITE0] += sprite0_fifo_extra;
> > +	fifo_left -= sprite0_fifo_extra;
> > +
> >  	fifo_state->plane[PLANE_CURSOR] = 63;
> >  
> >  	fifo_extra = DIV_ROUND_UP(fifo_left, num_active_planes ?: 1);
> 

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way
  2016-12-15 15:45       ` Maarten Lankhorst
@ 2016-12-15 16:09         ` Ville Syrjälä
  2016-12-15 17:12           ` Maarten Lankhorst
  2016-12-29 15:42           ` Maarten Lankhorst
  0 siblings, 2 replies; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 16:09 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 04:45:49PM +0100, Maarten Lankhorst wrote:
> Op 15-12-16 om 16:38 schreef Ville Syrjälä:
> > On Thu, Dec 15, 2016 at 04:30:54PM +0100, Maarten Lankhorst wrote:
> >> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> >>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>
> >>> Start computing the vlv/chv watermarks the atomic way, from the
> >>> .compute_pipe_wm() hook. We'll recompute the actual watermarks
> >>> for only planes that are part of the state, the other planes will
> >>> keep their watermark from the last time it was computed.
> >>>
> >>> And the actual watermark programming will happen from the
> >>> .initial_watermarks() hook. For now we'll just compute the
> >>> optimal watermarks, and we'll hook up the intermediate
> >>> watermarks properly later.
> >>>
> >>> The DSPARB registers responsible for the FIFO paritioning are
> >>> double buffered, so they will be programming from
> >>> intel_begin_crtc_commit().
> >>>
> >>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>> ---
> >>>  drivers/gpu/drm/i915/i915_drv.h      |   8 +
> >>>  drivers/gpu/drm/i915/intel_display.c |  21 ++-
> >>>  drivers/gpu/drm/i915/intel_drv.h     |   2 -
> >>>  drivers/gpu/drm/i915/intel_pm.c      | 327 +++++++++++++++++++++++------------
> >>>  4 files changed, 238 insertions(+), 120 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> >>> index 20bc04d5e617..f23698f99685 100644
> >>> --- a/drivers/gpu/drm/i915/i915_drv.h
> >>> +++ b/drivers/gpu/drm/i915/i915_drv.h
> >>> @@ -493,6 +493,14 @@ struct i915_hotplug {
> >>>  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
> >>>  		for_each_if ((1 << (domain)) & (mask))
> >>>  
> >>> +#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \
> >>> +	for ((__i) = 0; \
> >>> +	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
> >>> +		     ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
> >>> +		      (plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \
> >>> +	     (__i)++) \
> >>> +		for_each_if (plane_state)
> >>> +
> >>>  struct drm_i915_private;
> >>>  struct i915_mm_struct;
> >>>  struct i915_mmu_object;
> >>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >>> index 3f027341b0f3..8d80873b6643 100644
> >>> --- a/drivers/gpu/drm/i915/intel_display.c
> >>> +++ b/drivers/gpu/drm/i915/intel_display.c
> >>> @@ -6736,6 +6736,8 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> >>>  static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> >>>  				   struct drm_atomic_state *old_state)
> >>>  {
> >>> +	struct intel_atomic_state *old_intel_state =
> >>> +		to_intel_atomic_state(old_state);
> >>>  	struct drm_crtc *crtc = pipe_config->base.crtc;
> >>>  	struct drm_device *dev = crtc->dev;
> >>>  	struct drm_i915_private *dev_priv = to_i915(dev);
> >>> @@ -6780,7 +6782,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> >>>  
> >>>  	intel_color_load_luts(&pipe_config->base);
> >>>  
> >>> -	intel_update_watermarks(intel_crtc);
> >>> +	dev_priv->display.initial_watermarks(old_intel_state,
> >>> +					     pipe_config);
> >>>  	intel_enable_pipe(intel_crtc);
> >>>  
> >>>  	assert_vblank_disabled(crtc);
> >>> @@ -6897,6 +6900,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
> >>>  
> >>>  	if (!IS_GEN2(dev_priv))
> >>>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
> >>> +
> >>> +	if (!dev_priv->display.initial_watermarks)
> >>> +		intel_update_watermarks(intel_crtc);
> >>>  }
> >>>  
> >>>  static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
> >>> @@ -12980,10 +12986,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
> >>>  static void
> >>>  clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> >>>  {
> >>> +	struct drm_i915_private *dev_priv =
> >>> +		to_i915(crtc_state->base.crtc->dev);
> >>>  	struct drm_crtc_state tmp_state;
> >>>  	struct intel_crtc_scaler_state scaler_state;
> >>>  	struct intel_dpll_hw_state dpll_hw_state;
> >>>  	struct intel_shared_dpll *shared_dpll;
> >>> +	struct intel_crtc_wm_state wm_state;
> >>>  	bool force_thru;
> >>>  
> >>>  	/* FIXME: before the switch to atomic started, a new pipe_config was
> >>> @@ -12996,6 +13005,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> >>>  	shared_dpll = crtc_state->shared_dpll;
> >>>  	dpll_hw_state = crtc_state->dpll_hw_state;
> >>>  	force_thru = crtc_state->pch_pfit.force_thru;
> >>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> >>> +		wm_state = crtc_state->wm;
> >>>  
> >>>  	memset(crtc_state, 0, sizeof *crtc_state);
> >>>  
> >>> @@ -13004,6 +13015,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> >>>  	crtc_state->shared_dpll = shared_dpll;
> >>>  	crtc_state->dpll_hw_state = dpll_hw_state;
> >>>  	crtc_state->pch_pfit.force_thru = force_thru;
> >>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> >>> +		crtc_state->wm = wm_state;
> >> Is this required? In skl we throw away everything and rebuild using drm_atomic_crtc_state_for_each_plane_state.
> > I don't want to add all the planes into the state when not necessary.
> It doesn't. It uses the fact that updating planes requires crtc mutex, and only iterates over all planes in crtc_state->planes_mask.

Which is setting a somewhat dangerous precedent. So no, I don't think I
want to do that. It's not immediately obvious from the code that it's
100% safe either since the crtc lock is taken after the plane->state
is dereferenced. Which means someon can in parallel be looking at the
old plane state while the new state already exists. I can't think of
a way it could actually go wrong, but seems easier to stick to the
rules and avoid that particular headache entirely.

> Any planes outside it are disabled so wm values can be considered 0, and roughly does the following:
> 
> for_each_plane_in_mask(crtc_state->planes_mask)
> if ((!plane_state = drm_atomic_get_existing_state(state, plane_state)) plane_state = plane->state;
> 
> plane_state must be const, but that's no problem for wm calculations.

And recomputing stuff that didn't even change just seems wasteful.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 13/14] drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
  2016-12-15 15:47     ` Ville Syrjälä
@ 2016-12-15 16:13       ` Maarten Lankhorst
  2016-12-15 16:18         ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 16:13 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

Op 15-12-16 om 16:47 schreef Ville Syrjälä:
> On Thu, Dec 15, 2016 at 04:34:58PM +0100, Maarten Lankhorst wrote:
>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> On VLV/CHV enabling sprite0 when sprite1 has already been enabled may
>>> lead to an underrun. This only happens when sprite0 FIFO size is zero
>>> prior to enabling it. Hence an effective workaround is to always
>>> allocate at least one cacheline for sprite0 when sprite1 is active.
>>>
>>> I've not observed this sort of failure during any other type of plane
>>> enable/disable sequence.
>>>
>>> Testcase: igt/kms_plane_blinker
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> ---
>>>  drivers/gpu/drm/i915/intel_pm.c | 24 +++++++++++++++++++++++-
>>>  1 file changed, 23 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>>> index fa882cdcac52..75a5bde43723 100644
>>> --- a/drivers/gpu/drm/i915/intel_pm.c
>>> +++ b/drivers/gpu/drm/i915/intel_pm.c
>>> @@ -1006,6 +1006,12 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
>>>  	return min_t(int, wm, USHRT_MAX);
>>>  }
>>>  
>>> +static bool vlv_need_sprite0_fifo_workaround(unsigned int active_planes)
>>> +{
>>> +	return (active_planes & (BIT(PLANE_SPRITE0) |
>>> +				 BIT(PLANE_SPRITE1))) == BIT(PLANE_SPRITE1);
>>> +}
>>> +
>>>  static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
>>>  {
>>>  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
>>> @@ -1016,12 +1022,25 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
>>>  	int num_active_planes = hweight32(active_planes);
>>>  	const int fifo_size = 511;
>>>  	int fifo_extra, fifo_left = fifo_size;
>>> +	int sprite0_fifo_extra = 0;
>>>  	unsigned int total_rate;
>>>  	enum plane_id plane_id;
>>>  
>>> +	/*
>>> +	 * When enabling sprite0 after sprite1 has already been enabled
>>> +	 * we tend to get an underrun unless sprite0 already has some
>>> +	 * FIFO space allcoated. Hence we always allocate at least one
>>> +	 * cacheline for sprite0 whenever sprite1 is enabled.
>>> +	 *
>>> +	 * All other plane enable sequences appear immune to this problem.
>>> +	 */
>>> +	if (vlv_need_sprite0_fifo_workaround(active_planes))
>>> +		sprite0_fifo_extra = 1;
>> I don't think you need crtc_state->active_planes just for this, it adds a lot of tracking for something that could be done by
>>
>> if (noninverted->plane[SPRITE1] && !noninverted->plane[SPRITE0])
>> /* allocate 1 for sprite 0 */
>>
>> Maybe drop that patch?
> We'll want it for other things outside of the vlv watermark code as
> well. So figured this is a good excuse for getting the ball rolling,
I haven't seen a good reason yet, at least not one that requires visible_mask = BIT(plane->id)

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

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

* Re: [PATCH 13/14] drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
  2016-12-15 16:13       ` Maarten Lankhorst
@ 2016-12-15 16:18         ` Ville Syrjälä
  0 siblings, 0 replies; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 16:18 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 05:13:37PM +0100, Maarten Lankhorst wrote:
> Op 15-12-16 om 16:47 schreef Ville Syrjälä:
> > On Thu, Dec 15, 2016 at 04:34:58PM +0100, Maarten Lankhorst wrote:
> >> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> >>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>
> >>> On VLV/CHV enabling sprite0 when sprite1 has already been enabled may
> >>> lead to an underrun. This only happens when sprite0 FIFO size is zero
> >>> prior to enabling it. Hence an effective workaround is to always
> >>> allocate at least one cacheline for sprite0 when sprite1 is active.
> >>>
> >>> I've not observed this sort of failure during any other type of plane
> >>> enable/disable sequence.
> >>>
> >>> Testcase: igt/kms_plane_blinker
> >>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>> ---
> >>>  drivers/gpu/drm/i915/intel_pm.c | 24 +++++++++++++++++++++++-
> >>>  1 file changed, 23 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> >>> index fa882cdcac52..75a5bde43723 100644
> >>> --- a/drivers/gpu/drm/i915/intel_pm.c
> >>> +++ b/drivers/gpu/drm/i915/intel_pm.c
> >>> @@ -1006,6 +1006,12 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
> >>>  	return min_t(int, wm, USHRT_MAX);
> >>>  }
> >>>  
> >>> +static bool vlv_need_sprite0_fifo_workaround(unsigned int active_planes)
> >>> +{
> >>> +	return (active_planes & (BIT(PLANE_SPRITE0) |
> >>> +				 BIT(PLANE_SPRITE1))) == BIT(PLANE_SPRITE1);
> >>> +}
> >>> +
> >>>  static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
> >>>  {
> >>>  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> >>> @@ -1016,12 +1022,25 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
> >>>  	int num_active_planes = hweight32(active_planes);
> >>>  	const int fifo_size = 511;
> >>>  	int fifo_extra, fifo_left = fifo_size;
> >>> +	int sprite0_fifo_extra = 0;
> >>>  	unsigned int total_rate;
> >>>  	enum plane_id plane_id;
> >>>  
> >>> +	/*
> >>> +	 * When enabling sprite0 after sprite1 has already been enabled
> >>> +	 * we tend to get an underrun unless sprite0 already has some
> >>> +	 * FIFO space allcoated. Hence we always allocate at least one
> >>> +	 * cacheline for sprite0 whenever sprite1 is enabled.
> >>> +	 *
> >>> +	 * All other plane enable sequences appear immune to this problem.
> >>> +	 */
> >>> +	if (vlv_need_sprite0_fifo_workaround(active_planes))
> >>> +		sprite0_fifo_extra = 1;
> >> I don't think you need crtc_state->active_planes just for this, it adds a lot of tracking for something that could be done by
> >>
> >> if (noninverted->plane[SPRITE1] && !noninverted->plane[SPRITE0])
> >> /* allocate 1 for sprite 0 */
> >>
> >> Maybe drop that patch?
> > We'll want it for other things outside of the vlv watermark code as
> > well. So figured this is a good excuse for getting the ball rolling,
> I haven't seen a good reason yet, at least not one that requires visible_mask = BIT(plane->id)

There are a lot of good reasons for tracking active planes: IPS and gen2
fifo underrun suppression come to mind immediately.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH i-g-t] tests: Add kms_plane_blinker
  2016-12-15 15:41           ` Maarten Lankhorst
@ 2016-12-15 16:42             ` Ville Syrjälä
  2016-12-15 17:26               ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 16:42 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 04:41:51PM +0100, Maarten Lankhorst wrote:
> Op 15-12-16 om 16:36 schreef Ville Syrjälä:
> > On Thu, Dec 15, 2016 at 04:28:52PM +0100, Maarten Lankhorst wrote:
> >> Op 15-12-16 om 16:23 schreef Ville Syrjälä:
> >>> On Thu, Dec 15, 2016 at 04:17:45PM +0100, Maarten Lankhorst wrote:
> >>>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> >>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>>>
> >>>>> Add a test to try out all the different plane enable/disable
> >>>>> order permutations.
> >>>>>
> >>>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>> Didn't look through the test, but sounds like
> >>>>
> >>>> kms_atomic_transitions.plane-*-transition-* ?
> >>>>
> >>>> Although that one tests a few more edge cases like modeset disable and nonblocking updates..
> >>> I don't immediately see where it would try all the permutations, nor can
> >>> I see any crc_nonblock() stuff so doesn't seem like it could even spot
> >>> transient errors.
> >>>
> >> I haven't done any crc test there yet, but the double loop in run_transition_test handles all combinations of planes.
> > permutations > combinations
> >
> It permutates too, I used it for some basic wm testing before. :)

Does it? I'm too lazy to reverse engineed it, so I just tried to run it
but it didn't want to run, so meh.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 14/14] drm/i915: Kill level 0 wm hack for VLV/CHV
  2016-12-12 20:35 ` [PATCH 14/14] drm/i915: Kill level 0 wm hack for VLV/CHV ville.syrjala
@ 2016-12-15 17:10   ` Maarten Lankhorst
  0 siblings, 0 replies; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 17:10 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We now compute the watermarks correctly, so just return an error if we
> can't support the configuration.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 4 ----
>  1 file changed, 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 75a5bde43723..f3aed64e7086 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1163,10 +1163,6 @@ static bool vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
>  		int wm = vlv_compute_wm_level(crtc_state, plane_state, level);
>  		int max_wm = plane_id == PLANE_CURSOR ? 63 : 511;
>  
> -		/* FIXME just bail */
> -		if (WARN_ON(level == 0 && wm > max_wm))
> -			wm = max_wm;
> -
>  		if (wm > max_wm)
>  			break;
>  

Good riddance.

Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

Same for 3, 4, 5 and 6. 2 too if you remove intel_plane_wm_parameters, can do it in the same patch or separately.

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

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

* Re: [PATCH 01/14] drm/i915: Track visible planes in a bitmask
  2016-12-15 15:02     ` Ville Syrjälä
@ 2016-12-15 17:11       ` Maarten Lankhorst
  2016-12-15 17:20         ` Ville Syrjälä
  0 siblings, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 17:11 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

Op 15-12-16 om 16:02 schreef Ville Syrjälä:
> On Thu, Dec 15, 2016 at 03:56:03PM +0100, Maarten Lankhorst wrote:
>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> In a lot of place we wish to know which planes on the crtc are actually
>>> visible, or how many of them there are. Let's start tracking that in a
>>> bitmask in the crtc state.
>>>
>>> We already track enabled planes (ie. ones with an fb and crtc specified by
>>> the user) but that's not quite the same thing as enabled planes may
>>> still end up being invisible due to clipping and whatnot.
>>>
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> ---
>>>  drivers/gpu/drm/i915/intel_atomic_plane.c |  6 +++
>>>  drivers/gpu/drm/i915/intel_display.c      | 79 +++++++++++++++++++++----------
>>>  drivers/gpu/drm/i915/intel_drv.h          |  3 ++
>>>  3 files changed, 64 insertions(+), 24 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
>>> index dbe9fb41ae53..7ec12edda4d4 100644
>>> --- a/drivers/gpu/drm/i915/intel_atomic_plane.c
>>> +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
>>> @@ -181,6 +181,12 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
>>>  	if (ret)
>>>  		return ret;
>>>  
>>> +	/* FIXME pre-g4x don't work like this */
>>> +	if (intel_state->base.visible)
>>> +		crtc_state->active_planes |= BIT(intel_plane->id);
>>> +	else
>>> +		crtc_state->active_planes &= ~BIT(intel_plane->id);
>>> +
>>>  	return intel_plane_atomic_calc_changes(&crtc_state->base, state);
>>>  }
>>>  
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index bc1af87789bc..3f027341b0f3 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -2741,6 +2741,29 @@ update_state_fb(struct drm_plane *plane)
>>>  }
>>>  
>>>  static void
>>> +intel_set_plane_visible(struct intel_crtc_state *crtc_state,
>>> +			struct intel_plane_state *plane_state,
>>> +			bool visible)
>>> +{
>>> +	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
>>> +
>>> +	plane_state->base.visible = visible;
>>> +
>>> +	/* FIXME pre-g4x don't work like this */
>>> +	if (visible) {
>>> +		crtc_state->base.plane_mask |= BIT(drm_plane_index(&plane->base));
>>> +		crtc_state->active_planes |= BIT(plane->id);
>>> +	} else {
>>> +		crtc_state->base.plane_mask &= ~BIT(drm_plane_index(&plane->base));
>>> +		crtc_state->active_planes &= ~BIT(plane->id);
>>> +	}
>>> +
>>> +	DRM_DEBUG_KMS("%s active planes 0x%x\n",
>>> +		      crtc_state->base.crtc->name,
>>> +		      crtc_state->active_planes);
>>> +}
>>> +
>>> +static void
>>>  intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
>>>  			     struct intel_initial_plane_config *plane_config)
>>>  {
>>> @@ -2798,8 +2821,9 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
>>>  	 * simplest solution is to just disable the primary plane now and
>>>  	 * pretend the BIOS never had it enabled.
>>>  	 */
>>> -	to_intel_plane_state(plane_state)->base.visible = false;
>>> -	crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
>>> +	intel_set_plane_visible(to_intel_crtc_state(crtc_state),
>>> +				to_intel_plane_state(plane_state),
>>> +				false);
>>>  	intel_pre_disable_primary_noatomic(&intel_crtc->base);
>>>  	intel_plane->disable_plane(primary, &intel_crtc->base);
>>>  
>>> @@ -2826,7 +2850,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
>>>  	drm_framebuffer_reference(fb);
>>>  	primary->fb = primary->state->fb = fb;
>>>  	primary->crtc = primary->state->crtc = &intel_crtc->base;
>>> -	intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
>>> +
>>> +	intel_set_plane_visible(to_intel_crtc_state(intel_crtc->base.state),
>>> +				to_intel_plane_state(primary->state),
>>> +				true);
>>> +
>>>  	atomic_or(to_intel_plane(primary)->frontbuffer_bit,
>>>  		  &obj->frontbuffer_bits);
>>>  }
>>> @@ -12440,11 +12468,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>>>  	struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
>>>  	struct drm_crtc *crtc = crtc_state->crtc;
>>>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>>> -	struct drm_plane *plane = plane_state->plane;
>>> +	struct intel_plane *plane = to_intel_plane(plane_state->plane);
>>>  	struct drm_device *dev = crtc->dev;
>>>  	struct drm_i915_private *dev_priv = to_i915(dev);
>>>  	struct intel_plane_state *old_plane_state =
>>> -		to_intel_plane_state(plane->state);
>>> +		to_intel_plane_state(plane->base.state);
>>>  	bool mode_changed = needs_modeset(crtc_state);
>>>  	bool was_crtc_enabled = crtc->state->active;
>>>  	bool is_crtc_enabled = crtc_state->active;
>>> @@ -12452,7 +12480,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>>>  	struct drm_framebuffer *fb = plane_state->fb;
>>>  	int ret;
>>>  
>>> -	if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
>>> +	if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_CURSOR) {
>>>  		ret = skl_update_scaler_plane(
>>>  			to_intel_crtc_state(crtc_state),
>>>  			to_intel_plane_state(plane_state));
>>> @@ -12476,8 +12504,10 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>>>  	 * per-plane wm computation to the .check_plane() hook, and
>>>  	 * only combine the results from all planes in the current place?
>>>  	 */
>>> -	if (!is_crtc_enabled)
>>> +	if (!is_crtc_enabled) {
>>>  		to_intel_plane_state(plane_state)->base.visible = visible = false;
>>> +		to_intel_crtc_state(crtc_state)->active_planes &= ~BIT(plane->id);
>>> +	}
>>>  
>>>  	if (!was_visible && !visible)
>>>  		return 0;
>>> @@ -12489,13 +12519,12 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>>>  	turn_on = visible && (!was_visible || mode_changed);
>>>  
>>>  	DRM_DEBUG_ATOMIC("[CRTC:%d:%s] has [PLANE:%d:%s] with fb %i\n",
>>> -			 intel_crtc->base.base.id,
>>> -			 intel_crtc->base.name,
>>> -			 plane->base.id, plane->name,
>>> +			 intel_crtc->base.base.id, intel_crtc->base.name,
>>> +			 plane->base.base.id, plane->base.name,
>>>  			 fb ? fb->base.id : -1);
>>>  
>>>  	DRM_DEBUG_ATOMIC("[PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
>>> -			 plane->base.id, plane->name,
>>> +			 plane->base.base.id, plane->base.name,
>>>  			 was_visible, visible,
>>>  			 turn_off, turn_on, mode_changed);
>>>  
>>> @@ -12503,15 +12532,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>>>  		pipe_config->update_wm_pre = true;
>>>  
>>>  		/* must disable cxsr around plane enable/disable */
>>> -		if (plane->type != DRM_PLANE_TYPE_CURSOR)
>>> +		if (plane->id != PLANE_CURSOR)
>>>  			pipe_config->disable_cxsr = true;
>>>  	} else if (turn_off) {
>>>  		pipe_config->update_wm_post = true;
>>>  
>>>  		/* must disable cxsr around plane enable/disable */
>>> -		if (plane->type != DRM_PLANE_TYPE_CURSOR)
>>> +		if (plane->id != PLANE_CURSOR)
>>>  			pipe_config->disable_cxsr = true;
>>> -	} else if (intel_wm_need_update(plane, plane_state)) {
>>> +	} else if (intel_wm_need_update(&plane->base, plane_state)) {
>>>  		/* FIXME bollocks */
>>>  		pipe_config->update_wm_pre = true;
>>>  		pipe_config->update_wm_post = true;
>>> @@ -12523,7 +12552,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>>>  		to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
>>>  
>>>  	if (visible || was_visible)
>>> -		pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit;
>>> +		pipe_config->fb_bits |= plane->frontbuffer_bit;
>>>  
>>>  	/*
>>>  	 * WaCxSRDisabledForSpriteScaling:ivb
>>> @@ -12531,7 +12560,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>>>  	 * cstate->update_wm was already set above, so this flag will
>>>  	 * take effect when we commit and program watermarks.
>>>  	 */
>>> -	if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) &&
>>> +	if (plane->id == PLANE_SPRITE0 && IS_IVYBRIDGE(dev_priv) &&
>>>  	    needs_scaling(to_intel_plane_state(plane_state)) &&
>>>  	    !needs_scaling(old_plane_state))
>>>  		pipe_config->disable_lp_wm = true;
>>> @@ -16876,15 +16905,14 @@ static bool primary_get_hw_state(struct intel_plane *plane)
>>>  /* FIXME read out full plane state for all planes */
>>>  static void readout_plane_state(struct intel_crtc *crtc)
>>>  {
>>> -	struct drm_plane *primary = crtc->base.primary;
>>> -	struct intel_plane_state *plane_state =
>>> -		to_intel_plane_state(primary->state);
>>> +	struct intel_plane *primary = to_intel_plane(crtc->base.primary);
>>> +	bool visible;
>>>  
>>> -	plane_state->base.visible = crtc->active &&
>>> -		primary_get_hw_state(to_intel_plane(primary));
>>> +	visible = crtc->active && primary_get_hw_state(primary);
>>>  
>>> -	if (plane_state->base.visible)
>>> -		crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
>>> +	intel_set_plane_visible(to_intel_crtc_state(crtc->base.state),
>>> +				to_intel_plane_state(primary->base.state),
>>> +				visible);
>>>  }
>>>  
>>>  static void intel_modeset_readout_hw_state(struct drm_device *dev)
>>> @@ -17171,7 +17199,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
>>>  			c->primary->fb = NULL;
>>>  			c->primary->crtc = c->primary->state->crtc = NULL;
>>>  			update_state_fb(c->primary);
>>> -			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
>>> +
>>> +			intel_set_plane_visible(to_intel_crtc_state(c->state),
>>> +						to_intel_plane_state(c->primary->state),
>>> +						false);
>>>  		}
>>>  	}
>>>  }
>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>>> index 8f4ddca0f521..20ba8f48bc3b 100644
>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>> @@ -669,6 +669,9 @@ struct intel_crtc_state {
>>>  
>>>  	/* Gamma mode programmed on the pipe */
>>>  	uint32_t gamma_mode;
>>> +
>>> +	/* bitmask of visible planes (enum plane_id) */
>>> +	u8 active_planes;
>> Can we change this to uint32_t 1<<drm_plane_index like the other masks?
>>
>> plane_mask, connector_mask and encoder_mask use 1 << index.
>> Perhaps name it active_planes_mask too.
> The way I use it wouldn't lend itself well to that. I don't have any
> plane structs around in a bunch of the places where this gets used.
>
Do you use this outside of 13/14? If not please drop the patch from this series. :)

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

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

* Re: [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way
  2016-12-15 16:09         ` Ville Syrjälä
@ 2016-12-15 17:12           ` Maarten Lankhorst
  2016-12-15 17:17             ` Ville Syrjälä
  2016-12-29 15:42           ` Maarten Lankhorst
  1 sibling, 1 reply; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-15 17:12 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

Op 15-12-16 om 17:09 schreef Ville Syrjälä:
> On Thu, Dec 15, 2016 at 04:45:49PM +0100, Maarten Lankhorst wrote:
>> Op 15-12-16 om 16:38 schreef Ville Syrjälä:
>>> On Thu, Dec 15, 2016 at 04:30:54PM +0100, Maarten Lankhorst wrote:
>>>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
>>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>>
>>>>> Start computing the vlv/chv watermarks the atomic way, from the
>>>>> .compute_pipe_wm() hook. We'll recompute the actual watermarks
>>>>> for only planes that are part of the state, the other planes will
>>>>> keep their watermark from the last time it was computed.
>>>>>
>>>>> And the actual watermark programming will happen from the
>>>>> .initial_watermarks() hook. For now we'll just compute the
>>>>> optimal watermarks, and we'll hook up the intermediate
>>>>> watermarks properly later.
>>>>>
>>>>> The DSPARB registers responsible for the FIFO paritioning are
>>>>> double buffered, so they will be programming from
>>>>> intel_begin_crtc_commit().
>>>>>
>>>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>> ---
>>>>>  drivers/gpu/drm/i915/i915_drv.h      |   8 +
>>>>>  drivers/gpu/drm/i915/intel_display.c |  21 ++-
>>>>>  drivers/gpu/drm/i915/intel_drv.h     |   2 -
>>>>>  drivers/gpu/drm/i915/intel_pm.c      | 327 +++++++++++++++++++++++------------
>>>>>  4 files changed, 238 insertions(+), 120 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>>>>> index 20bc04d5e617..f23698f99685 100644
>>>>> --- a/drivers/gpu/drm/i915/i915_drv.h
>>>>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>>>>> @@ -493,6 +493,14 @@ struct i915_hotplug {
>>>>>  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
>>>>>  		for_each_if ((1 << (domain)) & (mask))
>>>>>  
>>>>> +#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \
>>>>> +	for ((__i) = 0; \
>>>>> +	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
>>>>> +		     ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
>>>>> +		      (plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \
>>>>> +	     (__i)++) \
>>>>> +		for_each_if (plane_state)
>>>>> +
>>>>>  struct drm_i915_private;
>>>>>  struct i915_mm_struct;
>>>>>  struct i915_mmu_object;
>>>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>>>> index 3f027341b0f3..8d80873b6643 100644
>>>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>>>> @@ -6736,6 +6736,8 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>>>>>  static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
>>>>>  				   struct drm_atomic_state *old_state)
>>>>>  {
>>>>> +	struct intel_atomic_state *old_intel_state =
>>>>> +		to_intel_atomic_state(old_state);
>>>>>  	struct drm_crtc *crtc = pipe_config->base.crtc;
>>>>>  	struct drm_device *dev = crtc->dev;
>>>>>  	struct drm_i915_private *dev_priv = to_i915(dev);
>>>>> @@ -6780,7 +6782,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
>>>>>  
>>>>>  	intel_color_load_luts(&pipe_config->base);
>>>>>  
>>>>> -	intel_update_watermarks(intel_crtc);
>>>>> +	dev_priv->display.initial_watermarks(old_intel_state,
>>>>> +					     pipe_config);
>>>>>  	intel_enable_pipe(intel_crtc);
>>>>>  
>>>>>  	assert_vblank_disabled(crtc);
>>>>> @@ -6897,6 +6900,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
>>>>>  
>>>>>  	if (!IS_GEN2(dev_priv))
>>>>>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
>>>>> +
>>>>> +	if (!dev_priv->display.initial_watermarks)
>>>>> +		intel_update_watermarks(intel_crtc);
>>>>>  }
>>>>>  
>>>>>  static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
>>>>> @@ -12980,10 +12986,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
>>>>>  static void
>>>>>  clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>>>>>  {
>>>>> +	struct drm_i915_private *dev_priv =
>>>>> +		to_i915(crtc_state->base.crtc->dev);
>>>>>  	struct drm_crtc_state tmp_state;
>>>>>  	struct intel_crtc_scaler_state scaler_state;
>>>>>  	struct intel_dpll_hw_state dpll_hw_state;
>>>>>  	struct intel_shared_dpll *shared_dpll;
>>>>> +	struct intel_crtc_wm_state wm_state;
>>>>>  	bool force_thru;
>>>>>  
>>>>>  	/* FIXME: before the switch to atomic started, a new pipe_config was
>>>>> @@ -12996,6 +13005,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>>>>>  	shared_dpll = crtc_state->shared_dpll;
>>>>>  	dpll_hw_state = crtc_state->dpll_hw_state;
>>>>>  	force_thru = crtc_state->pch_pfit.force_thru;
>>>>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>>>>> +		wm_state = crtc_state->wm;
>>>>>  
>>>>>  	memset(crtc_state, 0, sizeof *crtc_state);
>>>>>  
>>>>> @@ -13004,6 +13015,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>>>>>  	crtc_state->shared_dpll = shared_dpll;
>>>>>  	crtc_state->dpll_hw_state = dpll_hw_state;
>>>>>  	crtc_state->pch_pfit.force_thru = force_thru;
>>>>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>>>>> +		crtc_state->wm = wm_state;
>>>> Is this required? In skl we throw away everything and rebuild using drm_atomic_crtc_state_for_each_plane_state.
>>> I don't want to add all the planes into the state when not necessary.
>> It doesn't. It uses the fact that updating planes requires crtc mutex, and only iterates over all planes in crtc_state->planes_mask.
> Which is setting a somewhat dangerous precedent. So no, I don't think I
> want to do that. It's not immediately obvious from the code that it's
> 100% safe either since the crtc lock is taken after the plane->state
> is dereferenced. Which means someon can in parallel be looking at the
> old plane state while the new state already exists. I can't think of
> a way it could actually go wrong, but seems easier to stick to the
> rules and avoid that particular headache entirely.
You can't do anything with your duplicated plane state without locking crtc_mutex.
This is what the whole -EDEADLK design will prevent. :)
>> Any planes outside it are disabled so wm values can be considered 0, and roughly does the following:
>>
>> for_each_plane_in_mask(crtc_state->planes_mask)
>> if ((!plane_state = drm_atomic_get_existing_state(state, plane_state)) plane_state = plane->state;
>>
>> plane_state must be const, but that's no problem for wm calculations.
> And recomputing stuff that didn't even change just seems wasteful.
It might change if your fifo allocations are different. Could skip the whole recalculation thing when crtc_state->planes_changed = false.

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

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

* Re: [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way
  2016-12-15 17:12           ` Maarten Lankhorst
@ 2016-12-15 17:17             ` Ville Syrjälä
  0 siblings, 0 replies; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 17:17 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 06:12:12PM +0100, Maarten Lankhorst wrote:
> Op 15-12-16 om 17:09 schreef Ville Syrjälä:
> > On Thu, Dec 15, 2016 at 04:45:49PM +0100, Maarten Lankhorst wrote:
> >> Op 15-12-16 om 16:38 schreef Ville Syrjälä:
> >>> On Thu, Dec 15, 2016 at 04:30:54PM +0100, Maarten Lankhorst wrote:
> >>>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> >>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>>>
> >>>>> Start computing the vlv/chv watermarks the atomic way, from the
> >>>>> .compute_pipe_wm() hook. We'll recompute the actual watermarks
> >>>>> for only planes that are part of the state, the other planes will
> >>>>> keep their watermark from the last time it was computed.
> >>>>>
> >>>>> And the actual watermark programming will happen from the
> >>>>> .initial_watermarks() hook. For now we'll just compute the
> >>>>> optimal watermarks, and we'll hook up the intermediate
> >>>>> watermarks properly later.
> >>>>>
> >>>>> The DSPARB registers responsible for the FIFO paritioning are
> >>>>> double buffered, so they will be programming from
> >>>>> intel_begin_crtc_commit().
> >>>>>
> >>>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>>> ---
> >>>>>  drivers/gpu/drm/i915/i915_drv.h      |   8 +
> >>>>>  drivers/gpu/drm/i915/intel_display.c |  21 ++-
> >>>>>  drivers/gpu/drm/i915/intel_drv.h     |   2 -
> >>>>>  drivers/gpu/drm/i915/intel_pm.c      | 327 +++++++++++++++++++++++------------
> >>>>>  4 files changed, 238 insertions(+), 120 deletions(-)
> >>>>>
> >>>>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> >>>>> index 20bc04d5e617..f23698f99685 100644
> >>>>> --- a/drivers/gpu/drm/i915/i915_drv.h
> >>>>> +++ b/drivers/gpu/drm/i915/i915_drv.h
> >>>>> @@ -493,6 +493,14 @@ struct i915_hotplug {
> >>>>>  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
> >>>>>  		for_each_if ((1 << (domain)) & (mask))
> >>>>>  
> >>>>> +#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \
> >>>>> +	for ((__i) = 0; \
> >>>>> +	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
> >>>>> +		     ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
> >>>>> +		      (plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \
> >>>>> +	     (__i)++) \
> >>>>> +		for_each_if (plane_state)
> >>>>> +
> >>>>>  struct drm_i915_private;
> >>>>>  struct i915_mm_struct;
> >>>>>  struct i915_mmu_object;
> >>>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >>>>> index 3f027341b0f3..8d80873b6643 100644
> >>>>> --- a/drivers/gpu/drm/i915/intel_display.c
> >>>>> +++ b/drivers/gpu/drm/i915/intel_display.c
> >>>>> @@ -6736,6 +6736,8 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
> >>>>>  static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> >>>>>  				   struct drm_atomic_state *old_state)
> >>>>>  {
> >>>>> +	struct intel_atomic_state *old_intel_state =
> >>>>> +		to_intel_atomic_state(old_state);
> >>>>>  	struct drm_crtc *crtc = pipe_config->base.crtc;
> >>>>>  	struct drm_device *dev = crtc->dev;
> >>>>>  	struct drm_i915_private *dev_priv = to_i915(dev);
> >>>>> @@ -6780,7 +6782,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> >>>>>  
> >>>>>  	intel_color_load_luts(&pipe_config->base);
> >>>>>  
> >>>>> -	intel_update_watermarks(intel_crtc);
> >>>>> +	dev_priv->display.initial_watermarks(old_intel_state,
> >>>>> +					     pipe_config);
> >>>>>  	intel_enable_pipe(intel_crtc);
> >>>>>  
> >>>>>  	assert_vblank_disabled(crtc);
> >>>>> @@ -6897,6 +6900,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
> >>>>>  
> >>>>>  	if (!IS_GEN2(dev_priv))
> >>>>>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
> >>>>> +
> >>>>> +	if (!dev_priv->display.initial_watermarks)
> >>>>> +		intel_update_watermarks(intel_crtc);
> >>>>>  }
> >>>>>  
> >>>>>  static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
> >>>>> @@ -12980,10 +12986,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
> >>>>>  static void
> >>>>>  clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> >>>>>  {
> >>>>> +	struct drm_i915_private *dev_priv =
> >>>>> +		to_i915(crtc_state->base.crtc->dev);
> >>>>>  	struct drm_crtc_state tmp_state;
> >>>>>  	struct intel_crtc_scaler_state scaler_state;
> >>>>>  	struct intel_dpll_hw_state dpll_hw_state;
> >>>>>  	struct intel_shared_dpll *shared_dpll;
> >>>>> +	struct intel_crtc_wm_state wm_state;
> >>>>>  	bool force_thru;
> >>>>>  
> >>>>>  	/* FIXME: before the switch to atomic started, a new pipe_config was
> >>>>> @@ -12996,6 +13005,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> >>>>>  	shared_dpll = crtc_state->shared_dpll;
> >>>>>  	dpll_hw_state = crtc_state->dpll_hw_state;
> >>>>>  	force_thru = crtc_state->pch_pfit.force_thru;
> >>>>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> >>>>> +		wm_state = crtc_state->wm;
> >>>>>  
> >>>>>  	memset(crtc_state, 0, sizeof *crtc_state);
> >>>>>  
> >>>>> @@ -13004,6 +13015,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> >>>>>  	crtc_state->shared_dpll = shared_dpll;
> >>>>>  	crtc_state->dpll_hw_state = dpll_hw_state;
> >>>>>  	crtc_state->pch_pfit.force_thru = force_thru;
> >>>>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> >>>>> +		crtc_state->wm = wm_state;
> >>>> Is this required? In skl we throw away everything and rebuild using drm_atomic_crtc_state_for_each_plane_state.
> >>> I don't want to add all the planes into the state when not necessary.
> >> It doesn't. It uses the fact that updating planes requires crtc mutex, and only iterates over all planes in crtc_state->planes_mask.
> > Which is setting a somewhat dangerous precedent. So no, I don't think I
> > want to do that. It's not immediately obvious from the code that it's
> > 100% safe either since the crtc lock is taken after the plane->state
> > is dereferenced. Which means someon can in parallel be looking at the
> > old plane state while the new state already exists. I can't think of
> > a way it could actually go wrong, but seems easier to stick to the
> > rules and avoid that particular headache entirely.
> You can't do anything with your duplicated plane state without locking crtc_mutex.
> This is what the whole -EDEADLK design will prevent. :)
> >> Any planes outside it are disabled so wm values can be considered 0, and roughly does the following:
> >>
> >> for_each_plane_in_mask(crtc_state->planes_mask)
> >> if ((!plane_state = drm_atomic_get_existing_state(state, plane_state)) plane_state = plane->state;
> >>
> >> plane_state must be const, but that's no problem for wm calculations.
> > And recomputing stuff that didn't even change just seems wasteful.
> It might change if your fifo allocations are different. Could skip the whole recalculation thing when crtc_state->planes_changed = false.

Nah. I want better granularity than that. Also FIFO allocation changes
don't require recomputing watermarks.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 01/14] drm/i915: Track visible planes in a bitmask
  2016-12-15 17:11       ` Maarten Lankhorst
@ 2016-12-15 17:20         ` Ville Syrjälä
  0 siblings, 0 replies; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 17:20 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 06:11:24PM +0100, Maarten Lankhorst wrote:
> Op 15-12-16 om 16:02 schreef Ville Syrjälä:
> > On Thu, Dec 15, 2016 at 03:56:03PM +0100, Maarten Lankhorst wrote:
> >> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> >>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>
> >>> In a lot of place we wish to know which planes on the crtc are actually
> >>> visible, or how many of them there are. Let's start tracking that in a
> >>> bitmask in the crtc state.
> >>>
> >>> We already track enabled planes (ie. ones with an fb and crtc specified by
> >>> the user) but that's not quite the same thing as enabled planes may
> >>> still end up being invisible due to clipping and whatnot.
> >>>
> >>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>> ---
> >>>  drivers/gpu/drm/i915/intel_atomic_plane.c |  6 +++
> >>>  drivers/gpu/drm/i915/intel_display.c      | 79 +++++++++++++++++++++----------
> >>>  drivers/gpu/drm/i915/intel_drv.h          |  3 ++
> >>>  3 files changed, 64 insertions(+), 24 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
> >>> index dbe9fb41ae53..7ec12edda4d4 100644
> >>> --- a/drivers/gpu/drm/i915/intel_atomic_plane.c
> >>> +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
> >>> @@ -181,6 +181,12 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
> >>>  	if (ret)
> >>>  		return ret;
> >>>  
> >>> +	/* FIXME pre-g4x don't work like this */
> >>> +	if (intel_state->base.visible)
> >>> +		crtc_state->active_planes |= BIT(intel_plane->id);
> >>> +	else
> >>> +		crtc_state->active_planes &= ~BIT(intel_plane->id);
> >>> +
> >>>  	return intel_plane_atomic_calc_changes(&crtc_state->base, state);
> >>>  }
> >>>  
> >>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >>> index bc1af87789bc..3f027341b0f3 100644
> >>> --- a/drivers/gpu/drm/i915/intel_display.c
> >>> +++ b/drivers/gpu/drm/i915/intel_display.c
> >>> @@ -2741,6 +2741,29 @@ update_state_fb(struct drm_plane *plane)
> >>>  }
> >>>  
> >>>  static void
> >>> +intel_set_plane_visible(struct intel_crtc_state *crtc_state,
> >>> +			struct intel_plane_state *plane_state,
> >>> +			bool visible)
> >>> +{
> >>> +	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
> >>> +
> >>> +	plane_state->base.visible = visible;
> >>> +
> >>> +	/* FIXME pre-g4x don't work like this */
> >>> +	if (visible) {
> >>> +		crtc_state->base.plane_mask |= BIT(drm_plane_index(&plane->base));
> >>> +		crtc_state->active_planes |= BIT(plane->id);
> >>> +	} else {
> >>> +		crtc_state->base.plane_mask &= ~BIT(drm_plane_index(&plane->base));
> >>> +		crtc_state->active_planes &= ~BIT(plane->id);
> >>> +	}
> >>> +
> >>> +	DRM_DEBUG_KMS("%s active planes 0x%x\n",
> >>> +		      crtc_state->base.crtc->name,
> >>> +		      crtc_state->active_planes);
> >>> +}
> >>> +
> >>> +static void
> >>>  intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
> >>>  			     struct intel_initial_plane_config *plane_config)
> >>>  {
> >>> @@ -2798,8 +2821,9 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
> >>>  	 * simplest solution is to just disable the primary plane now and
> >>>  	 * pretend the BIOS never had it enabled.
> >>>  	 */
> >>> -	to_intel_plane_state(plane_state)->base.visible = false;
> >>> -	crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
> >>> +	intel_set_plane_visible(to_intel_crtc_state(crtc_state),
> >>> +				to_intel_plane_state(plane_state),
> >>> +				false);
> >>>  	intel_pre_disable_primary_noatomic(&intel_crtc->base);
> >>>  	intel_plane->disable_plane(primary, &intel_crtc->base);
> >>>  
> >>> @@ -2826,7 +2850,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
> >>>  	drm_framebuffer_reference(fb);
> >>>  	primary->fb = primary->state->fb = fb;
> >>>  	primary->crtc = primary->state->crtc = &intel_crtc->base;
> >>> -	intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
> >>> +
> >>> +	intel_set_plane_visible(to_intel_crtc_state(intel_crtc->base.state),
> >>> +				to_intel_plane_state(primary->state),
> >>> +				true);
> >>> +
> >>>  	atomic_or(to_intel_plane(primary)->frontbuffer_bit,
> >>>  		  &obj->frontbuffer_bits);
> >>>  }
> >>> @@ -12440,11 +12468,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >>>  	struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
> >>>  	struct drm_crtc *crtc = crtc_state->crtc;
> >>>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >>> -	struct drm_plane *plane = plane_state->plane;
> >>> +	struct intel_plane *plane = to_intel_plane(plane_state->plane);
> >>>  	struct drm_device *dev = crtc->dev;
> >>>  	struct drm_i915_private *dev_priv = to_i915(dev);
> >>>  	struct intel_plane_state *old_plane_state =
> >>> -		to_intel_plane_state(plane->state);
> >>> +		to_intel_plane_state(plane->base.state);
> >>>  	bool mode_changed = needs_modeset(crtc_state);
> >>>  	bool was_crtc_enabled = crtc->state->active;
> >>>  	bool is_crtc_enabled = crtc_state->active;
> >>> @@ -12452,7 +12480,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >>>  	struct drm_framebuffer *fb = plane_state->fb;
> >>>  	int ret;
> >>>  
> >>> -	if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
> >>> +	if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_CURSOR) {
> >>>  		ret = skl_update_scaler_plane(
> >>>  			to_intel_crtc_state(crtc_state),
> >>>  			to_intel_plane_state(plane_state));
> >>> @@ -12476,8 +12504,10 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >>>  	 * per-plane wm computation to the .check_plane() hook, and
> >>>  	 * only combine the results from all planes in the current place?
> >>>  	 */
> >>> -	if (!is_crtc_enabled)
> >>> +	if (!is_crtc_enabled) {
> >>>  		to_intel_plane_state(plane_state)->base.visible = visible = false;
> >>> +		to_intel_crtc_state(crtc_state)->active_planes &= ~BIT(plane->id);
> >>> +	}
> >>>  
> >>>  	if (!was_visible && !visible)
> >>>  		return 0;
> >>> @@ -12489,13 +12519,12 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >>>  	turn_on = visible && (!was_visible || mode_changed);
> >>>  
> >>>  	DRM_DEBUG_ATOMIC("[CRTC:%d:%s] has [PLANE:%d:%s] with fb %i\n",
> >>> -			 intel_crtc->base.base.id,
> >>> -			 intel_crtc->base.name,
> >>> -			 plane->base.id, plane->name,
> >>> +			 intel_crtc->base.base.id, intel_crtc->base.name,
> >>> +			 plane->base.base.id, plane->base.name,
> >>>  			 fb ? fb->base.id : -1);
> >>>  
> >>>  	DRM_DEBUG_ATOMIC("[PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
> >>> -			 plane->base.id, plane->name,
> >>> +			 plane->base.base.id, plane->base.name,
> >>>  			 was_visible, visible,
> >>>  			 turn_off, turn_on, mode_changed);
> >>>  
> >>> @@ -12503,15 +12532,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >>>  		pipe_config->update_wm_pre = true;
> >>>  
> >>>  		/* must disable cxsr around plane enable/disable */
> >>> -		if (plane->type != DRM_PLANE_TYPE_CURSOR)
> >>> +		if (plane->id != PLANE_CURSOR)
> >>>  			pipe_config->disable_cxsr = true;
> >>>  	} else if (turn_off) {
> >>>  		pipe_config->update_wm_post = true;
> >>>  
> >>>  		/* must disable cxsr around plane enable/disable */
> >>> -		if (plane->type != DRM_PLANE_TYPE_CURSOR)
> >>> +		if (plane->id != PLANE_CURSOR)
> >>>  			pipe_config->disable_cxsr = true;
> >>> -	} else if (intel_wm_need_update(plane, plane_state)) {
> >>> +	} else if (intel_wm_need_update(&plane->base, plane_state)) {
> >>>  		/* FIXME bollocks */
> >>>  		pipe_config->update_wm_pre = true;
> >>>  		pipe_config->update_wm_post = true;
> >>> @@ -12523,7 +12552,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >>>  		to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
> >>>  
> >>>  	if (visible || was_visible)
> >>> -		pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit;
> >>> +		pipe_config->fb_bits |= plane->frontbuffer_bit;
> >>>  
> >>>  	/*
> >>>  	 * WaCxSRDisabledForSpriteScaling:ivb
> >>> @@ -12531,7 +12560,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> >>>  	 * cstate->update_wm was already set above, so this flag will
> >>>  	 * take effect when we commit and program watermarks.
> >>>  	 */
> >>> -	if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) &&
> >>> +	if (plane->id == PLANE_SPRITE0 && IS_IVYBRIDGE(dev_priv) &&
> >>>  	    needs_scaling(to_intel_plane_state(plane_state)) &&
> >>>  	    !needs_scaling(old_plane_state))
> >>>  		pipe_config->disable_lp_wm = true;
> >>> @@ -16876,15 +16905,14 @@ static bool primary_get_hw_state(struct intel_plane *plane)
> >>>  /* FIXME read out full plane state for all planes */
> >>>  static void readout_plane_state(struct intel_crtc *crtc)
> >>>  {
> >>> -	struct drm_plane *primary = crtc->base.primary;
> >>> -	struct intel_plane_state *plane_state =
> >>> -		to_intel_plane_state(primary->state);
> >>> +	struct intel_plane *primary = to_intel_plane(crtc->base.primary);
> >>> +	bool visible;
> >>>  
> >>> -	plane_state->base.visible = crtc->active &&
> >>> -		primary_get_hw_state(to_intel_plane(primary));
> >>> +	visible = crtc->active && primary_get_hw_state(primary);
> >>>  
> >>> -	if (plane_state->base.visible)
> >>> -		crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
> >>> +	intel_set_plane_visible(to_intel_crtc_state(crtc->base.state),
> >>> +				to_intel_plane_state(primary->base.state),
> >>> +				visible);
> >>>  }
> >>>  
> >>>  static void intel_modeset_readout_hw_state(struct drm_device *dev)
> >>> @@ -17171,7 +17199,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
> >>>  			c->primary->fb = NULL;
> >>>  			c->primary->crtc = c->primary->state->crtc = NULL;
> >>>  			update_state_fb(c->primary);
> >>> -			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
> >>> +
> >>> +			intel_set_plane_visible(to_intel_crtc_state(c->state),
> >>> +						to_intel_plane_state(c->primary->state),
> >>> +						false);
> >>>  		}
> >>>  	}
> >>>  }
> >>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >>> index 8f4ddca0f521..20ba8f48bc3b 100644
> >>> --- a/drivers/gpu/drm/i915/intel_drv.h
> >>> +++ b/drivers/gpu/drm/i915/intel_drv.h
> >>> @@ -669,6 +669,9 @@ struct intel_crtc_state {
> >>>  
> >>>  	/* Gamma mode programmed on the pipe */
> >>>  	uint32_t gamma_mode;
> >>> +
> >>> +	/* bitmask of visible planes (enum plane_id) */
> >>> +	u8 active_planes;
> >> Can we change this to uint32_t 1<<drm_plane_index like the other masks?
> >>
> >> plane_mask, connector_mask and encoder_mask use 1 << index.
> >> Perhaps name it active_planes_mask too.
> > The way I use it wouldn't lend itself well to that. I don't have any
> > plane structs around in a bunch of the places where this gets used.
> >
> Do you use this outside of 13/14? If not please drop the patch from this series. :)

It's used in multiple places.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH i-g-t] tests: Add kms_plane_blinker
  2016-12-15 16:42             ` Ville Syrjälä
@ 2016-12-15 17:26               ` Ville Syrjälä
  2016-12-19  7:07                 ` Maarten Lankhorst
  0 siblings, 1 reply; 47+ messages in thread
From: Ville Syrjälä @ 2016-12-15 17:26 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 06:42:08PM +0200, Ville Syrjälä wrote:
> On Thu, Dec 15, 2016 at 04:41:51PM +0100, Maarten Lankhorst wrote:
> > Op 15-12-16 om 16:36 schreef Ville Syrjälä:
> > > On Thu, Dec 15, 2016 at 04:28:52PM +0100, Maarten Lankhorst wrote:
> > >> Op 15-12-16 om 16:23 schreef Ville Syrjälä:
> > >>> On Thu, Dec 15, 2016 at 04:17:45PM +0100, Maarten Lankhorst wrote:
> > >>>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> > >>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >>>>>
> > >>>>> Add a test to try out all the different plane enable/disable
> > >>>>> order permutations.
> > >>>>>
> > >>>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >>>> Didn't look through the test, but sounds like
> > >>>>
> > >>>> kms_atomic_transitions.plane-*-transition-* ?
> > >>>>
> > >>>> Although that one tests a few more edge cases like modeset disable and nonblocking updates..
> > >>> I don't immediately see where it would try all the permutations, nor can
> > >>> I see any crc_nonblock() stuff so doesn't seem like it could even spot
> > >>> transient errors.
> > >>>
> > >> I haven't done any crc test there yet, but the double loop in run_transition_test handles all combinations of planes.
> > > permutations > combinations
> > >
> > It permutates too, I used it for some basic wm testing before. :)
> 
> Does it? I'm too lazy to reverse engineed it, so I just tried to run it
> but it didn't want to run, so meh.

Needed i915.nuclear_pageflip=1. Didn't even know we had such a knob.

Anywyas, all it tells me is
"Running test on pipe A with resolution 1920x1080 and sprite size 1920x1080 alpha 1"
and similar lines, and mostly I just see a black screen or a blinking backlight.
So I can't tell what it's actually doing.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH i-g-t] tests: Add kms_plane_blinker
  2016-12-15 17:26               ` Ville Syrjälä
@ 2016-12-19  7:07                 ` Maarten Lankhorst
  0 siblings, 0 replies; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-19  7:07 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

Op 15-12-16 om 18:26 schreef Ville Syrjälä:
> On Thu, Dec 15, 2016 at 06:42:08PM +0200, Ville Syrjälä wrote:
>> On Thu, Dec 15, 2016 at 04:41:51PM +0100, Maarten Lankhorst wrote:
>>> Op 15-12-16 om 16:36 schreef Ville Syrjälä:
>>>> On Thu, Dec 15, 2016 at 04:28:52PM +0100, Maarten Lankhorst wrote:
>>>>> Op 15-12-16 om 16:23 schreef Ville Syrjälä:
>>>>>> On Thu, Dec 15, 2016 at 04:17:45PM +0100, Maarten Lankhorst wrote:
>>>>>>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
>>>>>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>>>>>
>>>>>>>> Add a test to try out all the different plane enable/disable
>>>>>>>> order permutations.
>>>>>>>>
>>>>>>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>>>> Didn't look through the test, but sounds like
>>>>>>>
>>>>>>> kms_atomic_transitions.plane-*-transition-* ?
>>>>>>>
>>>>>>> Although that one tests a few more edge cases like modeset disable and nonblocking updates..
>>>>>> I don't immediately see where it would try all the permutations, nor can
>>>>>> I see any crc_nonblock() stuff so doesn't seem like it could even spot
>>>>>> transient errors.
>>>>>>
>>>>> I haven't done any crc test there yet, but the double loop in run_transition_test handles all combinations of planes.
>>>> permutations > combinations
>>>>
>>> It permutates too, I used it for some basic wm testing before. :)
>> Does it? I'm too lazy to reverse engineed it, so I just tried to run it
>> but it didn't want to run, so meh.
> Needed i915.nuclear_pageflip=1. Didn't even know we had such a knob.
That was always needed for any atomic test in i915. :)
> Anywyas, all it tells me is
> "Running test on pipe A with resolution 1920x1080 and sprite size 1920x1080 alpha 1"
> and similar lines, and mostly I just see a black screen or a blinking backlight.
> So I can't tell what it's actually doing.
>
Well you can tell with --debug, it shows all atomic commits done.

It's a nice test for a 4k HDMI display, because in that case I had
big enough planes that having all planes enabled would cause a
underrun because the fifo size was too small. Patch 14 solves this
issue.

~Maarten

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

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

* Re: [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way
  2016-12-15 16:09         ` Ville Syrjälä
  2016-12-15 17:12           ` Maarten Lankhorst
@ 2016-12-29 15:42           ` Maarten Lankhorst
  1 sibling, 0 replies; 47+ messages in thread
From: Maarten Lankhorst @ 2016-12-29 15:42 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

Op 15-12-16 om 17:09 schreef Ville Syrjälä:
> On Thu, Dec 15, 2016 at 04:45:49PM +0100, Maarten Lankhorst wrote:
>> Op 15-12-16 om 16:38 schreef Ville Syrjälä:
>>> On Thu, Dec 15, 2016 at 04:30:54PM +0100, Maarten Lankhorst wrote:
>>>> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
>>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>>
>>>>> Start computing the vlv/chv watermarks the atomic way, from the
>>>>> .compute_pipe_wm() hook. We'll recompute the actual watermarks
>>>>> for only planes that are part of the state, the other planes will
>>>>> keep their watermark from the last time it was computed.
>>>>>
>>>>> And the actual watermark programming will happen from the
>>>>> .initial_watermarks() hook. For now we'll just compute the
>>>>> optimal watermarks, and we'll hook up the intermediate
>>>>> watermarks properly later.
>>>>>
>>>>> The DSPARB registers responsible for the FIFO paritioning are
>>>>> double buffered, so they will be programming from
>>>>> intel_begin_crtc_commit().
>>>>>
>>>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>> ---
>>>>>  drivers/gpu/drm/i915/i915_drv.h      |   8 +
>>>>>  drivers/gpu/drm/i915/intel_display.c |  21 ++-
>>>>>  drivers/gpu/drm/i915/intel_drv.h     |   2 -
>>>>>  drivers/gpu/drm/i915/intel_pm.c      | 327 +++++++++++++++++++++++------------
>>>>>  4 files changed, 238 insertions(+), 120 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>>>>> index 20bc04d5e617..f23698f99685 100644
>>>>> --- a/drivers/gpu/drm/i915/i915_drv.h
>>>>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>>>>> @@ -493,6 +493,14 @@ struct i915_hotplug {
>>>>>  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
>>>>>  		for_each_if ((1 << (domain)) & (mask))
>>>>>  
>>>>> +#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \
>>>>> +	for ((__i) = 0; \
>>>>> +	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
>>>>> +		     ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
>>>>> +		      (plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \
>>>>> +	     (__i)++) \
>>>>> +		for_each_if (plane_state)
>>>>> +
>>>>>  struct drm_i915_private;
>>>>>  struct i915_mm_struct;
>>>>>  struct i915_mmu_object;
>>>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>>>> index 3f027341b0f3..8d80873b6643 100644
>>>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>>>> @@ -6736,6 +6736,8 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
>>>>>  static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
>>>>>  				   struct drm_atomic_state *old_state)
>>>>>  {
>>>>> +	struct intel_atomic_state *old_intel_state =
>>>>> +		to_intel_atomic_state(old_state);
>>>>>  	struct drm_crtc *crtc = pipe_config->base.crtc;
>>>>>  	struct drm_device *dev = crtc->dev;
>>>>>  	struct drm_i915_private *dev_priv = to_i915(dev);
>>>>> @@ -6780,7 +6782,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
>>>>>  
>>>>>  	intel_color_load_luts(&pipe_config->base);
>>>>>  
>>>>> -	intel_update_watermarks(intel_crtc);
>>>>> +	dev_priv->display.initial_watermarks(old_intel_state,
>>>>> +					     pipe_config);
>>>>>  	intel_enable_pipe(intel_crtc);
>>>>>  
>>>>>  	assert_vblank_disabled(crtc);
>>>>> @@ -6897,6 +6900,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
>>>>>  
>>>>>  	if (!IS_GEN2(dev_priv))
>>>>>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
>>>>> +
>>>>> +	if (!dev_priv->display.initial_watermarks)
>>>>> +		intel_update_watermarks(intel_crtc);
>>>>>  }
>>>>>  
>>>>>  static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
>>>>> @@ -12980,10 +12986,13 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
>>>>>  static void
>>>>>  clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>>>>>  {
>>>>> +	struct drm_i915_private *dev_priv =
>>>>> +		to_i915(crtc_state->base.crtc->dev);
>>>>>  	struct drm_crtc_state tmp_state;
>>>>>  	struct intel_crtc_scaler_state scaler_state;
>>>>>  	struct intel_dpll_hw_state dpll_hw_state;
>>>>>  	struct intel_shared_dpll *shared_dpll;
>>>>> +	struct intel_crtc_wm_state wm_state;
>>>>>  	bool force_thru;
>>>>>  
>>>>>  	/* FIXME: before the switch to atomic started, a new pipe_config was
>>>>> @@ -12996,6 +13005,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>>>>>  	shared_dpll = crtc_state->shared_dpll;
>>>>>  	dpll_hw_state = crtc_state->dpll_hw_state;
>>>>>  	force_thru = crtc_state->pch_pfit.force_thru;
>>>>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>>>>> +		wm_state = crtc_state->wm;
>>>>>  
>>>>>  	memset(crtc_state, 0, sizeof *crtc_state);
>>>>>  
>>>>> @@ -13004,6 +13015,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
>>>>>  	crtc_state->shared_dpll = shared_dpll;
>>>>>  	crtc_state->dpll_hw_state = dpll_hw_state;
>>>>>  	crtc_state->pch_pfit.force_thru = force_thru;
>>>>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>>>>> +		crtc_state->wm = wm_state;
>>>> Is this required? In skl we throw away everything and rebuild using drm_atomic_crtc_state_for_each_plane_state.
>>> I don't want to add all the planes into the state when not necessary.
>> It doesn't. It uses the fact that updating planes requires crtc mutex, and only iterates over all planes in crtc_state->planes_mask.
> Which is setting a somewhat dangerous precedent. So no, I don't think I
> want to do that. It's not immediately obvious from the code that it's
> 100% safe either since the crtc lock is taken after the plane->state
> is dereferenced. Which means someon can in parallel be looking at the
> old plane state while the new state already exists. I can't think of
> a way it could actually go wrong, but seems easier to stick to the
> rules and avoid that particular headache entirely.
It can't go wrong as long as it is done before swapping state. We don't write
any plane state so worst that can happen is following:

thread1:
- grab crtc lock
- inspect plane state

thread2:
- grab plane lock
- duplicate plane state, only part that can race with thread1. This is why the iterator has to be const.
- grab crtc lock, wait for thread1 to complete or begin its nonblocking update
- commit and swap state

For things like watermark recalculations it's perfectly safe. Worst that can happen is that either thread
has to back off early with -EDEADLK, in which case the calculations are thrown away when starting over.
>> Any planes outside it are disabled so wm values can be considered 0, and roughly does the following:
>>
>> for_each_plane_in_mask(crtc_state->planes_mask)
>> if ((!plane_state = drm_atomic_get_existing_state(state, plane_state)) plane_state = plane->state;
>>
>> plane_state must be const, but that's no problem for wm calculations.
> And recomputing stuff that didn't even change just seems wasteful.

It's done on skylake because the per crtc allocations have to be changed when a plane is updated.

Adding other planes to the state unnecessarily may introduce extra waits, which is tested for example by

kms_cursor_legacy.flip-vs-cursor-busy-crc-legacy

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

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

* Re: [PATCH 02/14] drm/i915: Track plane fifo sizes under intel_crtc
  2016-12-15 14:58   ` Maarten Lankhorst
@ 2017-02-16 17:48     ` Ville Syrjälä
  0 siblings, 0 replies; 47+ messages in thread
From: Ville Syrjälä @ 2017-02-16 17:48 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 03:58:44PM +0100, Maarten Lankhorst wrote:
> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Track the plane fifo sizes under intel_crtc instead of under each
> > intel_plane. Avoids looping over the planes in a bunch of places,
> > and later we'll move this tracking into the crtc state properly.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_drv.h |   7 ++-
> >  drivers/gpu/drm/i915/intel_pm.c  | 115 ++++++++++++++++-----------------------
> >  2 files changed, 54 insertions(+), 68 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 20ba8f48bc3b..69b6f45e3eed 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -683,6 +683,10 @@ struct vlv_wm_state {
> >  	bool cxsr;
> >  };
> >  
> > +struct vlv_fifo_state {
> > +	uint16_t plane[I915_MAX_PLANES];
> > +};
> > +
> >  struct intel_crtc {
> >  	struct drm_crtc base;
> >  	enum pipe pipe;
> > @@ -732,6 +736,8 @@ struct intel_crtc {
> >  
> >  		/* allow CxSR on this pipe */
> >  		bool cxsr_allowed;
> > +
> > +		struct vlv_fifo_state fifo_state;
> >  	} wm;
> >  
> >  	int scanline_offset;
> > @@ -765,7 +771,6 @@ struct intel_plane_wm_parameters {
> >  	bool scaled;
> >  	u64 tiling;
> >  	unsigned int rotation;
> > -	uint16_t fifo_size;
> >  };
> intel_plane_wm_parameters can be removed entirely, fifo_size was the only member still being used there.

Done.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 08/14] drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not needed
  2016-12-15 15:37   ` Maarten Lankhorst
@ 2017-02-16 17:54     ` Ville Syrjälä
  0 siblings, 0 replies; 47+ messages in thread
From: Ville Syrjälä @ 2017-02-16 17:54 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Thu, Dec 15, 2016 at 04:37:53PM +0100, Maarten Lankhorst wrote:
> Op 12-12-16 om 21:35 schreef ville.syrjala@linux.intel.com:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Check whether anything relevant has actually change when we compute new
> > watermarks for each plane in the state. If the watermarks for no
> > primary/sprite planes changed we don't have to recompute the FIFO split
> > or reprogram the DSBARB registers. And even the cursor watermarks didn't
> > change we can skip the merge+invert step between all the planes on
> > the pipe as well.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_atomic.c |  1 +
> >  drivers/gpu/drm/i915/intel_drv.h    |  1 +
> >  drivers/gpu/drm/i915/intel_pm.c     | 73 +++++++++++++++++++++++++++++--------
> >  3 files changed, 60 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> > index c5a166752eda..df33f270b459 100644
> > --- a/drivers/gpu/drm/i915/intel_atomic.c
> > +++ b/drivers/gpu/drm/i915/intel_atomic.c
> > @@ -99,6 +99,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
> >  	crtc_state->update_wm_pre = false;
> >  	crtc_state->update_wm_post = false;
> >  	crtc_state->fb_changed = false;
> > +	crtc_state->fifo_changed = false;
> >  	crtc_state->wm.need_postvbl_update = false;
> >  	crtc_state->fb_bits = 0;
> This flag is only used in intel_pm.c, maybe put it in crtc_state->wm.vlv.fifo_changed, and clear it in the beginning of the wm recalculation?

I don't really like that. The state we get from duplicate_state() should
be directly useable IMO. It was already checked after all. So all these
kinds of flags should be reset immediately I think.

I guess modeset is a bit of an exception to my logic there. That is I'm
forcing the flag back to true wheever there's a modeset. Alternatively
I could restore the registers whenever the power well gets turned back
on, but this way is a little simpler I think.

> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 66668c18a47a..a92857864ee8 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -560,6 +560,7 @@ struct intel_crtc_state {
> >  	bool disable_cxsr;
> >  	bool update_wm_pre, update_wm_post; /* watermarks are updated */
> >  	bool fb_changed; /* fb on any of the planes is changed */
> > +	bool fifo_changed; /* FIFO split is changed */
> >  
> >  	/* Pipe source size (ie. panel fitter input size)
> >  	 * All planes will be positioned inside this space,
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index f68b46eed224..c7cc62cf51f6 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -1103,31 +1103,36 @@ static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size)
> >  }
> >  
> >  /* starting from 'level' set all higher levels to 'value' */
> > -static void vlv_plane_wm_set(struct intel_crtc_state *crtc_state,
> > +static bool vlv_plane_wm_set(struct intel_crtc_state *crtc_state,
> >  			     int level, enum plane_id plane_id, u16 value)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
> >  	int num_levels = vlv_num_wm_levels(dev_priv);
> > +	bool dirty = false;
> >  
> >  	for (; level < num_levels; level++) {
> >  		struct vlv_pipe_wm *noninverted =
> >  			&crtc_state->wm.vlv.noninverted[level];
> >  
> > +		dirty |= noninverted->plane[plane_id] != value;
> >  		noninverted->plane[plane_id] = value;
> >  	}
> > +
> > +	return dirty;
> >  }
> >  
> > -static void vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
> > +static bool vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
> >  				 const struct intel_plane_state *plane_state)
> >  {
> >  	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
> >  	enum plane_id plane_id = plane->id;
> >  	int num_levels = vlv_num_wm_levels(to_i915(plane->base.dev));
> >  	int level;
> > +	bool dirty = false;
> >  
> >  	if (!plane_state->base.visible) {
> > -		vlv_plane_wm_set(crtc_state, 0, plane_id, 0);
> > -		return;
> > +		dirty |= vlv_plane_wm_set(crtc_state, 0, plane_id, 0);
> > +		goto out;
> >  	}
> >  
> >  	for (level = 0; level < num_levels; level++) {
> > @@ -1143,17 +1148,22 @@ static void vlv_plane_wm_compute(struct intel_crtc_state *crtc_state,
> >  		if (wm > max_wm)
> >  			break;
> >  
> > +		dirty |= noninverted->plane[plane_id] != wm;
> >  		noninverted->plane[plane_id] = wm;
> >  	}
> >  
> >  	/* mark all higher levels as invalid */
> > -	vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
> > +	dirty |= vlv_plane_wm_set(crtc_state, level, plane_id, USHRT_MAX);
> >  
> > -	DRM_DEBUG_KMS("%s wms: [0]=%d,[1]=%d,[2]=%d\n",
> > -		      plane->base.name,
> > -		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2].plane[plane_id],
> > -		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM5].plane[plane_id],
> > -		      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_DDR_DVFS].plane[plane_id]);
> > +out:
> > +	if (dirty)
> > +		DRM_DEBUG_KMS("%s wms: [0]=%d,[1]=%d,[2]=%d\n",
> > +			      plane->base.name,
> > +			      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM2].plane[plane_id],
> > +			      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_PM5].plane[plane_id],
> > +			      crtc_state->wm.vlv.noninverted[VLV_WM_LEVEL_DDR_DVFS].plane[plane_id]);
> > +
> > +	return dirty;
> >  }
> >  
> >  static bool vlv_plane_wm_is_valid(const struct intel_crtc_state *crtc_state,
> > @@ -1186,10 +1196,12 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
> >  		&crtc_state->wm.vlv.fifo_state;
> >  	int num_active_planes = hweight32(crtc_state->active_planes &
> >  					  ~BIT(PLANE_CURSOR));
> > +	bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->base);
> >  	struct intel_plane_state *plane_state;
> >  	struct intel_plane *plane;
> >  	enum plane_id plane_id;
> >  	int level, ret, i;
> > +	unsigned int dirty = 0;
> >  
> >  	for_each_intel_plane_in_state(state, plane, plane_state, i) {
> >  		const struct intel_plane_state *old_plane_state =
> > @@ -1199,7 +1211,37 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
> >  		    old_plane_state->base.crtc != &crtc->base)
> >  			continue;
> >  
> > -		vlv_plane_wm_compute(crtc_state, plane_state);
> > +		if (vlv_plane_wm_compute(crtc_state, plane_state))
> > +			dirty |= BIT(plane->id);
> > +	}
> > +
> > +	/*
> > +	 * DSPARB registers may have been reset due to the
> > +	 * power well being turned off. Make sure we restore
> > +	 * them to a consistent state even if no primary/sprite
> > +	 * planes are initially active.
> > +	 */
> > +	if (needs_modeset)
> > +		crtc_state->fifo_changed = true;
> > +
> > +	if (!dirty)
> > +		return 0;
> > +
> > +	/* cursor changes don't warrant a FIFO recompute */
> > +	if (dirty & ~BIT(PLANE_CURSOR)) {
> > +		const struct intel_crtc_state *old_crtc_state =
> > +			to_intel_crtc_state(crtc->base.state);
> > +		const struct vlv_fifo_state *old_fifo_state =
> > +			&old_crtc_state->wm.vlv.fifo_state;
> > +
> > +		ret = vlv_compute_fifo(crtc_state);
> > +		if (ret)
> > +			return ret;
> > +
> > +		if (needs_modeset ||
> > +		    memcmp(old_fifo_state, fifo_state,
> > +			   sizeof(*fifo_state)) != 0)
> > +			crtc_state->fifo_changed = true;
> >  	}
> >  
> >  	/* initially allow all levels */
> > @@ -1212,10 +1254,6 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state)
> >  	wm_state->cxsr = crtc->pipe != PIPE_C &&
> >  		crtc->wm.cxsr_allowed && num_active_planes == 1;
> >  
> > -	ret = vlv_compute_fifo(crtc_state);
> > -	if (ret)
> > -		return ret;
> > -
> >  	for (level = 0; level < wm_state->num_levels; level++) {
> >  		const struct vlv_pipe_wm *noninverted =
> >  			&crtc_state->wm.vlv.noninverted[level];
> > @@ -1265,6 +1303,9 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
> >  		&crtc_state->wm.vlv.fifo_state;
> >  	int sprite0_start, sprite1_start, fifo_size;
> >  
> > +	if (!crtc_state->fifo_changed)
> > +		return;
> > +
> >  	sprite0_start = fifo_state->plane[PLANE_PRIMARY];
> >  	sprite1_start = fifo_state->plane[PLANE_SPRITE0] + sprite0_start;
> >  	fifo_size = fifo_state->plane[PLANE_SPRITE1] + sprite1_start;
> > @@ -4631,6 +4672,8 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
> >  		active->num_levels = wm->level + 1;
> >  		active->cxsr = wm->cxsr;
> >  
> > +		vlv_get_fifo_size(crtc_state);
> > +
> >  		/* FIXME sanitize things more */
> >  		for (level = 0; level < active->num_levels; level++) {
> >  			struct vlv_pipe_wm *noninverted =
> 

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

end of thread, other threads:[~2017-02-16 17:54 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-12 20:35 [PATCH 00/14] drm/i915: VLV/CHV two-stage watermarks ville.syrjala
2016-12-12 20:35 ` [PATCH 01/14] drm/i915: Track visible planes in a bitmask ville.syrjala
2016-12-15 14:56   ` Maarten Lankhorst
2016-12-15 15:02     ` Ville Syrjälä
2016-12-15 17:11       ` Maarten Lankhorst
2016-12-15 17:20         ` Ville Syrjälä
2016-12-12 20:35 ` [PATCH 02/14] drm/i915: Track plane fifo sizes under intel_crtc ville.syrjala
2016-12-15 14:58   ` Maarten Lankhorst
2017-02-16 17:48     ` Ville Syrjälä
2016-12-12 20:35 ` [PATCH 03/14] drm/i915: Move vlv wms from crtc->wm_state to crtc->wm.active.vlv ville.syrjala
2016-12-12 20:35 ` [PATCH 04/14] drm/i915: Plop vlv wm state into crtc_state ville.syrjala
2016-12-12 20:35 ` [PATCH 05/14] drm/i915: Plop vlv/chv fifo sizes into crtc state ville.syrjala
2016-12-12 20:35 ` [PATCH 06/14] drm/i915: Compute VLV/CHV FIFO sizes based on the PM2 watermarks ville.syrjala
2016-12-12 20:35 ` [PATCH 07/14] drm/i915: Compute vlv/chv wms the atomic way ville.syrjala
2016-12-15 15:30   ` Maarten Lankhorst
2016-12-15 15:38     ` Ville Syrjälä
2016-12-15 15:45       ` Maarten Lankhorst
2016-12-15 16:09         ` Ville Syrjälä
2016-12-15 17:12           ` Maarten Lankhorst
2016-12-15 17:17             ` Ville Syrjälä
2016-12-29 15:42           ` Maarten Lankhorst
2016-12-12 20:35 ` [PATCH 08/14] drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not needed ville.syrjala
2016-12-15 15:37   ` Maarten Lankhorst
2017-02-16 17:54     ` Ville Syrjälä
2016-12-12 20:35 ` [PATCH 09/14] drm/i915: Compute proper intermediate wms for vlv/cvh ville.syrjala
2016-12-12 20:35 ` [PATCH 10/14] drm/i915: Nuke crtc->wm.cxsr_allowed ville.syrjala
2016-12-12 20:35 ` [PATCH 11/14] drm/i915: Only use update_wm_{pre, post} for pre-ilk platforms ville.syrjala
2016-12-12 20:35 ` [PATCH 12/14] drm/i915: Sanitize VLV/CHV watermarks properly ville.syrjala
2016-12-12 20:35 ` [PATCH 13/14] drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun ville.syrjala
2016-12-15 15:34   ` Maarten Lankhorst
2016-12-15 15:47     ` Ville Syrjälä
2016-12-15 16:13       ` Maarten Lankhorst
2016-12-15 16:18         ` Ville Syrjälä
2016-12-12 20:35 ` [PATCH 14/14] drm/i915: Kill level 0 wm hack for VLV/CHV ville.syrjala
2016-12-15 17:10   ` Maarten Lankhorst
2016-12-12 20:35 ` [PATCH i-g-t] tests: Add kms_plane_blinker ville.syrjala
2016-12-15 15:17   ` Maarten Lankhorst
2016-12-15 15:23     ` Ville Syrjälä
2016-12-15 15:28       ` Maarten Lankhorst
2016-12-15 15:36         ` Ville Syrjälä
2016-12-15 15:41           ` Maarten Lankhorst
2016-12-15 16:42             ` Ville Syrjälä
2016-12-15 17:26               ` Ville Syrjälä
2016-12-19  7:07                 ` Maarten Lankhorst
2016-12-12 21:15 ` ✗ Fi.CI.BAT: warning for drm/i915: VLV/CHV two-stage watermarks Patchwork
2016-12-13  7:42   ` Saarinen, Jani
2016-12-13  8:40     ` Chris Wilson

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.