Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+125 -17
+67 -9
drivers/gpu/drm/drm_vblank.c
··· 339 339 u64 vblank; 340 340 unsigned long flags; 341 341 342 - WARN_ONCE(drm_debug_enabled(DRM_UT_VBL) && !dev->driver->get_vblank_timestamp, 342 + WARN_ONCE(drm_debug_enabled(DRM_UT_VBL) && 343 + !crtc->funcs->get_vblank_timestamp && 344 + !dev->driver->get_vblank_timestamp, 343 345 "This function requires support for accurate vblank timestamps."); 344 346 345 347 spin_lock_irqsave(&dev->vblank_time_lock, flags); ··· 541 539 * 542 540 * Calculate and store various constants which are later needed by vblank and 543 541 * swap-completion timestamping, e.g, by 544 - * drm_calc_vbltimestamp_from_scanoutpos(). They are derived from CRTC's true 545 - * scanout timing, so they take things like panel scaling or other adjustments 546 - * into account. 542 + * drm_crtc_vblank_helper_get_vblank_timestamp(). They are derived from 543 + * CRTC's true scanout timing, so they take things like panel scaling or 544 + * other adjustments into account. 547 545 */ 548 546 void drm_calc_timestamping_constants(struct drm_crtc *crtc, 549 547 const struct drm_display_mode *mode) ··· 607 605 * 608 606 * Implements calculation of exact vblank timestamps from given drm_display_mode 609 607 * timings and current video scanout position of a CRTC. This can be directly 610 - * used as the &drm_driver.get_vblank_timestamp implementation of a kms driver 611 - * if &drm_crtc_helper_funcs.get_scanout_position is implemented. 608 + * used as the &drm_crtc_funcs.get_vblank_timestamp implementation of a kms 609 + * driver if &drm_crtc_helper_funcs.get_scanout_position or 610 + * &drm_driver.get_scanout_position is implemented. 612 611 * 613 612 * The current implementation only handles standard video modes. For double scan 614 613 * and interlaced modes the driver is supposed to adjust the hardware mode ··· 806 803 EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_internal); 807 804 808 805 /** 806 + * drm_crtc_vblank_helper_get_vblank_timestamp - precise vblank timestamp 807 + * helper 808 + * @crtc: CRTC whose vblank timestamp to retrieve 809 + * @max_error: Desired maximum allowable error in timestamps (nanosecs) 810 + * On return contains true maximum error of timestamp 811 + * @vblank_time: Pointer to time which should receive the timestamp 812 + * @in_vblank_irq: 813 + * True when called from drm_crtc_handle_vblank(). Some drivers 814 + * need to apply some workarounds for gpu-specific vblank irq quirks 815 + * if flag is set. 816 + * 817 + * Implements calculation of exact vblank timestamps from given drm_display_mode 818 + * timings and current video scanout position of a CRTC. This can be directly 819 + * used as the &drm_crtc_funcs.get_vblank_timestamp implementation of a kms 820 + * driver if &drm_crtc_helper_funcs.get_scanout_position is implemented. 821 + * 822 + * The current implementation only handles standard video modes. For double scan 823 + * and interlaced modes the driver is supposed to adjust the hardware mode 824 + * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to 825 + * match the scanout position reported. 826 + * 827 + * Note that atomic drivers must call drm_calc_timestamping_constants() before 828 + * enabling a CRTC. The atomic helpers already take care of that in 829 + * drm_atomic_helper_update_legacy_modeset_state(). 830 + * 831 + * Returns: 832 + * 833 + * Returns true on success, and false on failure, i.e. when no accurate 834 + * timestamp could be acquired. 835 + */ 836 + bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, 837 + int *max_error, 838 + ktime_t *vblank_time, 839 + bool in_vblank_irq) 840 + { 841 + return drm_crtc_vblank_helper_get_vblank_timestamp_internal( 842 + crtc, max_error, vblank_time, in_vblank_irq, 843 + crtc->helper_private->get_scanout_position, NULL); 844 + } 845 + EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp); 846 + 847 + /** 809 848 * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent 810 849 * vblank interval 811 850 * @dev: DRM device ··· 872 827 drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, 873 828 ktime_t *tvblank, bool in_vblank_irq) 874 829 { 830 + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); 875 831 bool ret = false; 876 832 877 833 /* Define requested maximum error on timestamps (nanoseconds). */ 878 834 int max_error = (int) drm_timestamp_precision * 1000; 879 835 880 836 /* Query driver if possible and precision timestamping enabled. */ 881 - if (dev->driver->get_vblank_timestamp && (max_error > 0)) 837 + if (crtc && crtc->funcs->get_vblank_timestamp && max_error > 0) { 838 + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); 839 + 840 + ret = crtc->funcs->get_vblank_timestamp(crtc, &max_error, 841 + tvblank, in_vblank_irq); 842 + } else if (dev->driver->get_vblank_timestamp && max_error > 0) { 882 843 ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error, 883 844 tvblank, in_vblank_irq); 845 + } 884 846 885 847 /* GPU high precision timestamp query unsupported or failed. 886 848 * Return current monotonic/gettimeofday timestamp as best estimate. ··· 1870 1818 1871 1819 static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) 1872 1820 { 1821 + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); 1822 + bool high_prec = false; 1873 1823 struct drm_pending_vblank_event *e, *t; 1874 1824 ktime_t now; 1875 1825 u64 seq; ··· 1894 1840 send_vblank_event(dev, e, seq, now); 1895 1841 } 1896 1842 1897 - trace_drm_vblank_event(pipe, seq, now, 1898 - dev->driver->get_vblank_timestamp != NULL); 1843 + if (crtc && crtc->funcs->get_vblank_timestamp) 1844 + high_prec = true; 1845 + else if (dev->driver->get_vblank_timestamp) 1846 + high_prec = true; 1847 + 1848 + trace_drm_vblank_event(pipe, seq, now, high_prec); 1899 1849 } 1900 1850 1901 1851 /**
+44 -2
include/drm/drm_crtc.h
··· 887 887 * new drivers as the replacement of &drm_driver.disable_vblank hook. 888 888 */ 889 889 void (*disable_vblank)(struct drm_crtc *crtc); 890 + 891 + /** 892 + * @get_vblank_timestamp: 893 + * 894 + * Called by drm_get_last_vbltimestamp(). Should return a precise 895 + * timestamp when the most recent vblank interval ended or will end. 896 + * 897 + * Specifically, the timestamp in @vblank_time should correspond as 898 + * closely as possible to the time when the first video scanline of 899 + * the video frame after the end of vblank will start scanning out, 900 + * the time immediately after end of the vblank interval. If the 901 + * @crtc is currently inside vblank, this will be a time in the future. 902 + * If the @crtc is currently scanning out a frame, this will be the 903 + * past start time of the current scanout. This is meant to adhere 904 + * to the OpenML OML_sync_control extension specification. 905 + * 906 + * Parameters: 907 + * 908 + * crtc: 909 + * CRTC for which timestamp should be returned. 910 + * max_error: 911 + * Maximum allowable timestamp error in nanoseconds. 912 + * Implementation should strive to provide timestamp 913 + * with an error of at most max_error nanoseconds. 914 + * Returns true upper bound on error for timestamp. 915 + * vblank_time: 916 + * Target location for returned vblank timestamp. 917 + * in_vblank_irq: 918 + * True when called from drm_crtc_handle_vblank(). Some drivers 919 + * need to apply some workarounds for gpu-specific vblank irq quirks 920 + * if flag is set. 921 + * 922 + * Returns: 923 + * 924 + * True on success, false on failure, which means the core should 925 + * fallback to a simple timestamp taken in drm_crtc_handle_vblank(). 926 + */ 927 + bool (*get_vblank_timestamp)(struct drm_crtc *crtc, 928 + int *max_error, 929 + ktime_t *vblank_time, 930 + bool in_vblank_irq); 890 931 }; 891 932 892 933 /** ··· 1035 994 * Programmed mode in hw, after adjustments for encoders, crtc, panel 1036 995 * scaling etc. Should only be used by legacy drivers, for high 1037 996 * precision vblank timestamps in 1038 - * drm_calc_vbltimestamp_from_scanoutpos(). 997 + * drm_crtc_vblank_helper_get_vblank_timestamp(). 1039 998 * 1040 999 * Note that atomic drivers should not use this, but instead use 1041 1000 * &drm_crtc_state.adjusted_mode. And for high-precision timestamps 1042 - * drm_calc_vbltimestamp_from_scanoutpos() used &drm_vblank_crtc.hwmode, 1001 + * drm_crtc_vblank_helper_get_vblank_timestamp() used 1002 + * &drm_vblank_crtc.hwmode, 1043 1003 * which is filled out by calling drm_calc_timestamping_constants(). 1044 1004 */ 1045 1005 struct drm_display_mode hwmode;
+2 -2
include/drm/drm_modeset_helper_vtables.h
··· 459 459 * Returns the current display scanout position from a CRTC and an 460 460 * optional accurate ktime_get() timestamp of when the position was 461 461 * measured. Note that this is a helper callback which is only used 462 - * if a driver uses drm_calc_vbltimestamp_from_scanoutpos() for the 463 - * @drm_driver.get_vblank_timestamp callback. 462 + * if a driver uses drm_crtc_vblank_helper_get_vblank_timestamp() 463 + * for the @drm_crtc_funcs.get_vblank_timestamp callback. 464 464 * 465 465 * Parameters: 466 466 *
+12 -4
include/drm/drm_vblank.h
··· 174 174 unsigned int pipe; 175 175 /** 176 176 * @framedur_ns: Frame/Field duration in ns, used by 177 - * drm_calc_vbltimestamp_from_scanoutpos() and computed by 177 + * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by 178 178 * drm_calc_timestamping_constants(). 179 179 */ 180 180 int framedur_ns; 181 181 /** 182 182 * @linedur_ns: Line duration in ns, used by 183 - * drm_calc_vbltimestamp_from_scanoutpos() and computed by 183 + * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by 184 184 * drm_calc_timestamping_constants(). 185 185 */ 186 186 int linedur_ns; ··· 190 190 * 191 191 * Cache of the current hardware display mode. Only valid when @enabled 192 192 * is set. This is used by helpers like 193 - * drm_calc_vbltimestamp_from_scanoutpos(). We can't just access the 194 - * hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode, 193 + * drm_crtc_vblank_helper_get_vblank_timestamp(). We can't just access 194 + * the hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode, 195 195 * because that one is really hard to get from interrupt context. 196 196 */ 197 197 struct drm_display_mode hwmode; ··· 240 240 void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc, 241 241 u32 max_vblank_count); 242 242 243 + /* 244 + * Helpers for struct drm_crtc_funcs 245 + */ 246 + 243 247 typedef bool (*drm_vblank_get_scanout_position_func)(struct drm_crtc *crtc, 244 248 bool in_vblank_irq, 245 249 int *vpos, int *hpos, ··· 267 263 bool in_vblank_irq, 268 264 drm_vblank_get_scanout_position_func get_scanout_position, 269 265 drm_vblank_get_scanout_position_legacy_func get_scanout_position_legacy); 266 + bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, 267 + int *max_error, 268 + ktime_t *vblank_time, 269 + bool in_vblank_irq); 270 270 271 271 #endif