diff options
author | Mario Kleiner <mario.kleiner.de@gmail.com> | 2013-10-30 00:13:06 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-11-05 20:53:41 -0500 |
commit | 8f6fce03ddaf10bfa40c7d6cd59b778d35d41800 (patch) | |
tree | cada34e1587b003af267a75877e30caf60292779 /include | |
parent | 862cc8b4bba9381c1824a0b7ed6404ec2cfb21b1 (diff) |
drm: Push latency sensitive bits of vblank scanoutpos timestamping into kms drivers.
A change in locking of some kms drivers (currently intel-kms) make
the old approach too inaccurate and also incompatible with the
PREEMPT_RT realtime kernel patchset.
The driver->get_scanout_position() method of intel-kms now needs
to aquire a spinlock, which clashes badly with the former
preempt_disable() calls in the drm, and it also introduces larger
delays and timing uncertainty on a contended lock than acceptable.
This patch changes the prototype of driver->get_scanout_position()
to require/allow kms drivers to perform the ktime_get() system time
queries which go along with actual scanout position readout in a way
that provides maximum precision and to return those timestamps to
the drm. kms drivers implementations of get_scanout_position() are
asked to implement timestamping and scanoutpos readout in a way
that is as precise as possible and compatible with preempt_disable()
on a PREMPT_RT kernel. A driver should follow this pattern in
get_scanout_position() for precision and compatibility:
spin_lock...(...);
preempt_disable_rt(); // On a PREEMPT_RT kernel, otherwise omit.
if (stime) *stime = ktime_get();
... Minimum amount of MMIO register reads to get scanout position ...
... no taking of locks allowed here! ...
if (etime) *etime = ktime_get();
preempt_enable_rt(); // On PREEMPT_RT kernel, otherwise omit.
spin_unlock...(...);
v2: Fix formatting of new multi-line code comments.
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/drm/drmP.h | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index e6d0cd9f518e..748c72907829 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -836,12 +836,17 @@ struct drm_driver { | |||
836 | /** | 836 | /** |
837 | * Called by vblank timestamping code. | 837 | * Called by vblank timestamping code. |
838 | * | 838 | * |
839 | * Return the current display scanout position from a crtc. | 839 | * Return the current display scanout position from a crtc, and an |
840 | * optional accurate ktime_get timestamp of when position was measured. | ||
840 | * | 841 | * |
841 | * \param dev DRM device. | 842 | * \param dev DRM device. |
842 | * \param crtc Id of the crtc to query. | 843 | * \param crtc Id of the crtc to query. |
843 | * \param *vpos Target location for current vertical scanout position. | 844 | * \param *vpos Target location for current vertical scanout position. |
844 | * \param *hpos Target location for current horizontal scanout position. | 845 | * \param *hpos Target location for current horizontal scanout position. |
846 | * \param *stime Target location for timestamp taken immediately before | ||
847 | * scanout position query. Can be NULL to skip timestamp. | ||
848 | * \param *etime Target location for timestamp taken immediately after | ||
849 | * scanout position query. Can be NULL to skip timestamp. | ||
845 | * | 850 | * |
846 | * Returns vpos as a positive number while in active scanout area. | 851 | * Returns vpos as a positive number while in active scanout area. |
847 | * Returns vpos as a negative number inside vblank, counting the number | 852 | * Returns vpos as a negative number inside vblank, counting the number |
@@ -858,7 +863,8 @@ struct drm_driver { | |||
858 | * | 863 | * |
859 | */ | 864 | */ |
860 | int (*get_scanout_position) (struct drm_device *dev, int crtc, | 865 | int (*get_scanout_position) (struct drm_device *dev, int crtc, |
861 | int *vpos, int *hpos); | 866 | int *vpos, int *hpos, ktime_t *stime, |
867 | ktime_t *etime); | ||
862 | 868 | ||
863 | /** | 869 | /** |
864 | * Called by \c drm_get_last_vbltimestamp. Should return a precise | 870 | * Called by \c drm_get_last_vbltimestamp. Should return a precise |