On Tue, Sep 02, 2025 at 10:32:38AM +0200, Maxime Ripard wrote:
> In order to enable drivers to fill their initial state from the hardware
> state, we need to provide an alternative atomic_reset helper.
>
> This helper relies on each state having its own atomic_state_readout()
> hooks. Each component will thus be able to fill the initial state based
> on what they can figure out from the hardware.
>
> It also allocates a dummy drm_atomic_state to glue the whole thing
> together so atomic_state_readout implementations can still figure out
> the state of other related entities.
>
> Link:
> https://lore.kernel.org/dri-devel/CAKMK7uHtqHy_oz4W7F+hmp9iqp7W5Ra8CxPvJ=9bwmvfu-o...@mail.gmail.com/
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> drivers/gpu/drm/drm_atomic_helper.c | 382
> ++++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/drm_mode_config.c | 1 +
> include/drm/drm_atomic_helper.h | 1 +
> include/drm/drm_bridge.h | 21 ++
> include/drm/drm_connector.h | 26 +++
> include/drm/drm_crtc.h | 19 ++
> include/drm/drm_plane.h | 27 +++
> 7 files changed, 477 insertions(+)
>
> + drm_for_each_encoder(encoder, dev) {
> + struct drm_connector_state *enc_conn_state;
> + struct drm_crtc_state *enc_crtc_state;
> + struct drm_bridge *bridge;
> +
> + /*
> + * It works a bit differently for bridges. Because they are
> + * using a drm_private_state, and because
> + * drm_atomic_private_obj_init() asks for its initial state when
> + * initializing, instead of doing it later on through a reset
> + * call like the other entities, we can't have reset xor
> + * readout.
Would it make sense to unify the way the bridges / priv_obj handle the
state with the rest of the object types?
> + *
> + * We'll need a mandatory reset to create that initial, blank,
> + * state, and then readout will fill that state later on if the
> + * driver implements it.
> + *
> + * This also means we don't need to call the readout state
> + * function if we don't have the bridge enabled (ie, if no
> + * drm_connector_state->best_encoder points to bridge->encoder,
> + * and / or if drm_connector_state->crtc is NULL).
> + *
> + * In such a case, we would get the blank state reset created
> + * during registration.
> + */
> +
> + enc_conn_state = find_connector_state_for_encoder(state,
> encoder);
> + if (!enc_conn_state)
> + continue;
> +
> + enc_crtc_state = drm_atomic_get_old_crtc_state(state,
> enc_conn_state->crtc);
> + if (!enc_crtc_state)
> + continue;
> +
> + list_for_each_entry(bridge, &encoder->bridge_chain, chain_node)
> {
> + const struct drm_bridge_funcs *bridge_funcs =
> bridge->funcs;
> + struct drm_bridge_state *bridge_state;
> +
> + bridge_state = drm_bridge_get_current_state(bridge);
> + if (WARN_ON(!bridge_state)) {
> + ret = -EINVAL;
> + goto err_state_put;
> + }
> +
> + if (bridge_funcs->atomic_readout_state) {
> + ret = bridge_funcs->atomic_readout_state(bridge,
> +
> bridge_state,
> +
> enc_crtc_state,
> +
> enc_conn_state);
> + if (WARN_ON(ret))
> + goto err_state_put;
> + }
> +
> + drm_atomic_set_old_bridge_state(state, bridge,
> bridge_state);
> + }
> + }
> +
--
With best wishes
Dmitry