From 7beb691f1e6f349c9df3384a85e7a53c5601aaaf Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 29 Jan 2020 13:05:17 +0100 Subject: drm: Initialize struct drm_crtc_state.no_vblank from device settings At the end of a commit, atomic helpers can generate a fake VBLANK event automatically. Originally implemented for writeback connectors, the functionality can be used by any driver and/or hardware without proper VBLANK interrupt. The patch updates the documentation to make this behaviour official: settings struct drm_crtc_state.no_vblank to true enables automatic generation of fake VBLANK events. The new interface drm_dev_has_vblank() returns true if vblanking has been initialized for a device, or false otherwise. Atomic helpers use this function when initializing no_vblank in the CRTC state in drm_atomic_helper_check_modeset(). If vblanking has been initialized for a device, no_blank is disabled. Otherwise it's enabled. Hence, atomic helpers will automatically send out fake VBLANK events with any driver that did not initialize vblanking. v5: * more precise documentation and commit message v4: * replace drm_crtc_has_vblank() with drm_dev_has_vblank() * add drm_dev_has_vblank() in this patch * move driver changes into separate patches v3: * squash all related changes patches into this patch Signed-off-by: Thomas Zimmermann Acked-by: Gerd Hoffmann Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20200129120531.6891-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_vblank.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/gpu/drm/drm_vblank.c') diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 1659b13b178c..27a99c486f02 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -69,6 +69,12 @@ * &drm_driver.max_vblank_count. In that case the vblank core only disables the * vblanks after a timer has expired, which can be configured through the * ``vblankoffdelay`` module parameter. + * + * Drivers for hardware without support for vertical-blanking interrupts + * must not call drm_vblank_init(). For such drivers, atomic helpers will + * automatically generate fake vblank events as part of the display update. + * This functionality also can be controlled by the driver by enabling and + * disabling struct drm_crtc_state.no_vblank. */ /* Retry timestamp calculation up to 3 times to satisfy @@ -501,6 +507,28 @@ err: } EXPORT_SYMBOL(drm_vblank_init); +/** + * drm_dev_has_vblank - test if vblanking has been initialized for + * a device + * @dev: the device + * + * Drivers may call this function to test if vblank support is + * initialized for a device. For most hardware this means that vblanking + * can also be enabled. + * + * Atomic helpers use this function to initialize + * &drm_crtc_state.no_vblank. See also drm_atomic_helper_check_modeset(). + * + * Returns: + * True if vblanking has been initialized for the given device, false + * otherwise. + */ +bool drm_dev_has_vblank(const struct drm_device *dev) +{ + return dev->num_crtcs != 0; +} +EXPORT_SYMBOL(drm_dev_has_vblank); + /** * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC * @crtc: which CRTC's vblank waitqueue to retrieve -- cgit v1.2.3 From 9e0e8f01c862a3eb4599452aa576620be8f01e94 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 23 Jan 2020 14:59:22 +0100 Subject: drm: Remove internal setup of struct drm_device.vblank_disable_immediate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VBLANK interrupts can be disabled immediately or with a delay, where the latter is the default. The former option can be selected by setting get_vblank_timestamp and enabling vblank_disable_immediate in struct drm_device. Simplify the code in preparation of the removal of struct drm_device.get_vblank_timestamp. v3: * remove internal setup of vblank_disable_immediate Signed-off-by: Thomas Zimmermann Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200123135943.24140-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_vblank.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/gpu/drm/drm_vblank.c') diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 27a99c486f02..d7f5d4023f50 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -486,19 +486,6 @@ int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs) DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); - /* Driver specific high-precision vblank timestamping supported? */ - if (dev->driver->get_vblank_timestamp) - DRM_INFO("Driver supports precise vblank timestamp query.\n"); - else - DRM_INFO("No driver support for vblank timestamp query.\n"); - - /* Must have precise timestamping for reliable vblank instant disable */ - if (dev->vblank_disable_immediate && !dev->driver->get_vblank_timestamp) { - dev->vblank_disable_immediate = false; - DRM_INFO("Setting vblank_disable_immediate to false because " - "get_vblank_timestamp == NULL\n"); - } - return 0; err: -- cgit v1.2.3 From f1e2b6371c12aec5e772e5fdedaa4455c20a787f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 23 Jan 2020 14:59:23 +0100 Subject: drm: Add get_scanout_position() to struct drm_crtc_helper_funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new callback get_scanout_position() reads the current location of the scanout process. The operation is currently located in struct drm_driver, but really belongs to the CRTC. Drivers will be converted in separate patches. To help with the conversion, the timestamp calculation has been moved from drm_calc_vbltimestamp_from_scanoutpos() to drm_crtc_vblank_helper_get_vblank_timestamp_internal(). The helper function supports the new and old interface of get_scanout_position(). drm_calc_vbltimestamp_from_scanoutpos() remains as a wrapper around the new function. Callback functions return the scanout position from the CRTC. The legacy version of the interface receives the device and pipe index, the modern version receives a pointer to the CRTC. We keep the legacy version until all drivers have been converted. v4: * 80-character line fixes v3: * refactor drm_calc_vbltimestamp_from_scanoutpos() to minimize code duplication * define types for get_scanout_position() callbacks v2: * fix logical op in drm_calc_vbltimestamp_from_scanoutpos() Signed-off-by: Thomas Zimmermann Tested-by: Yannick Fertré Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200123135943.24140-3-tzimmermann@suse.de --- drivers/gpu/drm/drm_vblank.c | 101 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/drm_vblank.c') diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index d7f5d4023f50..496395324d1f 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -605,7 +606,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * Implements calculation of exact vblank timestamps from given drm_display_mode * timings and current video scanout position of a CRTC. This can be directly * used as the &drm_driver.get_vblank_timestamp implementation of a kms driver - * if &drm_driver.get_scanout_position is implemented. + * if &drm_crtc_helper_funcs.get_scanout_position is implemented. * * The current implementation only handles standard video modes. For double scan * and interlaced modes the driver is supposed to adjust the hardware mode @@ -627,28 +628,85 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, ktime_t *vblank_time, bool in_vblank_irq) { - struct timespec64 ts_etime, ts_vblank_time; - ktime_t stime, etime; - bool vbl_status; struct drm_crtc *crtc; - const struct drm_display_mode *mode; - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; - int vpos, hpos, i; - int delta_ns, duration_ns; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return false; crtc = drm_crtc_from_index(dev, pipe); + if (!crtc) + return false; - if (pipe >= dev->num_crtcs || !crtc) { + return drm_crtc_vblank_helper_get_vblank_timestamp_internal(crtc, + max_error, + vblank_time, + in_vblank_irq, + crtc->helper_private->get_scanout_position, + dev->driver->get_scanout_position); +} +EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); + +/** + * drm_crtc_vblank_helper_get_vblank_timestamp_internal - precise vblank + * timestamp helper + * @dev: DRM device + * @pipe: index of CRTC whose vblank timestamp to retrieve + * @max_error: Desired maximum allowable error in timestamps (nanosecs) + * On return contains true maximum error of timestamp + * @vblank_time: Pointer to time which should receive the 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. + * @get_scanout_position: + * Callback function to retrieve the scanout position. See + * @struct drm_crtc_helper_funcs.get_scanout_position. + * @get_scanout_position_legacy: + * Callback function to retrieve the scanout position. See + * @struct drm_driver.get_scanout_position. + * + * Implements calculation of exact vblank timestamps from given drm_display_mode + * timings and current video scanout position of a CRTC. + * + * The current implementation only handles standard video modes. For double scan + * and interlaced modes the driver is supposed to adjust the hardware mode + * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to + * match the scanout position reported. + * + * Note that atomic drivers must call drm_calc_timestamping_constants() before + * enabling a CRTC. The atomic helpers already take care of that in + * drm_atomic_helper_update_legacy_modeset_state(). + * + * Returns: + * + * Returns true on success, and false on failure, i.e. when no accurate + * timestamp could be acquired. + */ +bool +drm_crtc_vblank_helper_get_vblank_timestamp_internal( + struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time, + bool in_vblank_irq, + drm_vblank_get_scanout_position_func get_scanout_position, + drm_vblank_get_scanout_position_legacy_func get_scanout_position_legacy) +{ + struct drm_device *dev = crtc->dev; + unsigned int pipe = crtc->index; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct timespec64 ts_etime, ts_vblank_time; + ktime_t stime, etime; + bool vbl_status; + const struct drm_display_mode *mode; + int vpos, hpos, i; + int delta_ns, duration_ns; + + if (pipe >= dev->num_crtcs) { DRM_ERROR("Invalid crtc %u\n", pipe); return false; } /* Scanout position query not supported? Should not happen. */ - if (!dev->driver->get_scanout_position) { - DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); + if (!get_scanout_position && !get_scanout_position_legacy) { + DRM_ERROR("Called from CRTC w/o get_scanout_position()!?\n"); return false; } @@ -663,7 +721,6 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, if (mode->crtc_clock == 0) { DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe); WARN_ON_ONCE(drm_drv_uses_atomic_modeset(dev)); - return false; } @@ -679,11 +736,19 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, * Get vertical and horizontal scanout position vpos, hpos, * and bounding timestamps stime, etime, pre/post query. */ - vbl_status = dev->driver->get_scanout_position(dev, pipe, - in_vblank_irq, - &vpos, &hpos, - &stime, &etime, - mode); + if (get_scanout_position) { + vbl_status = get_scanout_position(crtc, + in_vblank_irq, + &vpos, &hpos, + &stime, &etime, + mode); + } else { + vbl_status = get_scanout_position_legacy(dev, pipe, + in_vblank_irq, + &vpos, &hpos, + &stime, &etime, + mode); + } /* Return as no-op if scanout query unsupported or failed. */ if (!vbl_status) { @@ -735,7 +800,7 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, return true; } -EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); +EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_internal); /** * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent -- cgit v1.2.3 From 7fe3f0d15aac6c98a97e6d7086f5a6b7bc4ccae4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 23 Jan 2020 14:59:24 +0100 Subject: drm: Add get_vblank_timestamp() to struct drm_crtc_funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200123135943.24140-4-tzimmermann@suse.de --- drivers/gpu/drm/drm_vblank.c | 76 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/drm_vblank.c') diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 496395324d1f..cc7ef64d35f2 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -339,7 +339,9 @@ u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) u64 vblank; unsigned long flags; - WARN_ONCE(drm_debug_enabled(DRM_UT_VBL) && !dev->driver->get_vblank_timestamp, + WARN_ONCE(drm_debug_enabled(DRM_UT_VBL) && + !crtc->funcs->get_vblank_timestamp && + !dev->driver->get_vblank_timestamp, "This function requires support for accurate vblank timestamps."); spin_lock_irqsave(&dev->vblank_time_lock, flags); @@ -539,9 +541,9 @@ EXPORT_SYMBOL(drm_crtc_vblank_waitqueue); * * Calculate and store various constants which are later needed by vblank and * swap-completion timestamping, e.g, by - * drm_calc_vbltimestamp_from_scanoutpos(). They are derived from CRTC's true - * scanout timing, so they take things like panel scaling or other adjustments - * into account. + * drm_crtc_vblank_helper_get_vblank_timestamp(). They are derived from + * CRTC's true scanout timing, so they take things like panel scaling or + * other adjustments into account. */ void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) @@ -605,8 +607,9 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * * Implements calculation of exact vblank timestamps from given drm_display_mode * timings and current video scanout position of a CRTC. This can be directly - * used as the &drm_driver.get_vblank_timestamp implementation of a kms driver - * if &drm_crtc_helper_funcs.get_scanout_position is implemented. + * used as the &drm_crtc_funcs.get_vblank_timestamp implementation of a kms + * driver if &drm_crtc_helper_funcs.get_scanout_position or + * &drm_driver.get_scanout_position is implemented. * * The current implementation only handles standard video modes. For double scan * and interlaced modes the driver is supposed to adjust the hardware mode @@ -802,6 +805,48 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal( } EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_internal); +/** + * drm_crtc_vblank_helper_get_vblank_timestamp - precise vblank timestamp + * helper + * @crtc: CRTC whose vblank timestamp to retrieve + * @max_error: Desired maximum allowable error in timestamps (nanosecs) + * On return contains true maximum error of timestamp + * @vblank_time: Pointer to time which should receive the 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. + * + * Implements calculation of exact vblank timestamps from given drm_display_mode + * timings and current video scanout position of a CRTC. This can be directly + * used as the &drm_crtc_funcs.get_vblank_timestamp implementation of a kms + * driver if &drm_crtc_helper_funcs.get_scanout_position is implemented. + * + * The current implementation only handles standard video modes. For double scan + * and interlaced modes the driver is supposed to adjust the hardware mode + * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to + * match the scanout position reported. + * + * Note that atomic drivers must call drm_calc_timestamping_constants() before + * enabling a CRTC. The atomic helpers already take care of that in + * drm_atomic_helper_update_legacy_modeset_state(). + * + * Returns: + * + * Returns true on success, and false on failure, i.e. when no accurate + * timestamp could be acquired. + */ +bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, + int *max_error, + ktime_t *vblank_time, + bool in_vblank_irq) +{ + return drm_crtc_vblank_helper_get_vblank_timestamp_internal( + crtc, max_error, vblank_time, in_vblank_irq, + crtc->helper_private->get_scanout_position, NULL); +} +EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp); + /** * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent * vblank interval @@ -827,15 +872,22 @@ static bool drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, ktime_t *tvblank, bool in_vblank_irq) { + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); bool ret = false; /* Define requested maximum error on timestamps (nanoseconds). */ int max_error = (int) drm_timestamp_precision * 1000; /* Query driver if possible and precision timestamping enabled. */ - if (dev->driver->get_vblank_timestamp && (max_error > 0)) + if (crtc && crtc->funcs->get_vblank_timestamp && max_error > 0) { + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); + + ret = crtc->funcs->get_vblank_timestamp(crtc, &max_error, + tvblank, in_vblank_irq); + } else if (dev->driver->get_vblank_timestamp && max_error > 0) { ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error, tvblank, in_vblank_irq); + } /* GPU high precision timestamp query unsupported or failed. * Return current monotonic/gettimeofday timestamp as best estimate. @@ -1818,6 +1870,8 @@ done: static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) { + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); + bool high_prec = false; struct drm_pending_vblank_event *e, *t; ktime_t now; u64 seq; @@ -1840,8 +1894,12 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) send_vblank_event(dev, e, seq, now); } - trace_drm_vblank_event(pipe, seq, now, - dev->driver->get_vblank_timestamp != NULL); + if (crtc && crtc->funcs->get_vblank_timestamp) + high_prec = true; + else if (dev->driver->get_vblank_timestamp) + high_prec = true; + + trace_drm_vblank_event(pipe, seq, now, high_prec); } /** -- cgit v1.2.3 From f397d66b31ab4f1380d3f31e2770e160a3e5a73b Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 23 Jan 2020 14:59:42 +0100 Subject: drm: Clean-up VBLANK-related callbacks in struct drm_driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All non-legacy users of VBLANK functions in struct drm_driver have been converted to use the respective interfaces in struct drm_crtc_funcs. The remaining users of VBLANK callbacks in struct drm_driver are legacy drivers with userspace modesetting. All users of struct drm_driver.get_scanout_position() have been converted to the respective CRTC helper function. Remove the callback from struct drm_driver. There are no users left of get_vblank_timestamp(), so the callback is being removed. The other VBLANK callbacks are being moved to the legacy section at the end of struct drm_driver. Also removed is drm_calc_vbltimestamp_from_scanoutpos(). Callers of this function have been converted to use the CRTC instead. v4: * more readable code for setting high_prec (Ville, Jani) v2: * merge with removal of struct drm_driver.get_scanout_position() * remove drm_calc_vbltimestamp_from_scanoutpos() Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Tested-by: Yannick Fertré Link: https://patchwork.freedesktop.org/patch/msgid/20200123135943.24140-22-tzimmermann@suse.de --- drivers/gpu/drm/drm_vblank.c | 81 +++++--------------------------------------- 1 file changed, 9 insertions(+), 72 deletions(-) (limited to 'drivers/gpu/drm/drm_vblank.c') diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index cc7ef64d35f2..224785020f17 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -144,10 +144,9 @@ static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe) if (crtc->funcs->get_vblank_counter) return crtc->funcs->get_vblank_counter(crtc); - } - - if (dev->driver->get_vblank_counter) + } else if (dev->driver->get_vblank_counter) { return dev->driver->get_vblank_counter(dev, pipe); + } return drm_vblank_no_hw_counter(dev, pipe); } @@ -340,8 +339,7 @@ u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) unsigned long flags; WARN_ONCE(drm_debug_enabled(DRM_UT_VBL) && - !crtc->funcs->get_vblank_timestamp && - !dev->driver->get_vblank_timestamp, + !crtc->funcs->get_vblank_timestamp, "This function requires support for accurate vblank timestamps."); spin_lock_irqsave(&dev->vblank_time_lock, flags); @@ -363,13 +361,11 @@ static void __disable_vblank(struct drm_device *dev, unsigned int pipe) if (WARN_ON(!crtc)) return; - if (crtc->funcs->disable_vblank) { + if (crtc->funcs->disable_vblank) crtc->funcs->disable_vblank(crtc); - return; - } + } else { + dev->driver->disable_vblank(dev, pipe); } - - dev->driver->disable_vblank(dev, pipe); } /* @@ -593,62 +589,6 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_calc_timestamping_constants); -/** - * drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper - * @dev: DRM device - * @pipe: index of CRTC whose vblank timestamp to retrieve - * @max_error: Desired maximum allowable error in timestamps (nanosecs) - * On return contains true maximum error of timestamp - * @vblank_time: Pointer to time which should receive the 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. - * - * Implements calculation of exact vblank timestamps from given drm_display_mode - * timings and current video scanout position of a CRTC. This can be directly - * used as the &drm_crtc_funcs.get_vblank_timestamp implementation of a kms - * driver if &drm_crtc_helper_funcs.get_scanout_position or - * &drm_driver.get_scanout_position is implemented. - * - * The current implementation only handles standard video modes. For double scan - * and interlaced modes the driver is supposed to adjust the hardware mode - * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to - * match the scanout position reported. - * - * Note that atomic drivers must call drm_calc_timestamping_constants() before - * enabling a CRTC. The atomic helpers already take care of that in - * drm_atomic_helper_update_legacy_modeset_state(). - * - * Returns: - * - * Returns true on success, and false on failure, i.e. when no accurate - * timestamp could be acquired. - */ -bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, - unsigned int pipe, - int *max_error, - ktime_t *vblank_time, - bool in_vblank_irq) -{ - struct drm_crtc *crtc; - - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - return false; - - crtc = drm_crtc_from_index(dev, pipe); - if (!crtc) - return false; - - return drm_crtc_vblank_helper_get_vblank_timestamp_internal(crtc, - max_error, - vblank_time, - in_vblank_irq, - crtc->helper_private->get_scanout_position, - dev->driver->get_scanout_position); -} -EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); - /** * drm_crtc_vblank_helper_get_vblank_timestamp_internal - precise vblank * timestamp helper @@ -884,9 +824,6 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, ret = crtc->funcs->get_vblank_timestamp(crtc, &max_error, tvblank, in_vblank_irq); - } else if (dev->driver->get_vblank_timestamp && max_error > 0) { - ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error, - tvblank, in_vblank_irq); } /* GPU high precision timestamp query unsupported or failed. @@ -1109,9 +1046,11 @@ static int __enable_vblank(struct drm_device *dev, unsigned int pipe) if (crtc->funcs->enable_vblank) return crtc->funcs->enable_vblank(crtc); + } else if (dev->driver->enable_vblank) { + return dev->driver->enable_vblank(dev, pipe); } - return dev->driver->enable_vblank(dev, pipe); + return -EINVAL; } static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) @@ -1896,8 +1835,6 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) if (crtc && crtc->funcs->get_vblank_timestamp) high_prec = true; - else if (dev->driver->get_vblank_timestamp) - high_prec = true; trace_drm_vblank_event(pipe, seq, now, high_prec); } -- cgit v1.2.3 From 48e678076e58341a70369d2db67770272181aa41 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 23 Jan 2020 14:59:43 +0100 Subject: drm: Remove legacy version of get_scanout_position() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The legacy version of get_scanout_position() was only useful while drivers still used drm_driver.get_scanout_position(). With no such drivers left, the related typedef and code can be removed Signed-off-by: Thomas Zimmermann Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200123135943.24140-23-tzimmermann@suse.de --- drivers/gpu/drm/drm_vblank.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/drm_vblank.c') diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 224785020f17..47fc4339ec7f 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -604,9 +604,6 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * @get_scanout_position: * Callback function to retrieve the scanout position. See * @struct drm_crtc_helper_funcs.get_scanout_position. - * @get_scanout_position_legacy: - * Callback function to retrieve the scanout position. See - * @struct drm_driver.get_scanout_position. * * Implements calculation of exact vblank timestamps from given drm_display_mode * timings and current video scanout position of a CRTC. @@ -629,8 +626,7 @@ bool drm_crtc_vblank_helper_get_vblank_timestamp_internal( struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time, bool in_vblank_irq, - drm_vblank_get_scanout_position_func get_scanout_position, - drm_vblank_get_scanout_position_legacy_func get_scanout_position_legacy) + drm_vblank_get_scanout_position_func get_scanout_position) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; @@ -648,7 +644,7 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal( } /* Scanout position query not supported? Should not happen. */ - if (!get_scanout_position && !get_scanout_position_legacy) { + if (!get_scanout_position) { DRM_ERROR("Called from CRTC w/o get_scanout_position()!?\n"); return false; } @@ -679,19 +675,10 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal( * Get vertical and horizontal scanout position vpos, hpos, * and bounding timestamps stime, etime, pre/post query. */ - if (get_scanout_position) { - vbl_status = get_scanout_position(crtc, - in_vblank_irq, - &vpos, &hpos, - &stime, &etime, - mode); - } else { - vbl_status = get_scanout_position_legacy(dev, pipe, - in_vblank_irq, - &vpos, &hpos, - &stime, &etime, - mode); - } + vbl_status = get_scanout_position(crtc, in_vblank_irq, + &vpos, &hpos, + &stime, &etime, + mode); /* Return as no-op if scanout query unsupported or failed. */ if (!vbl_status) { @@ -783,7 +770,7 @@ bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, { return drm_crtc_vblank_helper_get_vblank_timestamp_internal( crtc, max_error, vblank_time, in_vblank_irq, - crtc->helper_private->get_scanout_position, NULL); + crtc->helper_private->get_scanout_position); } EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp); -- cgit v1.2.3 From 099d705dd161897e98c6d7b99b8ca740f3bc747a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 3 Mar 2020 08:31:35 +0100 Subject: drm/vblank: Fix documentation of VBLANK timestamp helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per-CRTC VBLANK information used to be addressed by device and pipe index. A call drm_crtc_vblank_helper_get_vblank_timestamp_internal() receives a pointer to the CRTC instead. Fix the documentation. Signed-off-by: Thomas Zimmermann Reported-by: Daniel Vetter Reviewed-by: Daniel Vetter Fixes: f1e2b6371c12 ("drm: Add get_scanout_position() to struct drm_crtc_helper_funcs") Cc: Thomas Zimmermann Cc: Ville Syrjälä Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Link: https://patchwork.freedesktop.org/patch/msgid/20200303073135.10605-1-tzimmermann@suse.de --- drivers/gpu/drm/drm_vblank.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/drm_vblank.c') diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 47fc4339ec7f..da7b0b0c1090 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -592,8 +592,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); /** * drm_crtc_vblank_helper_get_vblank_timestamp_internal - precise vblank * timestamp helper - * @dev: DRM device - * @pipe: index of CRTC whose vblank timestamp to retrieve + * @crtc: CRTC whose vblank timestamp to retrieve * @max_error: Desired maximum allowable error in timestamps (nanosecs) * On return contains true maximum error of timestamp * @vblank_time: Pointer to time which should receive the timestamp -- cgit v1.2.3