mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-18 03:23:53 -04:00
The vblank timer simulates a vblank interrupt for hardware without
support. Rate-limits the display update frequency.
DRM drivers for hardware without vblank support apply display updates
ASAP. A vblank event informs DRM clients of the completed update.
Userspace compositors immediately schedule the next update, which
creates significant load on virtualization outputs. Display updates
are usually fast on virtualization outputs, as their framebuffers are
in regular system memory and there's no hardware vblank interrupt to
throttle the update rate.
The vblank timer is a HR timer that signals the vblank in software.
It limits the update frequency of a DRM driver similar to a hardware
vblank interrupt. The timer is not synchronized to the actual vblank
interval of the display.
The code has been adopted from vkms, which added the funtionality
in commit 3a0709928b ("drm/vkms: Add vblank events simulated by
hrtimers").
The new implementation is part of the existing vblank support,
which sets up the timer automatically. Drivers only have to start
and cancel the vblank timer as part of enabling and disabling the
CRTC. The new vblank helper library provides callbacks for struct
drm_crtc_funcs.
The standard way for handling vblank is to call drm_crtc_handle_vblank().
Drivers that require additional processing, such as vkms, can init
handle_vblank_timeout in struct drm_crtc_helper_funcs to refer to
their timeout handler.
There's a possible deadlock between drm_crtc_handle_vblank() and
hrtimer_cancel(). [1] The implementation avoids to call hrtimer_cancel()
directly and instead signals to the timer function to not restart
itself.
v4:
- fix possible race condition between timeout and atomic commit (Michael)
v3:
- avoid deadlock when cancelling timer (Ville, Lyude)
v2:
- implement vblank timer entirely in vblank helpers
- downgrade overrun warning to debug
- fix docs
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Tested-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Link: https://lore.kernel.org/all/20250510094757.4174662-1-zengheng4@huawei.com/ # [1]
Link: https://lore.kernel.org/r/20250916083816.30275-2-tzimmermann@suse.de
97 lines
3.2 KiB
C
97 lines
3.2 KiB
C
// SPDX-License-Identifier: MIT
|
|
|
|
#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.
|
|
*
|
|
* 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 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);
|