diff options
Diffstat (limited to 'drivers/gpu/drm/drm_vblank_helper.c')
| -rw-r--r-- | drivers/gpu/drm/drm_vblank_helper.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_vblank_helper.c b/drivers/gpu/drm/drm_vblank_helper.c new file mode 100644 index 000000000000..a04a6ba1b0ca --- /dev/null +++ b/drivers/gpu/drm/drm_vblank_helper.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: MIT + +#include <drm/drm_atomic.h> +#include <drm/drm_crtc.h> +#include <drm/drm_managed.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_print.h> +#include <drm/drm_vblank.h> +#include <drm/drm_vblank_helper.h> + +/** + * DOC: overview + * + * The vblank helper library provides functions for supporting vertical + * blanking in DRM drivers. + * + * For vblank timers, several callback implementations are available. + * Drivers enable support for vblank timers by setting the vblank callbacks + * in struct &drm_crtc_funcs to the helpers provided by this library. The + * initializer macro DRM_CRTC_VBLANK_TIMER_FUNCS does this conveniently. + * The driver further has to send the VBLANK event from its atomic_flush + * callback and control vblank from the CRTC's atomic_enable and atomic_disable + * callbacks. The callbacks are located in struct &drm_crtc_helper_funcs. + * The vblank helper library provides implementations of these callbacks + * for drivers without further requirements. The initializer macro + * DRM_CRTC_HELPER_VBLANK_FUNCS sets them coveniently. + * + * Once the driver enables vblank support with drm_vblank_init(), each + * CRTC's vblank timer fires according to the programmed display mode. By + * default, the vblank timer invokes drm_crtc_handle_vblank(). Drivers with + * more specific requirements can set their own handler function in + * struct &drm_crtc_helper_funcs.handle_vblank_timeout. + */ + +/* + * VBLANK helpers + */ + +/** + * drm_crtc_vblank_atomic_flush - + * Implements struct &drm_crtc_helper_funcs.atomic_flush + * @crtc: The CRTC + * @state: The atomic state to apply + * + * The helper drm_crtc_vblank_atomic_flush() implements atomic_flush of + * struct drm_crtc_helper_funcs for CRTCs that only need to send out a + * VBLANK event. + * + * See also struct &drm_crtc_helper_funcs.atomic_flush. + */ +void drm_crtc_vblank_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + struct drm_pending_vblank_event *event; + + spin_lock_irq(&dev->event_lock); + + event = crtc_state->event; + crtc_state->event = NULL; + + if (event) { + if (drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + } + + spin_unlock_irq(&dev->event_lock); +} +EXPORT_SYMBOL(drm_crtc_vblank_atomic_flush); + +/** + * drm_crtc_vblank_atomic_enable - Implements struct &drm_crtc_helper_funcs.atomic_enable + * @crtc: The CRTC + * @state: The atomic state + * + * The helper drm_crtc_vblank_atomic_enable() implements atomic_enable + * of struct drm_crtc_helper_funcs for CRTCs the only need to enable VBLANKs. + * + * See also struct &drm_crtc_helper_funcs.atomic_enable. + */ +void drm_crtc_vblank_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + drm_crtc_vblank_on(crtc); +} +EXPORT_SYMBOL(drm_crtc_vblank_atomic_enable); + +/** + * drm_crtc_vblank_atomic_disable - Implements struct &drm_crtc_helper_funcs.atomic_disable + * @crtc: The CRTC + * @state: The atomic state + * + * The helper drm_crtc_vblank_atomic_disable() implements atomic_disable + * of struct drm_crtc_helper_funcs for CRTCs the only need to disable VBLANKs. + * + * See also struct &drm_crtc_funcs.atomic_disable. + */ +void drm_crtc_vblank_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + drm_crtc_vblank_off(crtc); +} +EXPORT_SYMBOL(drm_crtc_vblank_atomic_disable); + +/* + * VBLANK timer + */ + +/** + * drm_crtc_vblank_helper_enable_vblank_timer - Implements struct &drm_crtc_funcs.enable_vblank + * @crtc: The CRTC + * + * The helper drm_crtc_vblank_helper_enable_vblank_timer() implements + * enable_vblank of struct drm_crtc_helper_funcs for CRTCs that require + * a VBLANK timer. It sets up the timer on the first invocation. The + * started timer expires after the current frame duration. See struct + * &drm_vblank_crtc.framedur_ns. + * + * See also struct &drm_crtc_helper_funcs.enable_vblank. + * + * Returns: + * 0 on success, or a negative errno code otherwise. + */ +int drm_crtc_vblank_helper_enable_vblank_timer(struct drm_crtc *crtc) +{ + return drm_crtc_vblank_start_timer(crtc); +} +EXPORT_SYMBOL(drm_crtc_vblank_helper_enable_vblank_timer); + +/** + * drm_crtc_vblank_helper_disable_vblank_timer - Implements struct &drm_crtc_funcs.disable_vblank + * @crtc: The CRTC + * + * The helper drm_crtc_vblank_helper_disable_vblank_timer() implements + * disable_vblank of struct drm_crtc_funcs for CRTCs that require a + * VBLANK timer. + * + * See also struct &drm_crtc_helper_funcs.disable_vblank. + */ +void drm_crtc_vblank_helper_disable_vblank_timer(struct drm_crtc *crtc) +{ + drm_crtc_vblank_cancel_timer(crtc); +} +EXPORT_SYMBOL(drm_crtc_vblank_helper_disable_vblank_timer); + +/** + * drm_crtc_vblank_helper_get_vblank_timestamp_from_timer - + * Implements struct &drm_crtc_funcs.get_vblank_timestamp + * @crtc: The CRTC + * @max_error: Maximum acceptable error + * @vblank_time: Returns the next vblank timestamp + * @in_vblank_irq: True is called from drm_crtc_handle_vblank() + * + * The helper drm_crtc_helper_get_vblank_timestamp_from_timer() implements + * get_vblank_timestamp of struct drm_crtc_funcs for CRTCs that require a + * VBLANK timer. It returns the timestamp according to the timer's expiry + * time. + * + * See also struct &drm_crtc_funcs.get_vblank_timestamp. + * + * Returns: + * True on success, or false otherwise. + */ +bool drm_crtc_vblank_helper_get_vblank_timestamp_from_timer(struct drm_crtc *crtc, + int *max_error, + ktime_t *vblank_time, + bool in_vblank_irq) +{ + drm_crtc_vblank_get_vblank_timeout(crtc, vblank_time); + + return true; +} +EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_from_timer); |
