diff options
author | Boris Brezillon <boris.brezillon@collabora.com> | 2020-01-28 14:55:03 +0100 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@collabora.com> | 2020-01-31 16:00:21 +0100 |
commit | 751465913f045a1120188ec91ed46d90ea5fd539 (patch) | |
tree | a22279887d908e0749e22bf4ab1260ad187fab95 /drivers/gpu/drm/drm_atomic.c | |
parent | 6d598a32ed871ee7ddb9612a3bdc8f3f1febea33 (diff) |
drm/bridge: Add a drm_bridge_state object
One of the last remaining objects to not have its atomic state.
This is being motivated by our attempt to support runtime bus-format
negotiation between elements of the bridge chain.
This patch just paves the road for such a feature by adding a new
drm_bridge_state object inheriting from drm_private_obj so we can
re-use some of the existing state initialization/tracking logic.
v10:
* Add changelog to the commit message
v9:
* Clarify the fact that the bridge->atomic_reset() and
{connector,plane,crtc,...}->reset() semantics are different
* Move the drm_atomic_private_obj_init() call back to
drm_bridge_attach()
* Check the presence of ->atomic_duplicate_state instead of
->atomic_reset in drm_atomic_add_encoder_bridges()
* Fix copy&paste errors in the atomic bridge state helpers doc
* Add A-b/R-b tags
v8:
* Move bridge state helpers out of the CONFIG_DEBUGFS section
v7:
* Move helpers, struct-defs, ... to atomic helper files to avoid the
drm -> drm_kms_helper -> drm circular dep
* Stop providing default implementation for atomic state reset,
duplicate and destroy hooks (has to do with the helper/core split)
* Drop all R-b/T-b as helpers have now be moved to other places
v6:
* Made helpers private, removed doc and moved them to satisfy dependencies
* Renamed helpers to _default_
v5:
* Re-introduced the helpers from v4
v4:
* Fix the doc
* Kill default helpers (inlined)
* Fix drm_atomic_get_bridge_state() to check for an ERR_PTR()
* Add Neil's R-b
v3:
* No changes
v2:
* Use drm_for_each_bridge_in_chain()
* Rename helpers to be more consistent with the rest of the DRM API
* Improve/fix the doc
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20200128135514.108171-2-boris.brezillon@collabora.com
Diffstat (limited to 'drivers/gpu/drm/drm_atomic.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index d33691512a8e..65c46ed049c5 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -30,6 +30,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_bridge.h> #include <drm/drm_debugfs.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> @@ -1018,6 +1019,121 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, } /** + * drm_atomic_get_bridge_state - get bridge state + * @state: global atomic state object + * @bridge: bridge to get state object for + * + * This function returns the bridge state for the given bridge, allocating it + * if needed. It will also grab the relevant bridge lock to make sure that the + * state is consistent. + * + * Returns: + * + * Either the allocated state or the error code encoded into the pointer. When + * the error is EDEADLK then the w/w mutex code has detected a deadlock and the + * entire atomic sequence must be restarted. + */ +struct drm_bridge_state * +drm_atomic_get_bridge_state(struct drm_atomic_state *state, + struct drm_bridge *bridge) +{ + struct drm_private_state *obj_state; + + obj_state = drm_atomic_get_private_obj_state(state, &bridge->base); + if (IS_ERR(obj_state)) + return ERR_CAST(obj_state); + + return drm_priv_to_bridge_state(obj_state); +} +EXPORT_SYMBOL(drm_atomic_get_bridge_state); + +/** + * drm_atomic_get_old_bridge_state - get old bridge state, if it exists + * @state: global atomic state object + * @bridge: bridge to grab + * + * This function returns the old bridge state for the given bridge, or NULL if + * the bridge is not part of the global atomic state. + */ +struct drm_bridge_state * +drm_atomic_get_old_bridge_state(struct drm_atomic_state *state, + struct drm_bridge *bridge) +{ + struct drm_private_state *obj_state; + + obj_state = drm_atomic_get_old_private_obj_state(state, &bridge->base); + if (!obj_state) + return NULL; + + return drm_priv_to_bridge_state(obj_state); +} +EXPORT_SYMBOL(drm_atomic_get_old_bridge_state); + +/** + * drm_atomic_get_new_bridge_state - get new bridge state, if it exists + * @state: global atomic state object + * @bridge: bridge to grab + * + * This function returns the new bridge state for the given bridge, or NULL if + * the bridge is not part of the global atomic state. + */ +struct drm_bridge_state * +drm_atomic_get_new_bridge_state(struct drm_atomic_state *state, + struct drm_bridge *bridge) +{ + struct drm_private_state *obj_state; + + obj_state = drm_atomic_get_new_private_obj_state(state, &bridge->base); + if (!obj_state) + return NULL; + + return drm_priv_to_bridge_state(obj_state); +} +EXPORT_SYMBOL(drm_atomic_get_new_bridge_state); + +/** + * drm_atomic_add_encoder_bridges - add bridges attached to an encoder + * @state: atomic state + * @encoder: DRM encoder + * + * This function adds all bridges attached to @encoder. This is needed to add + * bridge states to @state and make them available when + * &bridge_funcs.atomic_{check,pre_enable,enable,disable_post_disable}() are + * called + * + * Returns: + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK + * then the w/w mutex code has detected a deadlock and the entire atomic + * sequence must be restarted. All other errors are fatal. + */ +int +drm_atomic_add_encoder_bridges(struct drm_atomic_state *state, + struct drm_encoder *encoder) +{ + struct drm_bridge_state *bridge_state; + struct drm_bridge *bridge; + + if (!encoder) + return 0; + + DRM_DEBUG_ATOMIC("Adding all bridges for [encoder:%d:%s] to %p\n", + encoder->base.id, encoder->name, state); + + drm_for_each_bridge_in_chain(encoder, bridge) { + /* Skip bridges that don't implement the atomic state hooks. */ + if (!bridge->funcs->atomic_duplicate_state) + continue; + + bridge_state = drm_atomic_get_bridge_state(state, bridge); + if (IS_ERR(bridge_state)) + return PTR_ERR(bridge_state); + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_add_encoder_bridges); + +/** * drm_atomic_add_affected_connectors - add connectors for CRTC * @state: atomic state * @crtc: DRM CRTC |