Drivers implementing SRO need to iterate over their KMS objects, allocate a pristine state for each, call the readout hook, and store the result in the SRO state container.
Provide helpers for each object type (drm_atomic_helper_sro_readout_planes_state(), drm_atomic_helper_sro_readout_crtcs_state(), etc.) and a top-level drm_atomic_helper_sro_build_state() that calls them in sequence. Reviewed-by: Maarten Lankhorst <[email protected]> Signed-off-by: Maxime Ripard <[email protected]> --- Documentation/gpu/drm-kms-helpers.rst | 9 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_atomic_state_readout.c | 5 +- drivers/gpu/drm/drm_atomic_state_readout_helper.c | 681 ++++++++++++++++++++++ include/drm/drm_atomic_state_readout_helper.h | 35 ++ include/drm/drm_modeset_helper_vtables.h | 3 + 6 files changed, 733 insertions(+), 1 deletion(-) diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index b75bde712faf..a6dd8dbb3218 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -100,4 +100,13 @@ Atomic State Read-Out Reference :export: +Atomic State Read-Out Helpers Reference +---------------------------------------- + +.. kernel-doc:: include/drm/drm_atomic_state_readout_helper.h + :internal: + +.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_readout_helper.c + :export: + GEM Atomic Helper Reference --------------------------- diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index e94b77497514..7c8b778f4d5e 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -144,4 +144,5 @@ drm_kms_helper-y := \ drm_atomic_helper.o \ drm_atomic_state_helper.o \ + drm_atomic_state_readout_helper.o \ drm_bridge_helper.o \ drm_crtc_helper.o \ diff --git a/drivers/gpu/drm/drm_atomic_state_readout.c b/drivers/gpu/drm/drm_atomic_state_readout.c index 413823579ed5..2c17fa09c5f0 100644 --- a/drivers/gpu/drm/drm_atomic_state_readout.c +++ b/drivers/gpu/drm/drm_atomic_state_readout.c @@ -49,5 +49,8 @@ * object funcs vtables and setting the * &drm_mode_config_funcs.atomic_sro_readout_state and - * &drm_mode_config_helper_funcs.atomic_sro_build_state callbacks. + * &drm_mode_config_helper_funcs.atomic_sro_build_state callbacks. The + * default helpers drm_atomic_helper_sro_readout_state() and + * drm_atomic_helper_sro_build_state() handle the standard readout + * sequence. */ diff --git a/drivers/gpu/drm/drm_atomic_state_readout_helper.c b/drivers/gpu/drm/drm_atomic_state_readout_helper.c new file mode 100644 index 000000000000..a0b0337df2a0 --- /dev/null +++ b/drivers/gpu/drm/drm_atomic_state_readout_helper.c @@ -0,0 +1,681 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_state_readout.h> +#include <drm/drm_atomic_state_readout_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_colorop.h> +#include <drm/drm_connector.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_plane.h> +#include <drm/drm_print.h> + +#include <linux/gfp.h> +#include <linux/sched/mm.h> + +static int +drm_atomic_helper_sro_readout_plane_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_plane *plane) +{ + const struct drm_plane_funcs *plane_funcs = plane->funcs; + struct drm_plane_state *plane_state; + int ret; + + if (!plane_funcs->atomic_sro_readout_state) { + drm_warn(dev, "No plane readout implementation."); + return 0; + } + + drm_dbg_kms(dev, "Initializing Plane %s state.\n", plane->name); + + plane_state = plane_funcs->atomic_create_state(plane); + if (drm_WARN_ON(dev, IS_ERR(plane_state))) + return PTR_ERR(plane_state); + + ret = plane_funcs->atomic_sro_readout_state(plane, state, + plane_state); + if (drm_WARN_ON(dev, ret)) { + plane_funcs->atomic_destroy_state(plane, plane_state); + return ret; + } + + drm_atomic_sro_set_plane_state(state, plane, plane_state); + + return 0; +} + +static int +drm_atomic_helper_sro_readout_commit_planes_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_plane_state *new_plane_state; + struct drm_plane *plane; + unsigned int i; + int ret; + + if (!commit) + return -EINVAL; + + for_each_new_plane_in_state(commit, plane, new_plane_state, i) { + ret = drm_atomic_helper_sro_readout_plane_state(dev, state, plane); + if (ret) + return ret; + } + + return 0; +} + +/** + * drm_atomic_helper_sro_readout_planes_state - read out all plane states from hardware + * @dev: DRM device + * @state: SRO state container to fill + * @commit: optional atomic commit limiting the objects to read out + * + * Iterates over the planes that have a state in @commit when it isn't + * NULL, or over all the planes of @dev otherwise. For each, allocates + * a state via atomic_create_state, and calls the plane's + * atomic_sro_readout_state hook to fill it from hardware. + * + * RETURNS: + * + * 0 on success, a negative error code otherwise. + */ +int +drm_atomic_helper_sro_readout_planes_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_plane *plane; + int ret; + + might_alloc(GFP_KERNEL); + + if (commit) + return drm_atomic_helper_sro_readout_commit_planes_state(dev, state, commit); + + drm_for_each_plane(plane, dev) { + ret = drm_atomic_helper_sro_readout_plane_state(dev, state, plane); + if (ret) + return ret; + } + + return 0; +} + +static int +drm_atomic_helper_sro_readout_crtc_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_crtc *crtc) +{ + const struct drm_crtc_funcs *crtc_funcs = crtc->funcs; + struct drm_crtc_state *crtc_state; + int ret; + + if (!crtc_funcs->atomic_sro_readout_state) { + drm_warn(dev, "No CRTC readout implementation."); + return 0; + } + + drm_dbg_kms(dev, "Initializing CRTC %s state.\n", crtc->name); + + crtc_state = crtc_funcs->atomic_create_state(crtc); + if (drm_WARN_ON(dev, IS_ERR(crtc_state))) + return PTR_ERR(crtc_state); + + ret = crtc_funcs->atomic_sro_readout_state(crtc, state, crtc_state); + if (drm_WARN_ON(dev, ret)) { + crtc_funcs->atomic_destroy_state(crtc, crtc_state); + return ret; + } + + drm_atomic_sro_set_crtc_state(state, crtc, crtc_state); + + return 0; +} + +static int +drm_atomic_helper_sro_readout_commit_crtcs_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_crtc_state *new_crtc_state; + struct drm_crtc *crtc; + unsigned int i; + int ret; + + if (!commit) + return -EINVAL; + + for_each_new_crtc_in_state(commit, crtc, new_crtc_state, i) { + ret = drm_atomic_helper_sro_readout_crtc_state(dev, state, crtc); + if (ret) + return ret; + } + + return 0; +} + +/** + * drm_atomic_helper_sro_readout_crtcs_state - read out all CRTC states from hardware + * @dev: DRM device + * @state: SRO state container to fill + * @commit: optional atomic commit limiting the objects to read out + * + * Iterates over the CRTCs that have a state in @commit when it isn't + * NULL, or over all the CRTCs of @dev otherwise. For each, allocates a + * state via atomic_create_state, and calls the CRTC's + * atomic_sro_readout_state hook to fill it from hardware. + * + * RETURNS: + * + * 0 on success, a negative error code otherwise. + */ +int +drm_atomic_helper_sro_readout_crtcs_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_crtc *crtc; + int ret; + + might_alloc(GFP_KERNEL); + + if (commit) + return drm_atomic_helper_sro_readout_commit_crtcs_state(dev, state, commit); + + drm_for_each_crtc(crtc, dev) { + ret = drm_atomic_helper_sro_readout_crtc_state(dev, state, crtc); + if (ret) + return ret; + } + + return 0; +} + +static int +drm_atomic_helper_sro_readout_connector_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_connector *connector) +{ + const struct drm_connector_funcs *conn_funcs = connector->funcs; + struct drm_connector_state *conn_state; + int ret; + + if (!conn_funcs->atomic_sro_readout_state) { + drm_warn(dev, "No connector readout implementation."); + return 0; + } + + drm_dbg_kms(dev, "Initializing connector %s state.\n", + connector->name); + + conn_state = conn_funcs->atomic_create_state(connector); + if (drm_WARN_ON(dev, IS_ERR(conn_state))) + return PTR_ERR(conn_state); + + ret = conn_funcs->atomic_sro_readout_state(connector, state, + conn_state); + if (drm_WARN_ON(dev, ret)) { + conn_funcs->atomic_destroy_state(connector, conn_state); + return ret; + } + + drm_atomic_sro_set_connector_state(state, connector, conn_state); + + return 0; +} + +static int +drm_atomic_helper_sro_readout_commit_connectors_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_connector_state *new_connector_state; + struct drm_connector *connector; + unsigned int i; + int ret; + + if (!commit) + return -EINVAL; + + for_each_new_connector_in_state(commit, connector, new_connector_state, i) { + ret = drm_atomic_helper_sro_readout_connector_state(dev, state, connector); + if (ret) + return ret; + } + + return 0; +} + +/** + * drm_atomic_helper_sro_readout_connectors_state - read out all connector states from hardware + * @dev: DRM device + * @state: SRO state container to fill + * @commit: optional atomic commit limiting the objects to read out + * + * Iterates over the connectors that have a state in @commit when it + * isn't NULL, or over all the connectors of @dev otherwise. For each, + * allocates a state via atomic_create_state, and calls the connector's + * atomic_sro_readout_state hook to fill it from hardware. + * + * RETURNS: + * + * 0 on success, a negative error code otherwise. + */ +int +drm_atomic_helper_sro_readout_connectors_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_connector_list_iter conn_iter; + struct drm_connector *connector; + int ret; + + might_alloc(GFP_KERNEL); + + if (commit) + return drm_atomic_helper_sro_readout_commit_connectors_state(dev, state, commit); + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + ret = drm_atomic_helper_sro_readout_connector_state(dev, state, connector); + if (ret) { + drm_connector_list_iter_end(&conn_iter); + return ret; + } + } + drm_connector_list_iter_end(&conn_iter); + + return 0; +} + +static int +drm_atomic_helper_sro_readout_bridge_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_bridge *bridge) +{ + struct drm_private_obj *bridge_obj = &bridge->base; + const struct drm_private_state_funcs *bridge_obj_funcs = + bridge_obj->funcs; + struct drm_private_state *bridge_obj_state; + int ret; + + /* + * The same bridge chain can be reached through several + * connectors of the commit. This happens for instance when a + * commit disables a connector and routes another one to its + * encoder: the chain is then reached through the old state of + * the connector being disabled and through the new state of + * the connector taking over. Don't read a bridge out twice. + */ + if (drm_atomic_sro_get_private_obj_state(state, bridge_obj)) + return 0; + + if (!bridge_obj_funcs->atomic_sro_readout_state) { + drm_warn(dev, "No bridge %s readout implementation.", + bridge->name); + return 0; + } + + drm_dbg_kms(dev, "Initializing Bridge %s state", bridge->name); + + bridge_obj_state = bridge_obj_funcs->atomic_create_state(bridge_obj); + if (drm_WARN_ON(dev, IS_ERR(bridge_obj_state))) + return PTR_ERR(bridge_obj_state); + + ret = bridge_obj_funcs->atomic_sro_readout_state(bridge_obj, state, + bridge_obj_state); + if (drm_WARN_ON(dev, ret)) { + bridge_obj_funcs->atomic_destroy_state(bridge_obj, + bridge_obj_state); + return ret; + } + + drm_atomic_sro_set_private_obj_state(state, bridge_obj, + bridge_obj_state); + + return 0; +} + +static int +drm_atomic_helper_sro_readout_bridge_chain_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_encoder *encoder) +{ + int ret; + + drm_for_each_bridge_in_chain(encoder, bridge) { + ret = drm_atomic_helper_sro_readout_bridge_state(dev, state, bridge); + if (ret) + return ret; + } + + return 0; +} + +static int +drm_atomic_helper_sro_readout_commit_bridges_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_connector_state *old_conn_state, *new_conn_state; + struct drm_connector *connector; + unsigned int i; + + if (!commit) + return -EINVAL; + + /* + * Bridges can only be part of a commit through the connector + * they are routed to, either the one they were routed to before + * the commit or the one they are routed to after. Walking the + * chains of the encoders of the committed connectors thus + * covers all the bridges the commit can contain. + */ + for_each_oldnew_connector_in_state(commit, connector, old_conn_state, new_conn_state, i) { + struct drm_encoder *old_encoder = old_conn_state->best_encoder; + struct drm_encoder *new_encoder = new_conn_state->best_encoder; + int ret; + + if (old_encoder) { + ret = drm_atomic_helper_sro_readout_bridge_chain_state(dev, + state, + old_encoder); + if (ret) + return ret; + } + + if (new_encoder && new_encoder != old_encoder) { + ret = drm_atomic_helper_sro_readout_bridge_chain_state(dev, + state, + new_encoder); + if (ret) + return ret; + } + } + + return 0; +} + +/** + * drm_atomic_helper_sro_readout_bridges_state - read out all bridge states from hardware + * @dev: DRM device + * @state: SRO state container to fill + * @commit: optional atomic commit limiting the objects to read out + * + * Iterates over the bridge chains of the encoders of the connectors + * that have a state in @commit when it isn't NULL, or over all the + * encoders of @dev otherwise. For each bridge, allocates a state via + * atomic_create_state, and calls the bridge's atomic_sro_readout_state + * hook to fill it from hardware. + * + * Bridges are handled separately from other private objects because + * bridge registration does not guarantee ordering. Traversing the + * encoder bridge chains ensures each bridge can query the state of + * preceding bridges in its chain. + * + * RETURNS: + * + * 0 on success, a negative error code otherwise. + */ +int +drm_atomic_helper_sro_readout_bridges_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_encoder *encoder; + int ret; + + might_alloc(GFP_KERNEL); + + /* + * It works a bit differently for bridges. Indeed they rely on a + * drm_private_obj and drm_private_state, but bridge + * registration doesn't guarantee ordering. + * + * In order for each bridge callback to be able to query the + * previous bridge state, we thus need to read out the bridge + * state by looking at each encoder and then traversing its + * bridge list. + * + * And we'll then readout all the non-bridge drm_private_obj + * later. + */ + + if (commit) + return drm_atomic_helper_sro_readout_commit_bridges_state(dev, state, commit); + + drm_for_each_encoder(encoder, dev) { + ret = drm_atomic_helper_sro_readout_bridge_chain_state(dev, state, encoder); + if (ret) + return ret; + } + + return 0; +} + +static int +drm_atomic_helper_sro_readout_private_obj_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_private_obj *privobj) +{ + const struct drm_private_state_funcs *priv_funcs = privobj->funcs; + struct drm_private_state *priv_state; + int ret; + + /* + * The bridges are read out by + * drm_atomic_helper_sro_readout_bridges_state() instead, in + * bridge chain order. + */ + if (drm_private_obj_is_bridge(privobj)) + return 0; + + if (!priv_funcs->atomic_sro_readout_state) { + drm_warn(dev, "No private object %s readout implementation.", + privobj->name); + return 0; + } + + drm_dbg_kms(dev, "Initializing Private Object %s state", privobj->name); + + priv_state = priv_funcs->atomic_create_state(privobj); + if (drm_WARN_ON(dev, IS_ERR(priv_state))) + return PTR_ERR(priv_state); + + ret = priv_funcs->atomic_sro_readout_state(privobj, state, + priv_state); + if (drm_WARN_ON(dev, ret)) { + priv_funcs->atomic_destroy_state(privobj, priv_state); + return ret; + } + + drm_atomic_sro_set_private_obj_state(state, privobj, priv_state); + + return 0; +} + +static int +drm_atomic_helper_sro_readout_commit_private_objs_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_private_state *new_obj_state; + struct drm_private_obj *obj; + unsigned int i; + int ret; + + if (!commit) + return -EINVAL; + + for_each_new_private_obj_in_state(commit, obj, new_obj_state, i) { + ret = drm_atomic_helper_sro_readout_private_obj_state(dev, state, obj); + if (ret) + return ret; + } + + return 0; +} + +/** + * drm_atomic_helper_sro_readout_private_objs_state - read out non-bridge private object states + * @dev: DRM device + * @state: SRO state container to fill + * @commit: optional atomic commit limiting the objects to read out + * + * Iterates over the private objects that have a state in @commit when + * it isn't NULL, or over all the private objects of @dev otherwise. For + * each, allocates a state via atomic_create_state, and calls the + * object's atomic_sro_readout_state hook to fill it from hardware. + * + * RETURNS: + * + * 0 on success, a negative error code otherwise. + */ +int +drm_atomic_helper_sro_readout_private_objs_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit) +{ + struct drm_private_obj *obj; + int ret; + + might_alloc(GFP_KERNEL); + + if (commit) + return drm_atomic_helper_sro_readout_commit_private_objs_state(dev, state, commit); + + drm_for_each_privobj(obj, dev) { + ret = drm_atomic_helper_sro_readout_private_obj_state(dev, state, obj); + if (ret) + return ret; + } + + return 0; +} + +/** + * drm_atomic_helper_sro_build_state - build an SRO state from hardware + * @dev: DRM device to build the state for + * @commit: optional atomic commit limiting the objects to read out + * + * Allocates a &struct drm_atomic_sro_state and calls the readout hooks + * for CRTCs, planes, connectors, bridges, and private objects in + * sequence to fill it from the current hardware state. + * + * When @commit is NULL, the state of every object in the device is + * read out, and the caller must hold all the modeset locks. When it + * isn't NULL, only the objects that have a state in @commit are read + * out, and the caller must hold the locks of the objects in @commit. + * + * This is the default implementation for + * &drm_mode_config_helper_funcs.atomic_sro_build_state. + * + * RETURNS: + * + * A &struct drm_atomic_sro_state on success, an error pointer otherwise. + */ +struct drm_atomic_sro_state * +drm_atomic_helper_sro_build_state(struct drm_device *dev, + struct drm_atomic_commit *commit) +{ + struct drm_atomic_sro_state *state; + struct drm_printer p = drm_dbg_printer(dev, DRM_UT_ATOMIC, NULL); + int ret; + + might_alloc(GFP_KERNEL); + + drm_dbg_kms(dev, "Starting to build atomic state from hardware state.\n"); + + state = drm_atomic_sro_state_alloc(dev); + if (drm_WARN_ON(dev, IS_ERR(state))) + return state; + + ret = drm_atomic_helper_sro_readout_crtcs_state(dev, state, commit); + if (ret) + goto err_state_free; + + ret = drm_atomic_helper_sro_readout_planes_state(dev, state, commit); + if (ret) + goto err_state_free; + + ret = drm_atomic_helper_sro_readout_connectors_state(dev, state, + commit); + if (ret) + goto err_state_free; + + ret = drm_atomic_helper_sro_readout_bridges_state(dev, state, commit); + if (ret) + goto err_state_free; + + ret = drm_atomic_helper_sro_readout_private_objs_state(dev, state, + commit); + if (ret) + goto err_state_free; + + drm_atomic_sro_state_print(state, &p); + + return state; + +err_state_free: + drm_atomic_sro_state_free(state); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(drm_atomic_helper_sro_build_state); + +/** + * drm_atomic_helper_sro_readout_state - default &drm_mode_config_funcs.atomic_sro_readout_state implementation + * @dev: DRM device to read out state for + * + * Checks if the device supports hardware state readout, builds the SRO + * state via &drm_mode_config_helper_funcs.atomic_sro_build_state, + * installs it as the current state of all DRM objects, and frees the + * SRO container. + * + * The caller must hold all the modeset locks of @dev, as + * drm_mode_config_create_initial_state(), the usual caller, does. + * + * RETURNS: + * + * 0 on success, -ENOTSUPP if the device does not support readout, a + * negative error code otherwise. + */ +int drm_atomic_helper_sro_readout_state(struct drm_device *dev) +{ + const struct drm_mode_config_helper_funcs *funcs = + dev->mode_config.helper_private; + struct drm_atomic_sro_state *state; + struct drm_colorop *colorop; + + if (!drm_atomic_sro_device_can_readout(dev)) { + drm_info(dev, "Device doesn't support hardware state readout."); + return -ENOTSUPP; + } + + state = funcs->atomic_sro_build_state(dev, NULL); + if (IS_ERR(state)) + return PTR_ERR(state); + + /* TODO: Add colorop state readout support */ + drm_for_each_colorop(colorop, dev) { + struct drm_colorop_state *colorop_state; + + colorop_state = drm_atomic_helper_colorop_create_state(colorop); + if (IS_ERR(colorop_state)) { + drm_atomic_sro_state_free(state); + return PTR_ERR(colorop_state); + } + + colorop->state = colorop_state; + } + + drm_atomic_sro_install_state(state); + drm_atomic_sro_state_free(state); + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_sro_readout_state); diff --git a/include/drm/drm_atomic_state_readout_helper.h b/include/drm/drm_atomic_state_readout_helper.h new file mode 100644 index 000000000000..d685644ec25a --- /dev/null +++ b/include/drm/drm_atomic_state_readout_helper.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef DRM_ATOMIC_SRO_HELPER_H_ +#define DRM_ATOMIC_SRO_HELPER_H_ + +struct drm_atomic_commit; +struct drm_atomic_sro_state; +struct drm_device; + +int +drm_atomic_helper_sro_readout_planes_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit); +int +drm_atomic_helper_sro_readout_crtcs_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit); +int +drm_atomic_helper_sro_readout_connectors_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit); +int +drm_atomic_helper_sro_readout_bridges_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit); +int +drm_atomic_helper_sro_readout_private_objs_state(struct drm_device *dev, + struct drm_atomic_sro_state *state, + struct drm_atomic_commit *commit); +struct drm_atomic_sro_state * +drm_atomic_helper_sro_build_state(struct drm_device *dev, + struct drm_atomic_commit *commit); +int drm_atomic_helper_sro_readout_state(struct drm_device *dev); + +#endif /* DRM_ATOMIC_SRO_HELPER_H_ */ diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 6858f0052637..e72f4f781df8 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -1621,4 +1621,7 @@ struct drm_mode_config_helper_funcs { * commit, since its locks aren't held. * + * The default implementation is + * drm_atomic_helper_sro_build_state(). + * * RETURNS: * -- 2.55.0
