18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2016 Intel Corp. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next 128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 138c2ecf20Sopenharmony_ci * Software. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188c2ecf20Sopenharmony_ci * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 198c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 208c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 218c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#ifndef _DRM_VBLANK_H_ 258c2ecf20Sopenharmony_ci#define _DRM_VBLANK_H_ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include <linux/seqlock.h> 288c2ecf20Sopenharmony_ci#include <linux/idr.h> 298c2ecf20Sopenharmony_ci#include <linux/poll.h> 308c2ecf20Sopenharmony_ci#include <linux/kthread.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <drm/drm_file.h> 338c2ecf20Sopenharmony_ci#include <drm/drm_modes.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct drm_device; 368c2ecf20Sopenharmony_cistruct drm_crtc; 378c2ecf20Sopenharmony_cistruct drm_vblank_work; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/** 408c2ecf20Sopenharmony_ci * struct drm_pending_vblank_event - pending vblank event tracking 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_cistruct drm_pending_vblank_event { 438c2ecf20Sopenharmony_ci /** 448c2ecf20Sopenharmony_ci * @base: Base structure for tracking pending DRM events. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci struct drm_pending_event base; 478c2ecf20Sopenharmony_ci /** 488c2ecf20Sopenharmony_ci * @pipe: drm_crtc_index() of the &drm_crtc this event is for. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ci unsigned int pipe; 518c2ecf20Sopenharmony_ci /** 528c2ecf20Sopenharmony_ci * @sequence: frame event should be triggered at 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_ci u64 sequence; 558c2ecf20Sopenharmony_ci /** 568c2ecf20Sopenharmony_ci * @event: Actual event which will be sent to userspace. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_ci union { 598c2ecf20Sopenharmony_ci /** 608c2ecf20Sopenharmony_ci * @event.base: DRM event base class. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci struct drm_event base; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /** 658c2ecf20Sopenharmony_ci * @event.vbl: 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * Event payload for vblank events, requested through 688c2ecf20Sopenharmony_ci * either the MODE_PAGE_FLIP or MODE_ATOMIC IOCTL. Also 698c2ecf20Sopenharmony_ci * generated by the legacy WAIT_VBLANK IOCTL, but new userspace 708c2ecf20Sopenharmony_ci * should use MODE_QUEUE_SEQUENCE and &event.seq instead. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci struct drm_event_vblank vbl; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /** 758c2ecf20Sopenharmony_ci * @event.seq: Event payload for the MODE_QUEUEU_SEQUENCE IOCTL. 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci struct drm_event_crtc_sequence seq; 788c2ecf20Sopenharmony_ci } event; 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/** 828c2ecf20Sopenharmony_ci * struct drm_vblank_crtc - vblank tracking for a CRTC 838c2ecf20Sopenharmony_ci * 848c2ecf20Sopenharmony_ci * This structure tracks the vblank state for one CRTC. 858c2ecf20Sopenharmony_ci * 868c2ecf20Sopenharmony_ci * Note that for historical reasons - the vblank handling code is still shared 878c2ecf20Sopenharmony_ci * with legacy/non-kms drivers - this is a free-standing structure not directly 888c2ecf20Sopenharmony_ci * connected to &struct drm_crtc. But all public interface functions are taking 898c2ecf20Sopenharmony_ci * a &struct drm_crtc to hide this implementation detail. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_cistruct drm_vblank_crtc { 928c2ecf20Sopenharmony_ci /** 938c2ecf20Sopenharmony_ci * @dev: Pointer to the &drm_device. 948c2ecf20Sopenharmony_ci */ 958c2ecf20Sopenharmony_ci struct drm_device *dev; 968c2ecf20Sopenharmony_ci /** 978c2ecf20Sopenharmony_ci * @queue: Wait queue for vblank waiters. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci wait_queue_head_t queue; 1008c2ecf20Sopenharmony_ci /** 1018c2ecf20Sopenharmony_ci * @disable_timer: Disable timer for the delayed vblank disabling 1028c2ecf20Sopenharmony_ci * hysteresis logic. Vblank disabling is controlled through the 1038c2ecf20Sopenharmony_ci * drm_vblank_offdelay module option and the setting of the 1048c2ecf20Sopenharmony_ci * &drm_device.max_vblank_count value. 1058c2ecf20Sopenharmony_ci */ 1068c2ecf20Sopenharmony_ci struct timer_list disable_timer; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /** 1098c2ecf20Sopenharmony_ci * @seqlock: Protect vblank count and time. 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_ci seqlock_t seqlock; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /** 1148c2ecf20Sopenharmony_ci * @count: 1158c2ecf20Sopenharmony_ci * 1168c2ecf20Sopenharmony_ci * Current software vblank counter. 1178c2ecf20Sopenharmony_ci * 1188c2ecf20Sopenharmony_ci * Note that for a given vblank counter value drm_crtc_handle_vblank() 1198c2ecf20Sopenharmony_ci * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time() 1208c2ecf20Sopenharmony_ci * provide a barrier: Any writes done before calling 1218c2ecf20Sopenharmony_ci * drm_crtc_handle_vblank() will be visible to callers of the later 1228c2ecf20Sopenharmony_ci * functions, iff the vblank count is the same or a later one. 1238c2ecf20Sopenharmony_ci * 1248c2ecf20Sopenharmony_ci * IMPORTANT: This guarantee requires barriers, therefor never access 1258c2ecf20Sopenharmony_ci * this field directly. Use drm_crtc_vblank_count() instead. 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_ci atomic64_t count; 1288c2ecf20Sopenharmony_ci /** 1298c2ecf20Sopenharmony_ci * @time: Vblank timestamp corresponding to @count. 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_ci ktime_t time; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /** 1348c2ecf20Sopenharmony_ci * @refcount: Number of users/waiters of the vblank interrupt. Only when 1358c2ecf20Sopenharmony_ci * this refcount reaches 0 can the hardware interrupt be disabled using 1368c2ecf20Sopenharmony_ci * @disable_timer. 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_ci atomic_t refcount; 1398c2ecf20Sopenharmony_ci /** 1408c2ecf20Sopenharmony_ci * @last: Protected by &drm_device.vbl_lock, used for wraparound handling. 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_ci u32 last; 1438c2ecf20Sopenharmony_ci /** 1448c2ecf20Sopenharmony_ci * @max_vblank_count: 1458c2ecf20Sopenharmony_ci * 1468c2ecf20Sopenharmony_ci * Maximum value of the vblank registers for this crtc. This value +1 1478c2ecf20Sopenharmony_ci * will result in a wrap-around of the vblank register. It is used 1488c2ecf20Sopenharmony_ci * by the vblank core to handle wrap-arounds. 1498c2ecf20Sopenharmony_ci * 1508c2ecf20Sopenharmony_ci * If set to zero the vblank core will try to guess the elapsed vblanks 1518c2ecf20Sopenharmony_ci * between times when the vblank interrupt is disabled through 1528c2ecf20Sopenharmony_ci * high-precision timestamps. That approach is suffering from small 1538c2ecf20Sopenharmony_ci * races and imprecision over longer time periods, hence exposing a 1548c2ecf20Sopenharmony_ci * hardware vblank counter is always recommended. 1558c2ecf20Sopenharmony_ci * 1568c2ecf20Sopenharmony_ci * This is the runtime configurable per-crtc maximum set through 1578c2ecf20Sopenharmony_ci * drm_crtc_set_max_vblank_count(). If this is used the driver 1588c2ecf20Sopenharmony_ci * must leave the device wide &drm_device.max_vblank_count at zero. 1598c2ecf20Sopenharmony_ci * 1608c2ecf20Sopenharmony_ci * If non-zero, &drm_crtc_funcs.get_vblank_counter must be set. 1618c2ecf20Sopenharmony_ci */ 1628c2ecf20Sopenharmony_ci u32 max_vblank_count; 1638c2ecf20Sopenharmony_ci /** 1648c2ecf20Sopenharmony_ci * @inmodeset: Tracks whether the vblank is disabled due to a modeset. 1658c2ecf20Sopenharmony_ci * For legacy driver bit 2 additionally tracks whether an additional 1668c2ecf20Sopenharmony_ci * temporary vblank reference has been acquired to paper over the 1678c2ecf20Sopenharmony_ci * hardware counter resetting/jumping. KMS drivers should instead just 1688c2ecf20Sopenharmony_ci * call drm_crtc_vblank_off() and drm_crtc_vblank_on(), which explicitly 1698c2ecf20Sopenharmony_ci * save and restore the vblank count. 1708c2ecf20Sopenharmony_ci */ 1718c2ecf20Sopenharmony_ci unsigned int inmodeset; 1728c2ecf20Sopenharmony_ci /** 1738c2ecf20Sopenharmony_ci * @pipe: drm_crtc_index() of the &drm_crtc corresponding to this 1748c2ecf20Sopenharmony_ci * structure. 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_ci unsigned int pipe; 1778c2ecf20Sopenharmony_ci /** 1788c2ecf20Sopenharmony_ci * @framedur_ns: Frame/Field duration in ns, used by 1798c2ecf20Sopenharmony_ci * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by 1808c2ecf20Sopenharmony_ci * drm_calc_timestamping_constants(). 1818c2ecf20Sopenharmony_ci */ 1828c2ecf20Sopenharmony_ci int framedur_ns; 1838c2ecf20Sopenharmony_ci /** 1848c2ecf20Sopenharmony_ci * @linedur_ns: Line duration in ns, used by 1858c2ecf20Sopenharmony_ci * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by 1868c2ecf20Sopenharmony_ci * drm_calc_timestamping_constants(). 1878c2ecf20Sopenharmony_ci */ 1888c2ecf20Sopenharmony_ci int linedur_ns; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /** 1918c2ecf20Sopenharmony_ci * @hwmode: 1928c2ecf20Sopenharmony_ci * 1938c2ecf20Sopenharmony_ci * Cache of the current hardware display mode. Only valid when @enabled 1948c2ecf20Sopenharmony_ci * is set. This is used by helpers like 1958c2ecf20Sopenharmony_ci * drm_crtc_vblank_helper_get_vblank_timestamp(). We can't just access 1968c2ecf20Sopenharmony_ci * the hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode, 1978c2ecf20Sopenharmony_ci * because that one is really hard to get from interrupt context. 1988c2ecf20Sopenharmony_ci */ 1998c2ecf20Sopenharmony_ci struct drm_display_mode hwmode; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /** 2028c2ecf20Sopenharmony_ci * @enabled: Tracks the enabling state of the corresponding &drm_crtc to 2038c2ecf20Sopenharmony_ci * avoid double-disabling and hence corrupting saved state. Needed by 2048c2ecf20Sopenharmony_ci * drivers not using atomic KMS, since those might go through their CRTC 2058c2ecf20Sopenharmony_ci * disabling functions multiple times. 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_ci bool enabled; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /** 2108c2ecf20Sopenharmony_ci * @worker: The &kthread_worker used for executing vblank works. 2118c2ecf20Sopenharmony_ci */ 2128c2ecf20Sopenharmony_ci struct kthread_worker *worker; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /** 2158c2ecf20Sopenharmony_ci * @pending_work: A list of scheduled &drm_vblank_work items that are 2168c2ecf20Sopenharmony_ci * waiting for a future vblank. 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_ci struct list_head pending_work; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /** 2218c2ecf20Sopenharmony_ci * @work_wait_queue: The wait queue used for signaling that a 2228c2ecf20Sopenharmony_ci * &drm_vblank_work item has either finished executing, or was 2238c2ecf20Sopenharmony_ci * cancelled. 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_ci wait_queue_head_t work_wait_queue; 2268c2ecf20Sopenharmony_ci}; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ciint drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs); 2298c2ecf20Sopenharmony_cibool drm_dev_has_vblank(const struct drm_device *dev); 2308c2ecf20Sopenharmony_ciu64 drm_crtc_vblank_count(struct drm_crtc *crtc); 2318c2ecf20Sopenharmony_ciu64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, 2328c2ecf20Sopenharmony_ci ktime_t *vblanktime); 2338c2ecf20Sopenharmony_civoid drm_crtc_send_vblank_event(struct drm_crtc *crtc, 2348c2ecf20Sopenharmony_ci struct drm_pending_vblank_event *e); 2358c2ecf20Sopenharmony_civoid drm_crtc_arm_vblank_event(struct drm_crtc *crtc, 2368c2ecf20Sopenharmony_ci struct drm_pending_vblank_event *e); 2378c2ecf20Sopenharmony_civoid drm_vblank_set_event(struct drm_pending_vblank_event *e, 2388c2ecf20Sopenharmony_ci u64 *seq, 2398c2ecf20Sopenharmony_ci ktime_t *now); 2408c2ecf20Sopenharmony_cibool drm_handle_vblank(struct drm_device *dev, unsigned int pipe); 2418c2ecf20Sopenharmony_cibool drm_crtc_handle_vblank(struct drm_crtc *crtc); 2428c2ecf20Sopenharmony_ciint drm_crtc_vblank_get(struct drm_crtc *crtc); 2438c2ecf20Sopenharmony_civoid drm_crtc_vblank_put(struct drm_crtc *crtc); 2448c2ecf20Sopenharmony_civoid drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe); 2458c2ecf20Sopenharmony_civoid drm_crtc_wait_one_vblank(struct drm_crtc *crtc); 2468c2ecf20Sopenharmony_civoid drm_crtc_vblank_off(struct drm_crtc *crtc); 2478c2ecf20Sopenharmony_civoid drm_crtc_vblank_reset(struct drm_crtc *crtc); 2488c2ecf20Sopenharmony_civoid drm_crtc_vblank_on(struct drm_crtc *crtc); 2498c2ecf20Sopenharmony_ciu64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); 2508c2ecf20Sopenharmony_civoid drm_vblank_restore(struct drm_device *dev, unsigned int pipe); 2518c2ecf20Sopenharmony_civoid drm_crtc_vblank_restore(struct drm_crtc *crtc); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_civoid drm_calc_timestamping_constants(struct drm_crtc *crtc, 2548c2ecf20Sopenharmony_ci const struct drm_display_mode *mode); 2558c2ecf20Sopenharmony_ciwait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc); 2568c2ecf20Sopenharmony_civoid drm_crtc_set_max_vblank_count(struct drm_crtc *crtc, 2578c2ecf20Sopenharmony_ci u32 max_vblank_count); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci/* 2608c2ecf20Sopenharmony_ci * Helpers for struct drm_crtc_funcs 2618c2ecf20Sopenharmony_ci */ 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_citypedef bool (*drm_vblank_get_scanout_position_func)(struct drm_crtc *crtc, 2648c2ecf20Sopenharmony_ci bool in_vblank_irq, 2658c2ecf20Sopenharmony_ci int *vpos, int *hpos, 2668c2ecf20Sopenharmony_ci ktime_t *stime, 2678c2ecf20Sopenharmony_ci ktime_t *etime, 2688c2ecf20Sopenharmony_ci const struct drm_display_mode *mode); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cibool 2718c2ecf20Sopenharmony_cidrm_crtc_vblank_helper_get_vblank_timestamp_internal(struct drm_crtc *crtc, 2728c2ecf20Sopenharmony_ci int *max_error, 2738c2ecf20Sopenharmony_ci ktime_t *vblank_time, 2748c2ecf20Sopenharmony_ci bool in_vblank_irq, 2758c2ecf20Sopenharmony_ci drm_vblank_get_scanout_position_func get_scanout_position); 2768c2ecf20Sopenharmony_cibool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, 2778c2ecf20Sopenharmony_ci int *max_error, 2788c2ecf20Sopenharmony_ci ktime_t *vblank_time, 2798c2ecf20Sopenharmony_ci bool in_vblank_irq); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci#endif 282