174afeb81SThomas Zimmermann // SPDX-License-Identifier: MIT 274afeb81SThomas Zimmermann 3*d54dbb59SThomas Zimmermann #include <drm/drm_atomic.h> 474afeb81SThomas Zimmermann #include <drm/drm_crtc.h> 574afeb81SThomas Zimmermann #include <drm/drm_managed.h> 674afeb81SThomas Zimmermann #include <drm/drm_modeset_helper_vtables.h> 774afeb81SThomas Zimmermann #include <drm/drm_print.h> 874afeb81SThomas Zimmermann #include <drm/drm_vblank.h> 974afeb81SThomas Zimmermann #include <drm/drm_vblank_helper.h> 1074afeb81SThomas Zimmermann 1174afeb81SThomas Zimmermann /** 1274afeb81SThomas Zimmermann * DOC: overview 1374afeb81SThomas Zimmermann * 1474afeb81SThomas Zimmermann * The vblank helper library provides functions for supporting vertical 1574afeb81SThomas Zimmermann * blanking in DRM drivers. 1674afeb81SThomas Zimmermann * 1774afeb81SThomas Zimmermann * For vblank timers, several callback implementations are available. 1874afeb81SThomas Zimmermann * Drivers enable support for vblank timers by setting the vblank callbacks 1974afeb81SThomas Zimmermann * in struct &drm_crtc_funcs to the helpers provided by this library. The 2074afeb81SThomas Zimmermann * initializer macro DRM_CRTC_VBLANK_TIMER_FUNCS does this conveniently. 21*d54dbb59SThomas Zimmermann * The driver further has to send the VBLANK event from its atomic_flush 22*d54dbb59SThomas Zimmermann * callback and control vblank from the CRTC's atomic_enable and atomic_disable 23*d54dbb59SThomas Zimmermann * callbacks. The callbacks are located in struct &drm_crtc_helper_funcs. 24*d54dbb59SThomas Zimmermann * The vblank helper library provides implementations of these callbacks 25*d54dbb59SThomas Zimmermann * for drivers without further requirements. The initializer macro 26*d54dbb59SThomas Zimmermann * DRM_CRTC_HELPER_VBLANK_FUNCS sets them coveniently. 2774afeb81SThomas Zimmermann * 2874afeb81SThomas Zimmermann * Once the driver enables vblank support with drm_vblank_init(), each 2974afeb81SThomas Zimmermann * CRTC's vblank timer fires according to the programmed display mode. By 3074afeb81SThomas Zimmermann * default, the vblank timer invokes drm_crtc_handle_vblank(). Drivers with 3174afeb81SThomas Zimmermann * more specific requirements can set their own handler function in 3274afeb81SThomas Zimmermann * struct &drm_crtc_helper_funcs.handle_vblank_timeout. 3374afeb81SThomas Zimmermann */ 3474afeb81SThomas Zimmermann 3574afeb81SThomas Zimmermann /* 36*d54dbb59SThomas Zimmermann * VBLANK helpers 37*d54dbb59SThomas Zimmermann */ 38*d54dbb59SThomas Zimmermann 39*d54dbb59SThomas Zimmermann /** 40*d54dbb59SThomas Zimmermann * drm_crtc_vblank_atomic_flush - 41*d54dbb59SThomas Zimmermann * Implements struct &drm_crtc_helper_funcs.atomic_flush 42*d54dbb59SThomas Zimmermann * @crtc: The CRTC 43*d54dbb59SThomas Zimmermann * @state: The atomic state to apply 44*d54dbb59SThomas Zimmermann * 45*d54dbb59SThomas Zimmermann * The helper drm_crtc_vblank_atomic_flush() implements atomic_flush of 46*d54dbb59SThomas Zimmermann * struct drm_crtc_helper_funcs for CRTCs that only need to send out a 47*d54dbb59SThomas Zimmermann * VBLANK event. 48*d54dbb59SThomas Zimmermann * 49*d54dbb59SThomas Zimmermann * See also struct &drm_crtc_helper_funcs.atomic_flush. 50*d54dbb59SThomas Zimmermann */ 51*d54dbb59SThomas Zimmermann void drm_crtc_vblank_atomic_flush(struct drm_crtc *crtc, 52*d54dbb59SThomas Zimmermann struct drm_atomic_state *state) 53*d54dbb59SThomas Zimmermann { 54*d54dbb59SThomas Zimmermann struct drm_device *dev = crtc->dev; 55*d54dbb59SThomas Zimmermann struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 56*d54dbb59SThomas Zimmermann struct drm_pending_vblank_event *event; 57*d54dbb59SThomas Zimmermann 58*d54dbb59SThomas Zimmermann spin_lock_irq(&dev->event_lock); 59*d54dbb59SThomas Zimmermann 60*d54dbb59SThomas Zimmermann event = crtc_state->event; 61*d54dbb59SThomas Zimmermann crtc_state->event = NULL; 62*d54dbb59SThomas Zimmermann 63*d54dbb59SThomas Zimmermann if (event) { 64*d54dbb59SThomas Zimmermann if (drm_crtc_vblank_get(crtc) == 0) 65*d54dbb59SThomas Zimmermann drm_crtc_arm_vblank_event(crtc, event); 66*d54dbb59SThomas Zimmermann else 67*d54dbb59SThomas Zimmermann drm_crtc_send_vblank_event(crtc, event); 68*d54dbb59SThomas Zimmermann } 69*d54dbb59SThomas Zimmermann 70*d54dbb59SThomas Zimmermann spin_unlock_irq(&dev->event_lock); 71*d54dbb59SThomas Zimmermann } 72*d54dbb59SThomas Zimmermann EXPORT_SYMBOL(drm_crtc_vblank_atomic_flush); 73*d54dbb59SThomas Zimmermann 74*d54dbb59SThomas Zimmermann /** 75*d54dbb59SThomas Zimmermann * drm_crtc_vblank_atomic_enable - Implements struct &drm_crtc_helper_funcs.atomic_enable 76*d54dbb59SThomas Zimmermann * @crtc: The CRTC 77*d54dbb59SThomas Zimmermann * @state: The atomic state 78*d54dbb59SThomas Zimmermann * 79*d54dbb59SThomas Zimmermann * The helper drm_crtc_vblank_atomic_enable() implements atomic_enable 80*d54dbb59SThomas Zimmermann * of struct drm_crtc_helper_funcs for CRTCs the only need to enable VBLANKs. 81*d54dbb59SThomas Zimmermann * 82*d54dbb59SThomas Zimmermann * See also struct &drm_crtc_helper_funcs.atomic_enable. 83*d54dbb59SThomas Zimmermann */ 84*d54dbb59SThomas Zimmermann void drm_crtc_vblank_atomic_enable(struct drm_crtc *crtc, 85*d54dbb59SThomas Zimmermann struct drm_atomic_state *state) 86*d54dbb59SThomas Zimmermann { 87*d54dbb59SThomas Zimmermann drm_crtc_vblank_on(crtc); 88*d54dbb59SThomas Zimmermann } 89*d54dbb59SThomas Zimmermann EXPORT_SYMBOL(drm_crtc_vblank_atomic_enable); 90*d54dbb59SThomas Zimmermann 91*d54dbb59SThomas Zimmermann /** 92*d54dbb59SThomas Zimmermann * drm_crtc_vblank_atomic_disable - Implements struct &drm_crtc_helper_funcs.atomic_disable 93*d54dbb59SThomas Zimmermann * @crtc: The CRTC 94*d54dbb59SThomas Zimmermann * @state: The atomic state 95*d54dbb59SThomas Zimmermann * 96*d54dbb59SThomas Zimmermann * The helper drm_crtc_vblank_atomic_disable() implements atomic_disable 97*d54dbb59SThomas Zimmermann * of struct drm_crtc_helper_funcs for CRTCs the only need to disable VBLANKs. 98*d54dbb59SThomas Zimmermann * 99*d54dbb59SThomas Zimmermann * See also struct &drm_crtc_funcs.atomic_disable. 100*d54dbb59SThomas Zimmermann */ 101*d54dbb59SThomas Zimmermann void drm_crtc_vblank_atomic_disable(struct drm_crtc *crtc, 102*d54dbb59SThomas Zimmermann struct drm_atomic_state *state) 103*d54dbb59SThomas Zimmermann { 104*d54dbb59SThomas Zimmermann drm_crtc_vblank_off(crtc); 105*d54dbb59SThomas Zimmermann } 106*d54dbb59SThomas Zimmermann EXPORT_SYMBOL(drm_crtc_vblank_atomic_disable); 107*d54dbb59SThomas Zimmermann 108*d54dbb59SThomas Zimmermann /* 10974afeb81SThomas Zimmermann * VBLANK timer 11074afeb81SThomas Zimmermann */ 11174afeb81SThomas Zimmermann 11274afeb81SThomas Zimmermann /** 11374afeb81SThomas Zimmermann * drm_crtc_vblank_helper_enable_vblank_timer - Implements struct &drm_crtc_funcs.enable_vblank 11474afeb81SThomas Zimmermann * @crtc: The CRTC 11574afeb81SThomas Zimmermann * 11674afeb81SThomas Zimmermann * The helper drm_crtc_vblank_helper_enable_vblank_timer() implements 11774afeb81SThomas Zimmermann * enable_vblank of struct drm_crtc_helper_funcs for CRTCs that require 11874afeb81SThomas Zimmermann * a VBLANK timer. It sets up the timer on the first invocation. The 11974afeb81SThomas Zimmermann * started timer expires after the current frame duration. See struct 12074afeb81SThomas Zimmermann * &drm_vblank_crtc.framedur_ns. 12174afeb81SThomas Zimmermann * 12274afeb81SThomas Zimmermann * See also struct &drm_crtc_helper_funcs.enable_vblank. 12374afeb81SThomas Zimmermann * 12474afeb81SThomas Zimmermann * Returns: 12574afeb81SThomas Zimmermann * 0 on success, or a negative errno code otherwise. 12674afeb81SThomas Zimmermann */ 12774afeb81SThomas Zimmermann int drm_crtc_vblank_helper_enable_vblank_timer(struct drm_crtc *crtc) 12874afeb81SThomas Zimmermann { 12974afeb81SThomas Zimmermann return drm_crtc_vblank_start_timer(crtc); 13074afeb81SThomas Zimmermann } 13174afeb81SThomas Zimmermann EXPORT_SYMBOL(drm_crtc_vblank_helper_enable_vblank_timer); 13274afeb81SThomas Zimmermann 13374afeb81SThomas Zimmermann /** 13474afeb81SThomas Zimmermann * drm_crtc_vblank_helper_disable_vblank_timer - Implements struct &drm_crtc_funcs.disable_vblank 13574afeb81SThomas Zimmermann * @crtc: The CRTC 13674afeb81SThomas Zimmermann * 13774afeb81SThomas Zimmermann * The helper drm_crtc_vblank_helper_disable_vblank_timer() implements 13874afeb81SThomas Zimmermann * disable_vblank of struct drm_crtc_funcs for CRTCs that require a 13974afeb81SThomas Zimmermann * VBLANK timer. 14074afeb81SThomas Zimmermann * 14174afeb81SThomas Zimmermann * See also struct &drm_crtc_helper_funcs.disable_vblank. 14274afeb81SThomas Zimmermann */ 14374afeb81SThomas Zimmermann void drm_crtc_vblank_helper_disable_vblank_timer(struct drm_crtc *crtc) 14474afeb81SThomas Zimmermann { 14574afeb81SThomas Zimmermann drm_crtc_vblank_cancel_timer(crtc); 14674afeb81SThomas Zimmermann } 14774afeb81SThomas Zimmermann EXPORT_SYMBOL(drm_crtc_vblank_helper_disable_vblank_timer); 14874afeb81SThomas Zimmermann 14974afeb81SThomas Zimmermann /** 15074afeb81SThomas Zimmermann * drm_crtc_vblank_helper_get_vblank_timestamp_from_timer - 15174afeb81SThomas Zimmermann * Implements struct &drm_crtc_funcs.get_vblank_timestamp 15274afeb81SThomas Zimmermann * @crtc: The CRTC 15374afeb81SThomas Zimmermann * @max_error: Maximum acceptable error 15474afeb81SThomas Zimmermann * @vblank_time: Returns the next vblank timestamp 15574afeb81SThomas Zimmermann * @in_vblank_irq: True is called from drm_crtc_handle_vblank() 15674afeb81SThomas Zimmermann * 15774afeb81SThomas Zimmermann * The helper drm_crtc_helper_get_vblank_timestamp_from_timer() implements 15874afeb81SThomas Zimmermann * get_vblank_timestamp of struct drm_crtc_funcs for CRTCs that require a 15974afeb81SThomas Zimmermann * VBLANK timer. It returns the timestamp according to the timer's expiry 16074afeb81SThomas Zimmermann * time. 16174afeb81SThomas Zimmermann * 16274afeb81SThomas Zimmermann * See also struct &drm_crtc_funcs.get_vblank_timestamp. 16374afeb81SThomas Zimmermann * 16474afeb81SThomas Zimmermann * Returns: 16574afeb81SThomas Zimmermann * True on success, or false otherwise. 16674afeb81SThomas Zimmermann */ 16774afeb81SThomas Zimmermann bool drm_crtc_vblank_helper_get_vblank_timestamp_from_timer(struct drm_crtc *crtc, 16874afeb81SThomas Zimmermann int *max_error, 16974afeb81SThomas Zimmermann ktime_t *vblank_time, 17074afeb81SThomas Zimmermann bool in_vblank_irq) 17174afeb81SThomas Zimmermann { 17274afeb81SThomas Zimmermann drm_crtc_vblank_get_vblank_timeout(crtc, vblank_time); 17374afeb81SThomas Zimmermann 17474afeb81SThomas Zimmermann return true; 17574afeb81SThomas Zimmermann } 17674afeb81SThomas Zimmermann EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_from_timer); 177