All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ville Syrjala <ville.syrjala@linux.intel.com>
To: intel-gfx@lists.freedesktop.org
Subject: [PATCH 7/9] drm/i915: Move intel_vblank_evade() & co. into intel_vblank.c
Date: Wed, 13 Dec 2023 12:25:17 +0200	[thread overview]
Message-ID: <20231213102519.13500-8-ville.syrjala@linux.intel.com> (raw)
In-Reply-To: <20231213102519.13500-1-ville.syrjala@linux.intel.com>

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

intel_vblank.c seems like the appropriate place for the core
vblank evasion code. Move it there.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_crtc.c   | 135 --------------------
 drivers/gpu/drm/i915/display/intel_vblank.c | 130 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_vblank.h |  12 ++
 3 files changed, 142 insertions(+), 135 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 11a6a4b0a258..25593f6aae7d 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -461,141 +461,6 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
 			    1000 * adjusted_mode->crtc_htotal);
 }
 
-static int intel_mode_vblank_start(const struct drm_display_mode *mode)
-{
-	int vblank_start = mode->crtc_vblank_start;
-
-	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-		vblank_start = DIV_ROUND_UP(vblank_start, 2);
-
-	return vblank_start;
-}
-
-struct intel_vblank_evade_ctx {
-	struct intel_crtc *crtc;
-	int min, max, vblank_start;
-	bool need_vlv_dsi_wa;
-};
-
-static void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state,
-				    const struct intel_crtc_state *new_crtc_state,
-				    struct intel_vblank_evade_ctx *evade)
-{
-	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
-	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
-	const struct intel_crtc_state *crtc_state;
-	const struct drm_display_mode *adjusted_mode;
-
-	evade->crtc = crtc;
-
-	evade->need_vlv_dsi_wa = (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) &&
-		intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
-
-	/*
-	 * During fastsets/etc. the transcoder is still
-	 * running with the old timings at this point.
-	 *
-	 * TODO: maybe just use the active timings here?
-	 */
-	if (intel_crtc_needs_modeset(new_crtc_state))
-		crtc_state = new_crtc_state;
-	else
-		crtc_state = old_crtc_state;
-
-	adjusted_mode = &crtc_state->hw.adjusted_mode;
-
-	if (crtc->mode_flags & I915_MODE_FLAG_VRR) {
-		/* timing changes should happen with VRR disabled */
-		drm_WARN_ON(crtc->base.dev, intel_crtc_needs_modeset(new_crtc_state) ||
-			    new_crtc_state->update_m_n || new_crtc_state->update_lrr);
-
-		if (intel_vrr_is_push_sent(crtc_state))
-			evade->vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
-		else
-			evade->vblank_start = intel_vrr_vmax_vblank_start(crtc_state);
-	} else {
-		evade->vblank_start = intel_mode_vblank_start(adjusted_mode);
-	}
-
-	/* FIXME needs to be calibrated sensibly */
-	evade->min = evade->vblank_start - intel_usecs_to_scanlines(adjusted_mode,
-								VBLANK_EVASION_TIME_US);
-	evade->max = evade->vblank_start - 1;
-
-	/*
-	 * M/N and TRANS_VTOTAL are double buffered on the transcoder's
-	 * undelayed vblank, so with seamless M/N and LRR we must evade
-	 * both vblanks.
-	 *
-	 * DSB execution waits for the transcoder's undelayed vblank,
-	 * hence we must kick off the commit before that.
-	 */
-	if (new_crtc_state->dsb || new_crtc_state->update_m_n || new_crtc_state->update_lrr)
-		evade->min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay;
-}
-
-/* must be called with vblank interrupt already enabled! */
-static int intel_vblank_evade(struct intel_vblank_evade_ctx *evade)
-{
-	struct intel_crtc *crtc = evade->crtc;
-	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
-	long timeout = msecs_to_jiffies_timeout(1);
-	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
-	DEFINE_WAIT(wait);
-	int scanline;
-
-	if (evade->min <= 0 || evade->max <= 0)
-		return 0;
-
-	for (;;) {
-		/*
-		 * prepare_to_wait() has a memory barrier, which guarantees
-		 * other CPUs can see the task state update by the time we
-		 * read the scanline.
-		 */
-		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
-
-		scanline = intel_get_crtc_scanline(crtc);
-		if (scanline < evade->min || scanline > evade->max)
-			break;
-
-		if (!timeout) {
-			drm_err(&i915->drm,
-				"Potential atomic update failure on pipe %c\n",
-				pipe_name(crtc->pipe));
-			break;
-		}
-
-		local_irq_enable();
-
-		timeout = schedule_timeout(timeout);
-
-		local_irq_disable();
-	}
-
-	finish_wait(wq, &wait);
-
-	/*
-	 * On VLV/CHV DSI the scanline counter would appear to
-	 * increment approx. 1/3 of a scanline before start of vblank.
-	 * The registers still get latched at start of vblank however.
-	 * This means we must not write any registers on the first
-	 * line of vblank (since not the whole line is actually in
-	 * vblank). And unfortunately we can't use the interrupt to
-	 * wait here since it will fire too soon. We could use the
-	 * frame start interrupt instead since it will fire after the
-	 * critical scanline, but that would require more changes
-	 * in the interrupt code. So for now we'll just do the nasty
-	 * thing and poll for the bad scanline to pass us by.
-	 *
-	 * FIXME figure out if BXT+ DSI suffers from this as well
-	 */
-	while (evade->need_vlv_dsi_wa && scanline == evade->vblank_start)
-		scanline = intel_get_crtc_scanline(crtc);
-
-	return scanline;
-}
-
 /**
  * intel_pipe_update_start() - start update of a set of display registers
  * @state: the atomic state
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c
index fe256bf7b485..baf7354cb6e2 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.c
+++ b/drivers/gpu/drm/i915/display/intel_vblank.c
@@ -5,6 +5,7 @@
 
 #include "i915_drv.h"
 #include "i915_reg.h"
+#include "intel_crtc.h"
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_vblank.h"
@@ -581,3 +582,132 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state,
 	intel_vblank_section_exit(i915);
 	spin_unlock_irqrestore(&i915->drm.vblank_time_lock, irqflags);
 }
+
+static int intel_mode_vblank_start(const struct drm_display_mode *mode)
+{
+	int vblank_start = mode->crtc_vblank_start;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		vblank_start = DIV_ROUND_UP(vblank_start, 2);
+
+	return vblank_start;
+}
+
+void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state,
+			     const struct intel_crtc_state *new_crtc_state,
+			     struct intel_vblank_evade_ctx *evade)
+{
+	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+	const struct intel_crtc_state *crtc_state;
+	const struct drm_display_mode *adjusted_mode;
+
+	evade->crtc = crtc;
+
+	evade->need_vlv_dsi_wa = (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) &&
+		intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
+
+	/*
+	 * During fastsets/etc. the transcoder is still
+	 * running with the old timings at this point.
+	 *
+	 * TODO: maybe just use the active timings here?
+	 */
+	if (intel_crtc_needs_modeset(new_crtc_state))
+		crtc_state = new_crtc_state;
+	else
+		crtc_state = old_crtc_state;
+
+	adjusted_mode = &crtc_state->hw.adjusted_mode;
+
+	if (crtc->mode_flags & I915_MODE_FLAG_VRR) {
+		/* timing changes should happen with VRR disabled */
+		drm_WARN_ON(crtc->base.dev, intel_crtc_needs_modeset(new_crtc_state) ||
+			    new_crtc_state->update_m_n || new_crtc_state->update_lrr);
+
+		if (intel_vrr_is_push_sent(crtc_state))
+			evade->vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
+		else
+			evade->vblank_start = intel_vrr_vmax_vblank_start(crtc_state);
+	} else {
+		evade->vblank_start = intel_mode_vblank_start(adjusted_mode);
+	}
+
+	/* FIXME needs to be calibrated sensibly */
+	evade->min = evade->vblank_start - intel_usecs_to_scanlines(adjusted_mode,
+								    VBLANK_EVASION_TIME_US);
+	evade->max = evade->vblank_start - 1;
+
+	/*
+	 * M/N and TRANS_VTOTAL are double buffered on the transcoder's
+	 * undelayed vblank, so with seamless M/N and LRR we must evade
+	 * both vblanks.
+	 *
+	 * DSB execution waits for the transcoder's undelayed vblank,
+	 * hence we must kick off the commit before that.
+	 */
+	if (new_crtc_state->dsb || new_crtc_state->update_m_n || new_crtc_state->update_lrr)
+		evade->min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay;
+}
+
+/* must be called with vblank interrupt already enabled! */
+int intel_vblank_evade(struct intel_vblank_evade_ctx *evade)
+{
+	struct intel_crtc *crtc = evade->crtc;
+	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+	long timeout = msecs_to_jiffies_timeout(1);
+	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
+	DEFINE_WAIT(wait);
+	int scanline;
+
+	if (evade->min <= 0 || evade->max <= 0)
+		return 0;
+
+	for (;;) {
+		/*
+		 * prepare_to_wait() has a memory barrier, which guarantees
+		 * other CPUs can see the task state update by the time we
+		 * read the scanline.
+		 */
+		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
+
+		scanline = intel_get_crtc_scanline(crtc);
+		if (scanline < evade->min || scanline > evade->max)
+			break;
+
+		if (!timeout) {
+			drm_err(&i915->drm,
+				"Potential atomic update failure on pipe %c\n",
+				pipe_name(crtc->pipe));
+			break;
+		}
+
+		local_irq_enable();
+
+		timeout = schedule_timeout(timeout);
+
+		local_irq_disable();
+	}
+
+	finish_wait(wq, &wait);
+
+	/*
+	 * On VLV/CHV DSI the scanline counter would appear to
+	 * increment approx. 1/3 of a scanline before start of vblank.
+	 * The registers still get latched at start of vblank however.
+	 * This means we must not write any registers on the first
+	 * line of vblank (since not the whole line is actually in
+	 * vblank). And unfortunately we can't use the interrupt to
+	 * wait here since it will fire too soon. We could use the
+	 * frame start interrupt instead since it will fire after the
+	 * critical scanline, but that would require more changes
+	 * in the interrupt code. So for now we'll just do the nasty
+	 * thing and poll for the bad scanline to pass us by.
+	 *
+	 * FIXME figure out if BXT+ DSI suffers from this as well
+	 */
+	while (evade->need_vlv_dsi_wa && scanline == evade->vblank_start)
+		scanline = intel_get_crtc_scanline(crtc);
+
+	return scanline;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h
index 17636f140c71..ec6c3da3eeac 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.h
+++ b/drivers/gpu/drm/i915/display/intel_vblank.h
@@ -13,6 +13,18 @@ struct drm_crtc;
 struct intel_crtc;
 struct intel_crtc_state;
 
+struct intel_vblank_evade_ctx {
+	struct intel_crtc *crtc;
+	int min, max, vblank_start;
+	bool need_vlv_dsi_wa;
+};
+
+void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state,
+			     const struct intel_crtc_state *new_crtc_state,
+			     struct intel_vblank_evade_ctx *evade);
+/* must be called with vblank interrupt already enabled! */
+int intel_vblank_evade(struct intel_vblank_evade_ctx *evade);
+
 u32 i915_get_vblank_counter(struct drm_crtc *crtc);
 u32 g4x_get_vblank_counter(struct drm_crtc *crtc);
 bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error,
-- 
2.41.0


  parent reply	other threads:[~2023-12-13 10:25 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-13 10:25 [PATCH 0/9] drm/i915: Cursor vblank evasion Ville Syrjala
2023-12-13 10:25 ` [PATCH 1/9] drm/i915: Decouple intel_crtc_vblank_evade_scanlines() from atomic commits Ville Syrjala
2023-12-20 11:11   ` Shankar, Uma
2023-12-13 10:25 ` [PATCH 2/9] drm/i915: Reorder drm_vblank_put() vs. need_vlv_dsi_wa Ville Syrjala
2023-12-20 11:20   ` Shankar, Uma
2023-12-13 10:25 ` [PATCH 3/9] drm/i915: Introduce struct intel_vblank_evade_ctx Ville Syrjala
2023-12-20 11:22   ` Shankar, Uma
2023-12-13 10:25 ` [PATCH 4/9] drm/i915: Include need_vlv_dsi_wa in intel_vblank_evade_ctx Ville Syrjala
2023-12-20 11:22   ` Shankar, Uma
2023-12-13 10:25 ` [PATCH 5/9] drm/i915: Extract intel_vblank_evade() Ville Syrjala
2023-12-20 11:26   ` Shankar, Uma
2023-12-13 10:25 ` [PATCH 6/9] drm/i915: Move the min/max scanline sanity check into intel_vblank_evade() Ville Syrjala
2023-12-20 11:27   ` Shankar, Uma
2023-12-13 10:25 ` Ville Syrjala [this message]
2023-12-20 11:28   ` [PATCH 7/9] drm/i915: Move intel_vblank_evade() & co. into intel_vblank.c Shankar, Uma
2023-12-13 10:25 ` [PATCH 8/9] drm/i915: Perform vblank evasion around legacy cursor updates Ville Syrjala
2023-12-20 11:41   ` Shankar, Uma
2023-12-20 11:45     ` Shankar, Uma
2023-12-20 14:48       ` Ville Syrjälä
2023-12-22  5:07         ` Shankar, Uma
2024-01-16 20:49   ` [PATCH v2 " Ville Syrjala
2024-01-17 13:16     ` Hogander, Jouni
2024-01-18  7:53     ` Hogander, Jouni
2024-01-18  9:03     ` Hogander, Jouni
2023-12-13 10:25 ` [PATCH 9/9] Revert "drm/i915/xe2lpd: Treat cursor plane as regular plane for DDB allocation" Ville Syrjala
2023-12-13 11:28   ` Lisovskiy, Stanislav
2023-12-13 15:15     ` Ville Syrjälä
2023-12-13 15:29       ` Ville Syrjälä
2023-12-15 11:15         ` Ville Syrjälä
2024-01-09 12:17           ` Lisovskiy, Stanislav
2023-12-13 20:51 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cursor vblank evasion Patchwork
2023-12-13 21:08 ` ✗ Fi.CI.BAT: failure " Patchwork
2023-12-18 10:35   ` Saarinen, Jani
2024-01-18  8:04     ` Illipilli, TejasreeX
2024-01-19  8:11       ` Saarinen, Jani
2023-12-19 11:54 ` ✓ Fi.CI.BAT: success " Patchwork
2023-12-19 13:51 ` ✗ Fi.CI.IGT: failure " Patchwork
2024-01-09 12:34 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cursor vblank evasion (rev2) Patchwork
2024-01-09 12:48 ` ✓ Fi.CI.BAT: success " Patchwork
2024-01-09 15:10 ` ✗ Fi.CI.IGT: failure " Patchwork
2024-01-16 21:22 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cursor vblank evasion (rev3) Patchwork
2024-01-16 21:36 ` ✗ Fi.CI.BAT: failure " Patchwork
2024-01-17  8:02 ` ✓ Fi.CI.IGT: success for drm/i915: Cursor vblank evasion (rev2) Patchwork
2024-01-17  8:07 ` ✓ Fi.CI.BAT: success for drm/i915: Cursor vblank evasion (rev3) Patchwork
2024-01-17 10:31 ` ✗ Fi.CI.IGT: failure " Patchwork
2024-01-17 11:30 ` [PATCH 0/9] drm/i915: Cursor vblank evasion Shankar, Uma
2024-01-17 12:13   ` Ville Syrjälä
2024-01-18  7:57 ` ✓ Fi.CI.IGT: success for drm/i915: Cursor vblank evasion (rev3) Patchwork
2024-01-22 11:43 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Cursor vblank evasion (rev4) Patchwork
2024-01-22 11:56 ` ✓ Fi.CI.BAT: success " Patchwork
2024-01-22 15:03 ` ✗ Fi.CI.IGT: failure " Patchwork
2024-01-22 16:59   ` Ville Syrjälä

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231213102519.13500-8-ville.syrjala@linux.intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.