All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ville Syrjala <ville.syrjala@linux.intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org, stable@vger.kernel.org,
	Inki Dae <inki.dae@samsung.com>, Daniel Vetter <daniel@ffwll.ch>
Subject: [PATCH v2 01/15] drm/vblank: Allow dynamic per-crtc max_vblank_count
Date: Tue, 27 Nov 2018 20:20:04 +0200	[thread overview]
Message-ID: <20181127182004.28885-1-ville.syrjala@linux.intel.com> (raw)
In-Reply-To: <20181112170000.27531-2-ville.syrjala@linux.intel.com>

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

On i965gm we need to adjust max_vblank_count dynamically
depending on whether the TV encoder is used or not. To
that end add a per-crtc max_vblank_count that takes
precedence over its device wide counterpart. The driver
can now call drm_crtc_set_max_vblank_count() to configure
the per-crtc value before calling drm_vblank_on().

Also looks like there was some discussion about exynos needing
similar treatment.

v2: Drop the extra max_vblank_count!=0 check for the
    WARN(last!=current), will take care of it in i915 code (Daniel)
    WARN_ON(!inmodeset) (Daniel)
    WARN_ON(dev->max_vblank_count)
    Pimp up the docs (Daniel)

Cc: stable@vger.kernel.org
Cc: Inki Dae <inki.dae@samsung.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_vblank.c | 45 +++++++++++++++++++++++++++++++++---
 include/drm/drm_device.h     |  8 ++++++-
 include/drm/drm_vblank.h     | 22 ++++++++++++++++++
 3 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 98e091175921..cde71ee95a8f 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -105,13 +105,20 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,
 	write_sequnlock(&vblank->seqlock);
 }
 
+static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
+{
+	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+	return vblank->max_vblank_count ?: dev->max_vblank_count;
+}
+
 /*
  * "No hw counter" fallback implementation of .get_vblank_counter() hook,
  * if there is no useable hardware frame counter available.
  */
 static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
 {
-	WARN_ON_ONCE(dev->max_vblank_count != 0);
+	WARN_ON_ONCE(drm_max_vblank_count(dev, pipe) != 0);
 	return 0;
 }
 
@@ -198,6 +205,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 	ktime_t t_vblank;
 	int count = DRM_TIMESTAMP_MAXRETRIES;
 	int framedur_ns = vblank->framedur_ns;
+	u32 max_vblank_count = drm_max_vblank_count(dev, pipe);
 
 	/*
 	 * Interrupts were disabled prior to this call, so deal with counter
@@ -216,9 +224,9 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, in_vblank_irq);
 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
 
-	if (dev->max_vblank_count != 0) {
+	if (max_vblank_count) {
 		/* trust the hw counter when it's around */
-		diff = (cur_vblank - vblank->last) & dev->max_vblank_count;
+		diff = (cur_vblank - vblank->last) & max_vblank_count;
 	} else if (rc && framedur_ns) {
 		u64 diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
 
@@ -1204,6 +1212,37 @@ void drm_crtc_vblank_reset(struct drm_crtc *crtc)
 }
 EXPORT_SYMBOL(drm_crtc_vblank_reset);
 
+/**
+ * drm_crtc_set_max_vblank_count - configure the hw max vblank counter value
+ * @crtc: CRTC in question
+ * @max_vblank_count: max hardware vblank counter value
+ *
+ * Update the maximum hardware vblank counter value for @crtc
+ * at runtime. Useful for hardware where the operation of the
+ * hardware vblank counter depends on the currently active
+ * display configuration.
+ *
+ * For example, if the hardware vblank counter does not work
+ * when a specific connector is active the maximum can be set
+ * to zero. And when that specific connector isn't active the
+ * maximum can again be set to the appropriate non-zero value.
+ *
+ * If used, must be called before drm_vblank_on().
+ */
+void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
+				   u32 max_vblank_count)
+{
+	struct drm_device *dev = crtc->dev;
+	unsigned int pipe = drm_crtc_index(crtc);
+	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+	WARN_ON(dev->max_vblank_count);
+	WARN_ON(!READ_ONCE(vblank->inmodeset));
+
+	vblank->max_vblank_count = max_vblank_count;
+}
+EXPORT_SYMBOL(drm_crtc_set_max_vblank_count);
+
 /**
  * drm_crtc_vblank_on - enable vblank events on a CRTC
  * @crtc: CRTC in question
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index 42411b3ea0c8..45e43ce9652f 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -184,7 +184,13 @@ struct drm_device {
 	 * races and imprecision over longer time periods, hence exposing a
 	 * hardware vblank counter is always recommended.
 	 *
-	 * If non-zeor, &drm_crtc_funcs.get_vblank_counter must be set.
+	 * This is the statically configured device wide maximum. The driver
+	 * can instead choose to use a runtime configurable per-crtc value
+	 * &drm_vblank_crtc.max_vblank_count, in which case @max_vblank_count
+	 * must be left at zero. See drm_crtc_set_max_vblank_count() on how
+	 * to use the per-crtc value.
+	 *
+	 * If non-zero, &drm_crtc_funcs.get_vblank_counter must be set.
 	 */
 	u32 max_vblank_count;           /**< size of vblank counter register */
 
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index 6ad9630d4f48..e528bb2f659d 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -128,6 +128,26 @@ struct drm_vblank_crtc {
 	 * @last: Protected by &drm_device.vbl_lock, used for wraparound handling.
 	 */
 	u32 last;
+	/**
+	 * @max_vblank_count:
+	 *
+	 * Maximum value of the vblank registers for this crtc. This value +1
+	 * will result in a wrap-around of the vblank register. It is used
+	 * by the vblank core to handle wrap-arounds.
+	 *
+	 * If set to zero the vblank core will try to guess the elapsed vblanks
+	 * between times when the vblank interrupt is disabled through
+	 * high-precision timestamps. That approach is suffering from small
+	 * races and imprecision over longer time periods, hence exposing a
+	 * hardware vblank counter is always recommended.
+	 *
+	 * This is the runtime configurable per-crtc maximum set through
+	 * drm_crtc_set_max_vblank_count(). If this is used the driver
+	 * must leave the device wide &drm_device.max_vblank_count at zero.
+	 *
+	 * If non-zero, &drm_crtc_funcs.get_vblank_counter must be set.
+	 */
+	u32 max_vblank_count;
 	/**
 	 * @inmodeset: Tracks whether the vblank is disabled due to a modeset.
 	 * For legacy driver bit 2 additionally tracks whether an additional
@@ -206,4 +226,6 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
 void drm_calc_timestamping_constants(struct drm_crtc *crtc,
 				     const struct drm_display_mode *mode);
 wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
+void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
+				   u32 max_vblank_count);
 #endif
-- 
2.18.1

WARNING: multiple messages have this Message-ID (diff)
From: Ville Syrjala <ville.syrjala@linux.intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: stable@vger.kernel.org, dri-devel@lists.freedesktop.org
Subject: [PATCH v2 01/15] drm/vblank: Allow dynamic per-crtc max_vblank_count
Date: Tue, 27 Nov 2018 20:20:04 +0200	[thread overview]
Message-ID: <20181127182004.28885-1-ville.syrjala@linux.intel.com> (raw)
In-Reply-To: <20181112170000.27531-2-ville.syrjala@linux.intel.com>

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

On i965gm we need to adjust max_vblank_count dynamically
depending on whether the TV encoder is used or not. To
that end add a per-crtc max_vblank_count that takes
precedence over its device wide counterpart. The driver
can now call drm_crtc_set_max_vblank_count() to configure
the per-crtc value before calling drm_vblank_on().

Also looks like there was some discussion about exynos needing
similar treatment.

v2: Drop the extra max_vblank_count!=0 check for the
    WARN(last!=current), will take care of it in i915 code (Daniel)
    WARN_ON(!inmodeset) (Daniel)
    WARN_ON(dev->max_vblank_count)
    Pimp up the docs (Daniel)

Cc: stable@vger.kernel.org
Cc: Inki Dae <inki.dae@samsung.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_vblank.c | 45 +++++++++++++++++++++++++++++++++---
 include/drm/drm_device.h     |  8 ++++++-
 include/drm/drm_vblank.h     | 22 ++++++++++++++++++
 3 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 98e091175921..cde71ee95a8f 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -105,13 +105,20 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,
 	write_sequnlock(&vblank->seqlock);
 }
 
+static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
+{
+	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+	return vblank->max_vblank_count ?: dev->max_vblank_count;
+}
+
 /*
  * "No hw counter" fallback implementation of .get_vblank_counter() hook,
  * if there is no useable hardware frame counter available.
  */
 static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
 {
-	WARN_ON_ONCE(dev->max_vblank_count != 0);
+	WARN_ON_ONCE(drm_max_vblank_count(dev, pipe) != 0);
 	return 0;
 }
 
@@ -198,6 +205,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 	ktime_t t_vblank;
 	int count = DRM_TIMESTAMP_MAXRETRIES;
 	int framedur_ns = vblank->framedur_ns;
+	u32 max_vblank_count = drm_max_vblank_count(dev, pipe);
 
 	/*
 	 * Interrupts were disabled prior to this call, so deal with counter
@@ -216,9 +224,9 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, in_vblank_irq);
 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
 
-	if (dev->max_vblank_count != 0) {
+	if (max_vblank_count) {
 		/* trust the hw counter when it's around */
-		diff = (cur_vblank - vblank->last) & dev->max_vblank_count;
+		diff = (cur_vblank - vblank->last) & max_vblank_count;
 	} else if (rc && framedur_ns) {
 		u64 diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
 
@@ -1204,6 +1212,37 @@ void drm_crtc_vblank_reset(struct drm_crtc *crtc)
 }
 EXPORT_SYMBOL(drm_crtc_vblank_reset);
 
+/**
+ * drm_crtc_set_max_vblank_count - configure the hw max vblank counter value
+ * @crtc: CRTC in question
+ * @max_vblank_count: max hardware vblank counter value
+ *
+ * Update the maximum hardware vblank counter value for @crtc
+ * at runtime. Useful for hardware where the operation of the
+ * hardware vblank counter depends on the currently active
+ * display configuration.
+ *
+ * For example, if the hardware vblank counter does not work
+ * when a specific connector is active the maximum can be set
+ * to zero. And when that specific connector isn't active the
+ * maximum can again be set to the appropriate non-zero value.
+ *
+ * If used, must be called before drm_vblank_on().
+ */
+void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
+				   u32 max_vblank_count)
+{
+	struct drm_device *dev = crtc->dev;
+	unsigned int pipe = drm_crtc_index(crtc);
+	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+	WARN_ON(dev->max_vblank_count);
+	WARN_ON(!READ_ONCE(vblank->inmodeset));
+
+	vblank->max_vblank_count = max_vblank_count;
+}
+EXPORT_SYMBOL(drm_crtc_set_max_vblank_count);
+
 /**
  * drm_crtc_vblank_on - enable vblank events on a CRTC
  * @crtc: CRTC in question
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index 42411b3ea0c8..45e43ce9652f 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -184,7 +184,13 @@ struct drm_device {
 	 * races and imprecision over longer time periods, hence exposing a
 	 * hardware vblank counter is always recommended.
 	 *
-	 * If non-zeor, &drm_crtc_funcs.get_vblank_counter must be set.
+	 * This is the statically configured device wide maximum. The driver
+	 * can instead choose to use a runtime configurable per-crtc value
+	 * &drm_vblank_crtc.max_vblank_count, in which case @max_vblank_count
+	 * must be left at zero. See drm_crtc_set_max_vblank_count() on how
+	 * to use the per-crtc value.
+	 *
+	 * If non-zero, &drm_crtc_funcs.get_vblank_counter must be set.
 	 */
 	u32 max_vblank_count;           /**< size of vblank counter register */
 
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index 6ad9630d4f48..e528bb2f659d 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -128,6 +128,26 @@ struct drm_vblank_crtc {
 	 * @last: Protected by &drm_device.vbl_lock, used for wraparound handling.
 	 */
 	u32 last;
+	/**
+	 * @max_vblank_count:
+	 *
+	 * Maximum value of the vblank registers for this crtc. This value +1
+	 * will result in a wrap-around of the vblank register. It is used
+	 * by the vblank core to handle wrap-arounds.
+	 *
+	 * If set to zero the vblank core will try to guess the elapsed vblanks
+	 * between times when the vblank interrupt is disabled through
+	 * high-precision timestamps. That approach is suffering from small
+	 * races and imprecision over longer time periods, hence exposing a
+	 * hardware vblank counter is always recommended.
+	 *
+	 * This is the runtime configurable per-crtc maximum set through
+	 * drm_crtc_set_max_vblank_count(). If this is used the driver
+	 * must leave the device wide &drm_device.max_vblank_count at zero.
+	 *
+	 * If non-zero, &drm_crtc_funcs.get_vblank_counter must be set.
+	 */
+	u32 max_vblank_count;
 	/**
 	 * @inmodeset: Tracks whether the vblank is disabled due to a modeset.
 	 * For legacy driver bit 2 additionally tracks whether an additional
@@ -206,4 +226,6 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
 void drm_calc_timestamping_constants(struct drm_crtc *crtc,
 				     const struct drm_display_mode *mode);
 wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
+void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
+				   u32 max_vblank_count);
 #endif
-- 
2.18.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2018-11-28  5:22 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-12 16:59 [PATCH 00/15] drm/i915: Fix TV encoder support Ville Syrjala
2018-11-12 16:59 ` [PATCH 01/15] drm/vblank: Allow dynamic per-crtc max_vblank_count Ville Syrjala
2018-11-21  9:27   ` Daniel Vetter
2018-11-21  9:27     ` Daniel Vetter
2018-11-21 11:37     ` Ville Syrjälä
2018-11-21 11:37       ` Ville Syrjälä
2018-11-21 15:19       ` Daniel Vetter
2018-11-21 15:19         ` Daniel Vetter
2018-11-21 16:16         ` Ville Syrjälä
2018-11-21 16:16           ` Ville Syrjälä
2018-11-21 16:22           ` Daniel Vetter
2018-11-21 16:22             ` Daniel Vetter
2018-11-21 16:46             ` Ville Syrjälä
2018-11-21 16:46               ` Ville Syrjälä
2018-11-22  8:53               ` Daniel Vetter
2018-11-22  8:53                 ` Daniel Vetter
2018-11-27 18:20   ` Ville Syrjala [this message]
2018-11-27 18:20     ` [PATCH v2 " Ville Syrjala
2018-11-27 19:42     ` Daniel Vetter
2018-11-27 19:42       ` Daniel Vetter
2018-11-12 16:59 ` [PATCH 02/15] drm/i915: Don't try to use the hardware frame counter with i965gm TV output Ville Syrjala
2018-11-27 18:21   ` [PATCH v2 " Ville Syrjala
2018-11-27 20:05   ` [PATCH v3 " Ville Syrjala
2019-01-22 12:51     ` Imre Deak
2019-01-22 12:51       ` Imre Deak
2018-11-12 16:59 ` [PATCH 03/15] drm/i915/tv: Fix interlaced ysize calculation Ville Syrjala
2019-01-22 12:54   ` Imre Deak
2018-11-12 16:59 ` [PATCH 04/15] drm/i915/tv: Fix tv mode clocks Ville Syrjala
2019-01-22 12:56   ` Imre Deak
2018-11-12 16:59 ` [PATCH 05/15] drm/i915/tv: Store the TV oversampling factor in the TV mode Ville Syrjala
2019-01-22 13:03   ` Imre Deak
2018-11-12 16:59 ` [PATCH 06/15] drm/i915/tv: Use bools where appropriate Ville Syrjala
2019-01-22 13:07   ` Imre Deak
2018-11-12 16:59 ` [PATCH 07/15] drm/i915/tv: Nuke silly 0 initialzation of xpos/ypos Ville Syrjala
2019-01-22 13:09   ` Imre Deak
2018-11-12 16:59 ` [PATCH 07/15] drm/i915/tv: Nuke silly 0 inittialization " Ville Syrjala
2018-11-12 16:59 ` [PATCH 08/15] drm/i915/tv: Deobfuscate preferred mode selection Ville Syrjala
2019-01-22 14:43   ` [Intel-gfx] " Imre Deak
2018-11-12 16:59 ` [PATCH 09/15] drm/i915/tv: Use drm_mode_set_name() to name TV modes Ville Syrjala
2019-01-22 14:45   ` Imre Deak
2018-11-12 16:59 ` [PATCH 10/15] drm/i915/tv: Make TV mode autoselection actually useable Ville Syrjala
2019-01-22 14:54   ` Imre Deak
2018-11-12 16:59 ` [PATCH 11/15] drm/i915/tv: Nuke reported_modes[] Ville Syrjala
2019-01-22 15:08   ` Imre Deak
2018-11-12 16:59 ` [PATCH 12/15] drm/i915/tv: Add 1080p30/50/60 TV modes Ville Syrjala
2019-01-22 15:09   ` [Intel-gfx] " Imre Deak
2018-11-12 16:59 ` [PATCH 13/15] drm/i915/tv: Generate better pipe timings for TV encoder Ville Syrjala
2019-01-22 17:22   ` Imre Deak
2019-01-22 17:34     ` Ville Syrjälä
2019-01-23 10:30       ` Imre Deak
2018-11-12 16:59 ` [PATCH 14/15] drm/i915/tv: Fix >1024 modes on gen3 Ville Syrjala
2019-01-23 13:49   ` Imre Deak
2019-01-23 16:38     ` [Intel-gfx] " Ville Syrjälä
2019-01-24 10:40       ` Imre Deak
2019-01-25 18:11     ` [Intel-gfx] " Ville Syrjälä
2018-11-12 17:00 ` [PATCH 15/15] drm/i915/tv: Filter out >1024 wide modes that would need vertical scaling " Ville Syrjala
2019-01-23 13:49   ` Imre Deak
2018-11-12 17:16 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Fix TV encoder support Patchwork
2018-11-12 17:31 ` ✓ Fi.CI.BAT: success " Patchwork
2018-11-12 20:06 ` ✓ Fi.CI.IGT: " Patchwork
2018-11-21 16:51 ` ✗ Fi.CI.BAT: failure for drm/i915: Fix TV encoder support (rev2) Patchwork
2018-11-27 19:11 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Fix TV encoder support (rev4) Patchwork
2018-11-27 19:23 ` ✗ Fi.CI.BAT: failure " Patchwork
2018-11-27 20:37 ` ✗ Fi.CI.SPARSE: warning for drm/i915: Fix TV encoder support (rev5) Patchwork
2018-11-27 20:48 ` ✓ Fi.CI.BAT: success " Patchwork
2018-11-28  5:33 ` ✓ Fi.CI.IGT: " Patchwork

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=20181127182004.28885-1-ville.syrjala@linux.intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=inki.dae@samsung.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=stable@vger.kernel.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.