162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2016 Intel Corp. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the next 1262306a36Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 1362306a36Sopenharmony_ci * Software. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1862306a36Sopenharmony_ci * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 1962306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2062306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2162306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#ifndef _DRM_VBLANK_H_ 2562306a36Sopenharmony_ci#define _DRM_VBLANK_H_ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#include <linux/seqlock.h> 2862306a36Sopenharmony_ci#include <linux/idr.h> 2962306a36Sopenharmony_ci#include <linux/poll.h> 3062306a36Sopenharmony_ci#include <linux/kthread.h> 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include <drm/drm_file.h> 3362306a36Sopenharmony_ci#include <drm/drm_modes.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistruct drm_device; 3662306a36Sopenharmony_cistruct drm_crtc; 3762306a36Sopenharmony_cistruct drm_vblank_work; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/** 4062306a36Sopenharmony_ci * struct drm_pending_vblank_event - pending vblank event tracking 4162306a36Sopenharmony_ci */ 4262306a36Sopenharmony_cistruct drm_pending_vblank_event { 4362306a36Sopenharmony_ci /** 4462306a36Sopenharmony_ci * @base: Base structure for tracking pending DRM events. 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ci struct drm_pending_event base; 4762306a36Sopenharmony_ci /** 4862306a36Sopenharmony_ci * @pipe: drm_crtc_index() of the &drm_crtc this event is for. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci unsigned int pipe; 5162306a36Sopenharmony_ci /** 5262306a36Sopenharmony_ci * @sequence: frame event should be triggered at 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_ci u64 sequence; 5562306a36Sopenharmony_ci /** 5662306a36Sopenharmony_ci * @event: Actual event which will be sent to userspace. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci union { 5962306a36Sopenharmony_ci /** 6062306a36Sopenharmony_ci * @event.base: DRM event base class. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci struct drm_event base; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /** 6562306a36Sopenharmony_ci * @event.vbl: 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * Event payload for vblank events, requested through 6862306a36Sopenharmony_ci * either the MODE_PAGE_FLIP or MODE_ATOMIC IOCTL. Also 6962306a36Sopenharmony_ci * generated by the legacy WAIT_VBLANK IOCTL, but new userspace 7062306a36Sopenharmony_ci * should use MODE_QUEUE_SEQUENCE and &event.seq instead. 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_ci struct drm_event_vblank vbl; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /** 7562306a36Sopenharmony_ci * @event.seq: Event payload for the MODE_QUEUEU_SEQUENCE IOCTL. 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_ci struct drm_event_crtc_sequence seq; 7862306a36Sopenharmony_ci } event; 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/** 8262306a36Sopenharmony_ci * struct drm_vblank_crtc - vblank tracking for a CRTC 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * This structure tracks the vblank state for one CRTC. 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * Note that for historical reasons - the vblank handling code is still shared 8762306a36Sopenharmony_ci * with legacy/non-kms drivers - this is a free-standing structure not directly 8862306a36Sopenharmony_ci * connected to &struct drm_crtc. But all public interface functions are taking 8962306a36Sopenharmony_ci * a &struct drm_crtc to hide this implementation detail. 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_cistruct drm_vblank_crtc { 9262306a36Sopenharmony_ci /** 9362306a36Sopenharmony_ci * @dev: Pointer to the &drm_device. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_ci struct drm_device *dev; 9662306a36Sopenharmony_ci /** 9762306a36Sopenharmony_ci * @queue: Wait queue for vblank waiters. 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_ci wait_queue_head_t queue; 10062306a36Sopenharmony_ci /** 10162306a36Sopenharmony_ci * @disable_timer: Disable timer for the delayed vblank disabling 10262306a36Sopenharmony_ci * hysteresis logic. Vblank disabling is controlled through the 10362306a36Sopenharmony_ci * drm_vblank_offdelay module option and the setting of the 10462306a36Sopenharmony_ci * &drm_device.max_vblank_count value. 10562306a36Sopenharmony_ci */ 10662306a36Sopenharmony_ci struct timer_list disable_timer; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /** 10962306a36Sopenharmony_ci * @seqlock: Protect vblank count and time. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_ci seqlock_t seqlock; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /** 11462306a36Sopenharmony_ci * @count: 11562306a36Sopenharmony_ci * 11662306a36Sopenharmony_ci * Current software vblank counter. 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * Note that for a given vblank counter value drm_crtc_handle_vblank() 11962306a36Sopenharmony_ci * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time() 12062306a36Sopenharmony_ci * provide a barrier: Any writes done before calling 12162306a36Sopenharmony_ci * drm_crtc_handle_vblank() will be visible to callers of the later 12262306a36Sopenharmony_ci * functions, iff the vblank count is the same or a later one. 12362306a36Sopenharmony_ci * 12462306a36Sopenharmony_ci * IMPORTANT: This guarantee requires barriers, therefor never access 12562306a36Sopenharmony_ci * this field directly. Use drm_crtc_vblank_count() instead. 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_ci atomic64_t count; 12862306a36Sopenharmony_ci /** 12962306a36Sopenharmony_ci * @time: Vblank timestamp corresponding to @count. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_ci ktime_t time; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /** 13462306a36Sopenharmony_ci * @refcount: Number of users/waiters of the vblank interrupt. Only when 13562306a36Sopenharmony_ci * this refcount reaches 0 can the hardware interrupt be disabled using 13662306a36Sopenharmony_ci * @disable_timer. 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_ci atomic_t refcount; 13962306a36Sopenharmony_ci /** 14062306a36Sopenharmony_ci * @last: Protected by &drm_device.vbl_lock, used for wraparound handling. 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci u32 last; 14362306a36Sopenharmony_ci /** 14462306a36Sopenharmony_ci * @max_vblank_count: 14562306a36Sopenharmony_ci * 14662306a36Sopenharmony_ci * Maximum value of the vblank registers for this crtc. This value +1 14762306a36Sopenharmony_ci * will result in a wrap-around of the vblank register. It is used 14862306a36Sopenharmony_ci * by the vblank core to handle wrap-arounds. 14962306a36Sopenharmony_ci * 15062306a36Sopenharmony_ci * If set to zero the vblank core will try to guess the elapsed vblanks 15162306a36Sopenharmony_ci * between times when the vblank interrupt is disabled through 15262306a36Sopenharmony_ci * high-precision timestamps. That approach is suffering from small 15362306a36Sopenharmony_ci * races and imprecision over longer time periods, hence exposing a 15462306a36Sopenharmony_ci * hardware vblank counter is always recommended. 15562306a36Sopenharmony_ci * 15662306a36Sopenharmony_ci * This is the runtime configurable per-crtc maximum set through 15762306a36Sopenharmony_ci * drm_crtc_set_max_vblank_count(). If this is used the driver 15862306a36Sopenharmony_ci * must leave the device wide &drm_device.max_vblank_count at zero. 15962306a36Sopenharmony_ci * 16062306a36Sopenharmony_ci * If non-zero, &drm_crtc_funcs.get_vblank_counter must be set. 16162306a36Sopenharmony_ci */ 16262306a36Sopenharmony_ci u32 max_vblank_count; 16362306a36Sopenharmony_ci /** 16462306a36Sopenharmony_ci * @inmodeset: Tracks whether the vblank is disabled due to a modeset. 16562306a36Sopenharmony_ci * For legacy driver bit 2 additionally tracks whether an additional 16662306a36Sopenharmony_ci * temporary vblank reference has been acquired to paper over the 16762306a36Sopenharmony_ci * hardware counter resetting/jumping. KMS drivers should instead just 16862306a36Sopenharmony_ci * call drm_crtc_vblank_off() and drm_crtc_vblank_on(), which explicitly 16962306a36Sopenharmony_ci * save and restore the vblank count. 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_ci unsigned int inmodeset; 17262306a36Sopenharmony_ci /** 17362306a36Sopenharmony_ci * @pipe: drm_crtc_index() of the &drm_crtc corresponding to this 17462306a36Sopenharmony_ci * structure. 17562306a36Sopenharmony_ci */ 17662306a36Sopenharmony_ci unsigned int pipe; 17762306a36Sopenharmony_ci /** 17862306a36Sopenharmony_ci * @framedur_ns: Frame/Field duration in ns, used by 17962306a36Sopenharmony_ci * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by 18062306a36Sopenharmony_ci * drm_calc_timestamping_constants(). 18162306a36Sopenharmony_ci */ 18262306a36Sopenharmony_ci int framedur_ns; 18362306a36Sopenharmony_ci /** 18462306a36Sopenharmony_ci * @linedur_ns: Line duration in ns, used by 18562306a36Sopenharmony_ci * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by 18662306a36Sopenharmony_ci * drm_calc_timestamping_constants(). 18762306a36Sopenharmony_ci */ 18862306a36Sopenharmony_ci int linedur_ns; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /** 19162306a36Sopenharmony_ci * @hwmode: 19262306a36Sopenharmony_ci * 19362306a36Sopenharmony_ci * Cache of the current hardware display mode. Only valid when @enabled 19462306a36Sopenharmony_ci * is set. This is used by helpers like 19562306a36Sopenharmony_ci * drm_crtc_vblank_helper_get_vblank_timestamp(). We can't just access 19662306a36Sopenharmony_ci * the hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode, 19762306a36Sopenharmony_ci * because that one is really hard to get from interrupt context. 19862306a36Sopenharmony_ci */ 19962306a36Sopenharmony_ci struct drm_display_mode hwmode; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /** 20262306a36Sopenharmony_ci * @enabled: Tracks the enabling state of the corresponding &drm_crtc to 20362306a36Sopenharmony_ci * avoid double-disabling and hence corrupting saved state. Needed by 20462306a36Sopenharmony_ci * drivers not using atomic KMS, since those might go through their CRTC 20562306a36Sopenharmony_ci * disabling functions multiple times. 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ci bool enabled; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci /** 21062306a36Sopenharmony_ci * @worker: The &kthread_worker used for executing vblank works. 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_ci struct kthread_worker *worker; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci /** 21562306a36Sopenharmony_ci * @pending_work: A list of scheduled &drm_vblank_work items that are 21662306a36Sopenharmony_ci * waiting for a future vblank. 21762306a36Sopenharmony_ci */ 21862306a36Sopenharmony_ci struct list_head pending_work; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /** 22162306a36Sopenharmony_ci * @work_wait_queue: The wait queue used for signaling that a 22262306a36Sopenharmony_ci * &drm_vblank_work item has either finished executing, or was 22362306a36Sopenharmony_ci * cancelled. 22462306a36Sopenharmony_ci */ 22562306a36Sopenharmony_ci wait_queue_head_t work_wait_queue; 22662306a36Sopenharmony_ci}; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ciint drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs); 22962306a36Sopenharmony_cibool drm_dev_has_vblank(const struct drm_device *dev); 23062306a36Sopenharmony_ciu64 drm_crtc_vblank_count(struct drm_crtc *crtc); 23162306a36Sopenharmony_ciu64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, 23262306a36Sopenharmony_ci ktime_t *vblanktime); 23362306a36Sopenharmony_ciint drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime); 23462306a36Sopenharmony_civoid drm_crtc_send_vblank_event(struct drm_crtc *crtc, 23562306a36Sopenharmony_ci struct drm_pending_vblank_event *e); 23662306a36Sopenharmony_civoid drm_crtc_arm_vblank_event(struct drm_crtc *crtc, 23762306a36Sopenharmony_ci struct drm_pending_vblank_event *e); 23862306a36Sopenharmony_civoid drm_vblank_set_event(struct drm_pending_vblank_event *e, 23962306a36Sopenharmony_ci u64 *seq, 24062306a36Sopenharmony_ci ktime_t *now); 24162306a36Sopenharmony_cibool drm_handle_vblank(struct drm_device *dev, unsigned int pipe); 24262306a36Sopenharmony_cibool drm_crtc_handle_vblank(struct drm_crtc *crtc); 24362306a36Sopenharmony_ciint drm_crtc_vblank_get(struct drm_crtc *crtc); 24462306a36Sopenharmony_civoid drm_crtc_vblank_put(struct drm_crtc *crtc); 24562306a36Sopenharmony_civoid drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe); 24662306a36Sopenharmony_civoid drm_crtc_wait_one_vblank(struct drm_crtc *crtc); 24762306a36Sopenharmony_civoid drm_crtc_vblank_off(struct drm_crtc *crtc); 24862306a36Sopenharmony_civoid drm_crtc_vblank_reset(struct drm_crtc *crtc); 24962306a36Sopenharmony_civoid drm_crtc_vblank_on(struct drm_crtc *crtc); 25062306a36Sopenharmony_ciu64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); 25162306a36Sopenharmony_civoid drm_crtc_vblank_restore(struct drm_crtc *crtc); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_civoid drm_calc_timestamping_constants(struct drm_crtc *crtc, 25462306a36Sopenharmony_ci const struct drm_display_mode *mode); 25562306a36Sopenharmony_ciwait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc); 25662306a36Sopenharmony_civoid drm_crtc_set_max_vblank_count(struct drm_crtc *crtc, 25762306a36Sopenharmony_ci u32 max_vblank_count); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci/* 26062306a36Sopenharmony_ci * Helpers for struct drm_crtc_funcs 26162306a36Sopenharmony_ci */ 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_citypedef bool (*drm_vblank_get_scanout_position_func)(struct drm_crtc *crtc, 26462306a36Sopenharmony_ci bool in_vblank_irq, 26562306a36Sopenharmony_ci int *vpos, int *hpos, 26662306a36Sopenharmony_ci ktime_t *stime, 26762306a36Sopenharmony_ci ktime_t *etime, 26862306a36Sopenharmony_ci const struct drm_display_mode *mode); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cibool 27162306a36Sopenharmony_cidrm_crtc_vblank_helper_get_vblank_timestamp_internal(struct drm_crtc *crtc, 27262306a36Sopenharmony_ci int *max_error, 27362306a36Sopenharmony_ci ktime_t *vblank_time, 27462306a36Sopenharmony_ci bool in_vblank_irq, 27562306a36Sopenharmony_ci drm_vblank_get_scanout_position_func get_scanout_position); 27662306a36Sopenharmony_cibool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, 27762306a36Sopenharmony_ci int *max_error, 27862306a36Sopenharmony_ci ktime_t *vblank_time, 27962306a36Sopenharmony_ci bool in_vblank_irq); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci#endif 282