summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2020-01-23 14:59:24 +0100
committerThomas Zimmermann <tzimmermann@suse.de>2020-02-13 13:08:13 +0100
commit7fe3f0d15aac6c98a97e6d7086f5a6b7bc4ccae4 (patch)
treeff005fcab13165c3859c8c4cdce19b181f666e26 /include
parentf1e2b6371c12aec5e772e5fdedaa4455c20a787f (diff)
downloadlinux-7fe3f0d15aac6c98a97e6d7086f5a6b7bc4ccae4.tar.gz
drm: Add get_vblank_timestamp() to struct drm_crtc_funcs
The callback get_vblank_timestamp() is currently located in struct
drm_driver, but really belongs into struct drm_crtc_funcs. Add an
equivalent there. Driver will be converted in separate patches.

The default implementation is drm_calc_vbltimestamp_from_scanoutpos().
The patch adds drm_crtc_vblank_helper_get_vblank_timestamp(), which is
an implementation for the CRTC callback.

v4:
	* more readable code for setting high_prec (Ville, Jani)
v3:
	* use refactored timestamp calculation to minimize duplicated code
	* do more checks for crtc != NULL to support legacy drivers
v2:
	* rename helper to drm_crtc_vblank_helper_get_vblank_timestamp()
	* replace drm_calc_vbltimestamp_from_scanoutpos() with
	  drm_crtc_vblank_helper_get_vblank_timestamp() in docs

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200123135943.24140-4-tzimmermann@suse.de
Diffstat (limited to 'include')
-rw-r--r--include/drm/drm_crtc.h46
-rw-r--r--include/drm/drm_modeset_helper_vtables.h4
-rw-r--r--include/drm/drm_vblank.h16
3 files changed, 58 insertions, 8 deletions
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 6bef2f41d4d7..59b51a09cae6 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -887,6 +887,47 @@ struct drm_crtc_funcs {
 	 * new drivers as the replacement of &drm_driver.disable_vblank hook.
 	 */
 	void (*disable_vblank)(struct drm_crtc *crtc);
+
+	/**
+	 * @get_vblank_timestamp:
+	 *
+	 * Called by drm_get_last_vbltimestamp(). Should return a precise
+	 * timestamp when the most recent vblank interval ended or will end.
+	 *
+	 * Specifically, the timestamp in @vblank_time should correspond as
+	 * closely as possible to the time when the first video scanline of
+	 * the video frame after the end of vblank will start scanning out,
+	 * the time immediately after end of the vblank interval. If the
+	 * @crtc is currently inside vblank, this will be a time in the future.
+	 * If the @crtc is currently scanning out a frame, this will be the
+	 * past start time of the current scanout. This is meant to adhere
+	 * to the OpenML OML_sync_control extension specification.
+	 *
+	 * Parameters:
+	 *
+	 * crtc:
+	 *     CRTC for which timestamp should be returned.
+	 * max_error:
+	 *     Maximum allowable timestamp error in nanoseconds.
+	 *     Implementation should strive to provide timestamp
+	 *     with an error of at most max_error nanoseconds.
+	 *     Returns true upper bound on error for timestamp.
+	 * vblank_time:
+	 *     Target location for returned vblank timestamp.
+	 * in_vblank_irq:
+	 *     True when called from drm_crtc_handle_vblank().  Some drivers
+	 *     need to apply some workarounds for gpu-specific vblank irq quirks
+	 *     if flag is set.
+	 *
+	 * Returns:
+	 *
+	 * True on success, false on failure, which means the core should
+	 * fallback to a simple timestamp taken in drm_crtc_handle_vblank().
+	 */
+	bool (*get_vblank_timestamp)(struct drm_crtc *crtc,
+				     int *max_error,
+				     ktime_t *vblank_time,
+				     bool in_vblank_irq);
 };
 
 /**
@@ -994,11 +1035,12 @@ struct drm_crtc {
 	 * Programmed mode in hw, after adjustments for encoders, crtc, panel
 	 * scaling etc. Should only be used by legacy drivers, for high
 	 * precision vblank timestamps in
-	 * drm_calc_vbltimestamp_from_scanoutpos().
+	 * drm_crtc_vblank_helper_get_vblank_timestamp().
 	 *
 	 * Note that atomic drivers should not use this, but instead use
 	 * &drm_crtc_state.adjusted_mode. And for high-precision timestamps
-	 * drm_calc_vbltimestamp_from_scanoutpos() used &drm_vblank_crtc.hwmode,
+	 * drm_crtc_vblank_helper_get_vblank_timestamp() used
+	 * &drm_vblank_crtc.hwmode,
 	 * which is filled out by calling drm_calc_timestamping_constants().
 	 */
 	struct drm_display_mode hwmode;
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index e398512bfd5f..0afaf58da40d 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -459,8 +459,8 @@ struct drm_crtc_helper_funcs {
 	 * Returns the current display scanout position from a CRTC and an
 	 * optional accurate ktime_get() timestamp of when the position was
 	 * measured. Note that this is a helper callback which is only used
-	 * if a driver uses drm_calc_vbltimestamp_from_scanoutpos() for the
-	 * @drm_driver.get_vblank_timestamp callback.
+	 * if a driver uses drm_crtc_vblank_helper_get_vblank_timestamp()
+	 * for the @drm_crtc_funcs.get_vblank_timestamp callback.
 	 *
 	 * Parameters:
 	 *
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index fd28741e64ed..91f8e35d588d 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -174,13 +174,13 @@ struct drm_vblank_crtc {
 	unsigned int pipe;
 	/**
 	 * @framedur_ns: Frame/Field duration in ns, used by
-	 * drm_calc_vbltimestamp_from_scanoutpos() and computed by
+	 * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by
 	 * drm_calc_timestamping_constants().
 	 */
 	int framedur_ns;
 	/**
 	 * @linedur_ns: Line duration in ns, used by
-	 * drm_calc_vbltimestamp_from_scanoutpos() and computed by
+	 * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by
 	 * drm_calc_timestamping_constants().
 	 */
 	int linedur_ns;
@@ -190,8 +190,8 @@ struct drm_vblank_crtc {
 	 *
 	 * Cache of the current hardware display mode. Only valid when @enabled
 	 * is set. This is used by helpers like
-	 * drm_calc_vbltimestamp_from_scanoutpos(). We can't just access the
-	 * hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode,
+	 * drm_crtc_vblank_helper_get_vblank_timestamp(). We can't just access
+	 * the hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode,
 	 * because that one is really hard to get from interrupt context.
 	 */
 	struct drm_display_mode hwmode;
@@ -240,6 +240,10 @@ 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);
 
+/*
+ * Helpers for struct drm_crtc_funcs
+ */
+
 typedef bool (*drm_vblank_get_scanout_position_func)(struct drm_crtc *crtc,
 						     bool in_vblank_irq,
 						     int *vpos, int *hpos,
@@ -263,5 +267,9 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal(struct drm_crtc *crtc,
 						     bool in_vblank_irq,
 						     drm_vblank_get_scanout_position_func get_scanout_position,
 						     drm_vblank_get_scanout_position_legacy_func get_scanout_position_legacy);
+bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc,
+						 int *max_error,
+						 ktime_t *vblank_time,
+						 bool in_vblank_irq);
 
 #endif