drm: Initialize struct drm_crtc_state.no_vblank from device settings
At the end of a commit, atomic helpers can generate a fake VBLANK event automatically. Originally implemented for writeback connectors, the functionality can be used by any driver and/or hardware without proper VBLANK interrupt. The patch updates the documentation to make this behaviour official: settings struct drm_crtc_state.no_vblank to true enables automatic generation of fake VBLANK events. The new interface drm_dev_has_vblank() returns true if vblanking has been initialized for a device, or false otherwise. Atomic helpers use this function when initializing no_vblank in the CRTC state in drm_atomic_helper_check_modeset(). If vblanking has been initialized for a device, no_blank is disabled. Otherwise it's enabled. Hence, atomic helpers will automatically send out fake VBLANK events with any driver that did not initialize vblanking. v5: * more precise documentation and commit message v4: * replace drm_crtc_has_vblank() with drm_dev_has_vblank() * add drm_dev_has_vblank() in this patch * move driver changes into separate patches v3: * squash all related changes patches into this patch Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200129120531.6891-2-tzimmermann@suse.de
This commit is contained in:
parent
86a9360be1
commit
7beb691f1e
@ -583,6 +583,7 @@ mode_valid(struct drm_atomic_state *state)
|
||||
* &drm_crtc_state.connectors_changed is set when a connector is added or
|
||||
* removed from the CRTC. &drm_crtc_state.active_changed is set when
|
||||
* &drm_crtc_state.active changes, which is used for DPMS.
|
||||
* &drm_crtc_state.no_vblank is set from the result of drm_dev_has_vblank().
|
||||
* See also: drm_atomic_crtc_needs_modeset()
|
||||
*
|
||||
* IMPORTANT:
|
||||
@ -649,6 +650,11 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (drm_dev_has_vblank(dev))
|
||||
new_crtc_state->no_vblank = false;
|
||||
else
|
||||
new_crtc_state->no_vblank = true;
|
||||
}
|
||||
|
||||
ret = handle_conflicting_encoders(state, false);
|
||||
@ -2215,7 +2221,9 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
|
||||
* when a job is queued, and any change to the pipeline that does not touch the
|
||||
* connector is leading to timeouts when calling
|
||||
* drm_atomic_helper_wait_for_vblanks() or
|
||||
* drm_atomic_helper_wait_for_flip_done().
|
||||
* drm_atomic_helper_wait_for_flip_done(). In addition to writeback
|
||||
* connectors, this function can also fake VBLANK events for CRTCs without
|
||||
* VBLANK interrupt.
|
||||
*
|
||||
* This is part of the atomic helper support for nonblocking commits, see
|
||||
* drm_atomic_helper_setup_commit() for an overview.
|
||||
|
@ -69,6 +69,12 @@
|
||||
* &drm_driver.max_vblank_count. In that case the vblank core only disables the
|
||||
* vblanks after a timer has expired, which can be configured through the
|
||||
* ``vblankoffdelay`` module parameter.
|
||||
*
|
||||
* Drivers for hardware without support for vertical-blanking interrupts
|
||||
* must not call drm_vblank_init(). For such drivers, atomic helpers will
|
||||
* automatically generate fake vblank events as part of the display update.
|
||||
* This functionality also can be controlled by the driver by enabling and
|
||||
* disabling struct drm_crtc_state.no_vblank.
|
||||
*/
|
||||
|
||||
/* Retry timestamp calculation up to 3 times to satisfy
|
||||
@ -501,6 +507,28 @@ err:
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_init);
|
||||
|
||||
/**
|
||||
* drm_dev_has_vblank - test if vblanking has been initialized for
|
||||
* a device
|
||||
* @dev: the device
|
||||
*
|
||||
* Drivers may call this function to test if vblank support is
|
||||
* initialized for a device. For most hardware this means that vblanking
|
||||
* can also be enabled.
|
||||
*
|
||||
* Atomic helpers use this function to initialize
|
||||
* &drm_crtc_state.no_vblank. See also drm_atomic_helper_check_modeset().
|
||||
*
|
||||
* Returns:
|
||||
* True if vblanking has been initialized for the given device, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool drm_dev_has_vblank(const struct drm_device *dev)
|
||||
{
|
||||
return dev->num_crtcs != 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dev_has_vblank);
|
||||
|
||||
/**
|
||||
* drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC
|
||||
* @crtc: which CRTC's vblank waitqueue to retrieve
|
||||
|
@ -174,12 +174,25 @@ struct drm_crtc_state {
|
||||
* @no_vblank:
|
||||
*
|
||||
* Reflects the ability of a CRTC to send VBLANK events. This state
|
||||
* usually depends on the pipeline configuration, and the main usuage
|
||||
* is CRTCs feeding a writeback connector operating in oneshot mode.
|
||||
* In this case the VBLANK event is only generated when a job is queued
|
||||
* to the writeback connector, and we want the core to fake VBLANK
|
||||
* events when this part of the pipeline hasn't changed but others had
|
||||
* or when the CRTC and connectors are being disabled.
|
||||
* usually depends on the pipeline configuration. If set to true, DRM
|
||||
* atomic helpers will send out a fake VBLANK event during display
|
||||
* updates after all hardware changes have been committed. This is
|
||||
* implemented in drm_atomic_helper_fake_vblank().
|
||||
*
|
||||
* One usage is for drivers and/or hardware without support for VBLANK
|
||||
* interrupts. Such drivers typically do not initialize vblanking
|
||||
* (i.e., call drm_vblank_init() with the number of CRTCs). For CRTCs
|
||||
* without initialized vblanking, this field is set to true in
|
||||
* drm_atomic_helper_check_modeset(), and a fake VBLANK event will be
|
||||
* send out on each update of the display pipeline by
|
||||
* drm_atomic_helper_fake_vblank().
|
||||
*
|
||||
* Another usage is CRTCs feeding a writeback connector operating in
|
||||
* oneshot mode. In this case the fake VBLANK event is only generated
|
||||
* when a job is queued to the writeback connector, and we want the
|
||||
* core to fake VBLANK events when this part of the pipeline hasn't
|
||||
* changed but others had or when the CRTC and connectors are being
|
||||
* disabled.
|
||||
*
|
||||
* __drm_atomic_helper_crtc_duplicate_state() will not reset the value
|
||||
* from the current state, the CRTC driver is then responsible for
|
||||
@ -335,7 +348,14 @@ struct drm_crtc_state {
|
||||
* - Events for disabled CRTCs are not allowed, and drivers can ignore
|
||||
* that case.
|
||||
*
|
||||
* This can be handled by the drm_crtc_send_vblank_event() function,
|
||||
* For very simple hardware without VBLANK interrupt, enabling
|
||||
* &struct drm_crtc_state.no_vblank makes DRM's atomic commit helpers
|
||||
* send a fake VBLANK event at the end of the display update after all
|
||||
* hardware changes have been applied. See
|
||||
* drm_atomic_helper_fake_vblank().
|
||||
*
|
||||
* For more complex hardware this
|
||||
* can be handled by the drm_crtc_send_vblank_event() function,
|
||||
* which the driver should call on the provided event upon completion of
|
||||
* the atomic commit. Note that if the driver supports vblank signalling
|
||||
* and timestamping the vblank counters and timestamps must agree with
|
||||
|
@ -100,8 +100,11 @@ struct drm_simple_display_pipe_funcs {
|
||||
* This is the function drivers should submit the
|
||||
* &drm_pending_vblank_event from. Using either
|
||||
* drm_crtc_arm_vblank_event(), when the driver supports vblank
|
||||
* interrupt handling, or drm_crtc_send_vblank_event() directly in case
|
||||
* the hardware lacks vblank support entirely.
|
||||
* interrupt handling, or drm_crtc_send_vblank_event() for more
|
||||
* complex case. In case the hardware lacks vblank support entirely,
|
||||
* drivers can set &struct drm_crtc_state.no_vblank in
|
||||
* &struct drm_simple_display_pipe_funcs.check and let DRM's
|
||||
* atomic helper fake a vblank event.
|
||||
*/
|
||||
void (*update)(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_plane_state *old_plane_state);
|
||||
|
@ -206,6 +206,7 @@ struct drm_vblank_crtc {
|
||||
};
|
||||
|
||||
int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
|
||||
bool drm_dev_has_vblank(const struct drm_device *dev);
|
||||
u64 drm_crtc_vblank_count(struct drm_crtc *crtc);
|
||||
u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
|
||||
ktime_t *vblanktime);
|
||||
|
Loading…
Reference in New Issue
Block a user