2017-05-31 17:21:46 +08:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Intel Corp.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _DRM_VBLANK_H_
|
|
|
|
#define _DRM_VBLANK_H_
|
|
|
|
|
|
|
|
#include <linux/seqlock.h>
|
|
|
|
#include <linux/idr.h>
|
|
|
|
#include <linux/poll.h>
|
|
|
|
|
|
|
|
#include <drm/drm_file.h>
|
|
|
|
#include <drm/drm_modes.h>
|
|
|
|
|
|
|
|
struct drm_device;
|
|
|
|
struct drm_crtc;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct drm_pending_vblank_event - pending vblank event tracking
|
|
|
|
*/
|
|
|
|
struct drm_pending_vblank_event {
|
|
|
|
/**
|
|
|
|
* @base: Base structure for tracking pending DRM events.
|
|
|
|
*/
|
|
|
|
struct drm_pending_event base;
|
|
|
|
/**
|
|
|
|
* @pipe: drm_crtc_index() of the &drm_crtc this event is for.
|
|
|
|
*/
|
|
|
|
unsigned int pipe;
|
2017-10-13 02:57:49 +08:00
|
|
|
/**
|
|
|
|
* @sequence: frame event should be triggered at
|
|
|
|
*/
|
|
|
|
u64 sequence;
|
2017-05-31 17:21:46 +08:00
|
|
|
/**
|
|
|
|
* @event: Actual event which will be sent to userspace.
|
|
|
|
*/
|
2017-07-06 05:34:23 +08:00
|
|
|
union {
|
2018-02-20 06:53:56 +08:00
|
|
|
/**
|
|
|
|
* @event.base: DRM event base class.
|
|
|
|
*/
|
2017-07-06 05:34:23 +08:00
|
|
|
struct drm_event base;
|
2018-02-20 06:53:56 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @event.vbl:
|
|
|
|
*
|
|
|
|
* Event payload for vblank events, requested through
|
|
|
|
* either the MODE_PAGE_FLIP or MODE_ATOMIC IOCTL. Also
|
|
|
|
* generated by the legacy WAIT_VBLANK IOCTL, but new userspace
|
|
|
|
* should use MODE_QUEUE_SEQUENCE and &event.seq instead.
|
|
|
|
*/
|
2017-07-06 05:34:23 +08:00
|
|
|
struct drm_event_vblank vbl;
|
2018-02-20 06:53:56 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @event.seq: Event payload for the MODE_QUEUEU_SEQUENCE IOCTL.
|
|
|
|
*/
|
2017-06-30 13:49:31 +08:00
|
|
|
struct drm_event_crtc_sequence seq;
|
2017-07-06 05:34:23 +08:00
|
|
|
} event;
|
2017-05-31 17:21:46 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct drm_vblank_crtc - vblank tracking for a CRTC
|
|
|
|
*
|
|
|
|
* This structure tracks the vblank state for one CRTC.
|
|
|
|
*
|
|
|
|
* Note that for historical reasons - the vblank handling code is still shared
|
|
|
|
* with legacy/non-kms drivers - this is a free-standing structure not directly
|
|
|
|
* connected to &struct drm_crtc. But all public interface functions are taking
|
|
|
|
* a &struct drm_crtc to hide this implementation detail.
|
|
|
|
*/
|
|
|
|
struct drm_vblank_crtc {
|
|
|
|
/**
|
|
|
|
* @dev: Pointer to the &drm_device.
|
|
|
|
*/
|
|
|
|
struct drm_device *dev;
|
|
|
|
/**
|
|
|
|
* @queue: Wait queue for vblank waiters.
|
|
|
|
*/
|
2018-10-05 15:36:36 +08:00
|
|
|
wait_queue_head_t queue;
|
2017-05-31 17:21:46 +08:00
|
|
|
/**
|
|
|
|
* @disable_timer: Disable timer for the delayed vblank disabling
|
|
|
|
* hysteresis logic. Vblank disabling is controlled through the
|
|
|
|
* drm_vblank_offdelay module option and the setting of the
|
|
|
|
* &drm_device.max_vblank_count value.
|
|
|
|
*/
|
|
|
|
struct timer_list disable_timer;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @seqlock: Protect vblank count and time.
|
|
|
|
*/
|
2018-10-05 15:36:36 +08:00
|
|
|
seqlock_t seqlock;
|
2017-05-31 17:21:46 +08:00
|
|
|
|
|
|
|
/**
|
2019-07-23 21:13:37 +08:00
|
|
|
* @count:
|
|
|
|
*
|
|
|
|
* Current software vblank counter.
|
|
|
|
*
|
|
|
|
* Note that for a given vblank counter value drm_crtc_handle_vblank()
|
|
|
|
* and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
|
|
|
|
* provide a barrier: Any writes done before calling
|
|
|
|
* drm_crtc_handle_vblank() will be visible to callers of the later
|
|
|
|
* functions, iff the vblank count is the same or a later one.
|
|
|
|
*
|
|
|
|
* IMPORTANT: This guarantee requires barriers, therefor never access
|
|
|
|
* this field directly. Use drm_crtc_vblank_count() instead.
|
2017-05-31 17:21:46 +08:00
|
|
|
*/
|
2019-07-23 21:13:37 +08:00
|
|
|
atomic64_t count;
|
2017-05-31 17:21:46 +08:00
|
|
|
/**
|
|
|
|
* @time: Vblank timestamp corresponding to @count.
|
|
|
|
*/
|
drm: vblank: use ktime_t instead of timeval
The drm vblank handling uses 'timeval' to store timestamps in either
monotonic or wall-clock time base. In either case, it reads the current
time as a ktime_t in get_drm_timestamp() and converts it from there.
This is a bit suspicious, as users of 'timeval' often suffer from
the time_t overflow in y2038. I have gone through this code and
found that it is unlikely to cause problems here:
- The user space ABI does not use time_t or timeval, but uses
'u32' and 'long' as the types. This means at least that rebuilding
user programs against a new libc with 64-bit time_t does not
change the ABI.
- As of commit c61eef726a78 ("drm: add support for monotonic vblank
timestamps") in linux-3.8, the monotonic timestamp is the default
and can only get reverted to wall-clock through a module-parameter.
- With the default monotonic timestamps, there is no problem at all.
- The drm_wait_vblank_ioctl() interface is alway safe on 64-bit
architectures, on 32-bit it might overflow the 'long' timestamps
in 2038 with wall-clock timestamps.
- The event handling uses 'u32' seconds, which overflow in 2106
on both 32-bit and 64-bit machines, when wall-clock timestamps
are used.
- The effect of overflowing either of the two is only temporary
(during the overflow, and is likely to keep working again
afterwards. It is likely the same problem as observing a
'settimeofday()' call, which was the reason for moving to the
monotonic timestamps in the first place.
Overall, this seems good enough, so my patch removes the use of
'timeval' from the vblank handling altogether and uses ktime_t
consistently, except for the part where we copy the data to user
space structures in the existing format.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2017-10-11 23:20:12 +08:00
|
|
|
ktime_t time;
|
2017-05-31 17:21:46 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @refcount: Number of users/waiters of the vblank interrupt. Only when
|
|
|
|
* this refcount reaches 0 can the hardware interrupt be disabled using
|
|
|
|
* @disable_timer.
|
|
|
|
*/
|
2018-10-05 15:36:36 +08:00
|
|
|
atomic_t refcount;
|
2017-05-31 17:21:46 +08:00
|
|
|
/**
|
|
|
|
* @last: Protected by &drm_device.vbl_lock, used for wraparound handling.
|
|
|
|
*/
|
|
|
|
u32 last;
|
2018-11-28 02:20:04 +08:00
|
|
|
/**
|
|
|
|
* @max_vblank_count:
|
|
|
|
*
|
|
|
|
* Maximum value of the vblank registers for this crtc. This value +1
|
|
|
|
* will result in a wrap-around of the vblank register. It is used
|
|
|
|
* by the vblank core to handle wrap-arounds.
|
|
|
|
*
|
|
|
|
* If set to zero the vblank core will try to guess the elapsed vblanks
|
|
|
|
* between times when the vblank interrupt is disabled through
|
|
|
|
* high-precision timestamps. That approach is suffering from small
|
|
|
|
* races and imprecision over longer time periods, hence exposing a
|
|
|
|
* hardware vblank counter is always recommended.
|
|
|
|
*
|
|
|
|
* This is the runtime configurable per-crtc maximum set through
|
|
|
|
* drm_crtc_set_max_vblank_count(). If this is used the driver
|
|
|
|
* must leave the device wide &drm_device.max_vblank_count at zero.
|
|
|
|
*
|
|
|
|
* If non-zero, &drm_crtc_funcs.get_vblank_counter must be set.
|
|
|
|
*/
|
|
|
|
u32 max_vblank_count;
|
2017-05-31 17:21:46 +08:00
|
|
|
/**
|
|
|
|
* @inmodeset: Tracks whether the vblank is disabled due to a modeset.
|
|
|
|
* For legacy driver bit 2 additionally tracks whether an additional
|
|
|
|
* temporary vblank reference has been acquired to paper over the
|
|
|
|
* hardware counter resetting/jumping. KMS drivers should instead just
|
|
|
|
* call drm_crtc_vblank_off() and drm_crtc_vblank_on(), which explicitly
|
|
|
|
* save and restore the vblank count.
|
|
|
|
*/
|
2018-10-05 15:36:36 +08:00
|
|
|
unsigned int inmodeset;
|
2017-05-31 17:21:46 +08:00
|
|
|
/**
|
|
|
|
* @pipe: drm_crtc_index() of the &drm_crtc corresponding to this
|
|
|
|
* structure.
|
|
|
|
*/
|
|
|
|
unsigned int pipe;
|
|
|
|
/**
|
|
|
|
* @framedur_ns: Frame/Field duration in ns, used by
|
2020-01-23 21:59:24 +08:00
|
|
|
* drm_crtc_vblank_helper_get_vblank_timestamp() and computed by
|
2017-05-31 17:21:46 +08:00
|
|
|
* drm_calc_timestamping_constants().
|
|
|
|
*/
|
|
|
|
int framedur_ns;
|
|
|
|
/**
|
|
|
|
* @linedur_ns: Line duration in ns, used by
|
2020-01-23 21:59:24 +08:00
|
|
|
* drm_crtc_vblank_helper_get_vblank_timestamp() and computed by
|
2017-05-31 17:21:46 +08:00
|
|
|
* drm_calc_timestamping_constants().
|
|
|
|
*/
|
|
|
|
int linedur_ns;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @hwmode:
|
|
|
|
*
|
|
|
|
* Cache of the current hardware display mode. Only valid when @enabled
|
|
|
|
* is set. This is used by helpers like
|
2020-01-23 21:59:24 +08:00
|
|
|
* drm_crtc_vblank_helper_get_vblank_timestamp(). We can't just access
|
|
|
|
* the hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode,
|
2017-05-31 17:21:46 +08:00
|
|
|
* because that one is really hard to get from interrupt context.
|
|
|
|
*/
|
|
|
|
struct drm_display_mode hwmode;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @enabled: Tracks the enabling state of the corresponding &drm_crtc to
|
|
|
|
* avoid double-disabling and hence corrupting saved state. Needed by
|
|
|
|
* drivers not using atomic KMS, since those might go through their CRTC
|
|
|
|
* disabling functions multiple times.
|
|
|
|
*/
|
|
|
|
bool enabled;
|
|
|
|
};
|
|
|
|
|
|
|
|
int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
|
2020-01-29 20:05:17 +08:00
|
|
|
bool drm_dev_has_vblank(const struct drm_device *dev);
|
2017-10-13 02:57:49 +08:00
|
|
|
u64 drm_crtc_vblank_count(struct drm_crtc *crtc);
|
|
|
|
u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
|
drm: vblank: use ktime_t instead of timeval
The drm vblank handling uses 'timeval' to store timestamps in either
monotonic or wall-clock time base. In either case, it reads the current
time as a ktime_t in get_drm_timestamp() and converts it from there.
This is a bit suspicious, as users of 'timeval' often suffer from
the time_t overflow in y2038. I have gone through this code and
found that it is unlikely to cause problems here:
- The user space ABI does not use time_t or timeval, but uses
'u32' and 'long' as the types. This means at least that rebuilding
user programs against a new libc with 64-bit time_t does not
change the ABI.
- As of commit c61eef726a78 ("drm: add support for monotonic vblank
timestamps") in linux-3.8, the monotonic timestamp is the default
and can only get reverted to wall-clock through a module-parameter.
- With the default monotonic timestamps, there is no problem at all.
- The drm_wait_vblank_ioctl() interface is alway safe on 64-bit
architectures, on 32-bit it might overflow the 'long' timestamps
in 2038 with wall-clock timestamps.
- The event handling uses 'u32' seconds, which overflow in 2106
on both 32-bit and 64-bit machines, when wall-clock timestamps
are used.
- The effect of overflowing either of the two is only temporary
(during the overflow, and is likely to keep working again
afterwards. It is likely the same problem as observing a
'settimeofday()' call, which was the reason for moving to the
monotonic timestamps in the first place.
Overall, this seems good enough, so my patch removes the use of
'timeval' from the vblank handling altogether and uses ktime_t
consistently, except for the part where we copy the data to user
space structures in the existing format.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2017-10-11 23:20:12 +08:00
|
|
|
ktime_t *vblanktime);
|
2017-05-31 17:21:46 +08:00
|
|
|
void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
|
|
|
|
struct drm_pending_vblank_event *e);
|
|
|
|
void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
|
|
|
|
struct drm_pending_vblank_event *e);
|
2017-07-06 05:34:23 +08:00
|
|
|
void drm_vblank_set_event(struct drm_pending_vblank_event *e,
|
|
|
|
u64 *seq,
|
|
|
|
ktime_t *now);
|
2017-05-31 17:21:46 +08:00
|
|
|
bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe);
|
|
|
|
bool drm_crtc_handle_vblank(struct drm_crtc *crtc);
|
|
|
|
int drm_crtc_vblank_get(struct drm_crtc *crtc);
|
|
|
|
void drm_crtc_vblank_put(struct drm_crtc *crtc);
|
|
|
|
void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe);
|
|
|
|
void drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
|
|
|
|
void drm_crtc_vblank_off(struct drm_crtc *crtc);
|
|
|
|
void drm_crtc_vblank_reset(struct drm_crtc *crtc);
|
|
|
|
void drm_crtc_vblank_on(struct drm_crtc *crtc);
|
2018-02-03 13:12:53 +08:00
|
|
|
u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc);
|
2018-02-03 13:13:01 +08:00
|
|
|
void drm_vblank_restore(struct drm_device *dev, unsigned int pipe);
|
|
|
|
void drm_crtc_vblank_restore(struct drm_crtc *crtc);
|
2017-05-31 17:21:46 +08:00
|
|
|
|
|
|
|
void drm_calc_timestamping_constants(struct drm_crtc *crtc,
|
|
|
|
const struct drm_display_mode *mode);
|
|
|
|
wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
|
2018-11-28 02:20:04 +08:00
|
|
|
void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
|
|
|
|
u32 max_vblank_count);
|
2020-01-23 21:59:23 +08:00
|
|
|
|
2020-01-23 21:59:24 +08:00
|
|
|
/*
|
|
|
|
* Helpers for struct drm_crtc_funcs
|
|
|
|
*/
|
|
|
|
|
2020-01-23 21:59:23 +08:00
|
|
|
typedef bool (*drm_vblank_get_scanout_position_func)(struct drm_crtc *crtc,
|
|
|
|
bool in_vblank_irq,
|
|
|
|
int *vpos, int *hpos,
|
|
|
|
ktime_t *stime,
|
|
|
|
ktime_t *etime,
|
|
|
|
const struct drm_display_mode *mode);
|
|
|
|
|
|
|
|
bool
|
|
|
|
drm_crtc_vblank_helper_get_vblank_timestamp_internal(struct drm_crtc *crtc,
|
|
|
|
int *max_error,
|
|
|
|
ktime_t *vblank_time,
|
|
|
|
bool in_vblank_irq,
|
2020-01-23 21:59:43 +08:00
|
|
|
drm_vblank_get_scanout_position_func get_scanout_position);
|
2020-01-23 21:59:24 +08:00
|
|
|
bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc,
|
|
|
|
int *max_error,
|
|
|
|
ktime_t *vblank_time,
|
|
|
|
bool in_vblank_irq);
|
2020-01-23 21:59:23 +08:00
|
|
|
|
2017-05-31 17:21:46 +08:00
|
|
|
#endif
|