From 751465913f045a1120188ec91ed46d90ea5fd539 Mon Sep 17 00:00:00 2001 From: Boris Brezillon <boris.brezillon@collabora.com> Date: Tue, 28 Jan 2020 14:55:03 +0100 Subject: 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 --- include/drm/drm_atomic.h | 34 ++++++++++++++++++++ include/drm/drm_atomic_state_helper.h | 13 ++++++++ include/drm/drm_bridge.h | 60 +++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) (limited to 'include') diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 951dfb15c27b..82a888769b3d 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -669,6 +669,9 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state, return plane->state; } +int __must_check +drm_atomic_add_encoder_bridges(struct drm_atomic_state *state, + struct drm_encoder *encoder); int __must_check drm_atomic_add_affected_connectors(struct drm_atomic_state *state, struct drm_crtc *crtc); @@ -992,4 +995,35 @@ drm_atomic_crtc_effectively_active(const struct drm_crtc_state *state) return state->active || state->self_refresh_active; } +/** + * struct drm_bridge_state - Atomic bridge state object + */ +struct drm_bridge_state { + /** + * @base: inherit from &drm_private_state + */ + struct drm_private_state base; + + /** + * @bridge: the bridge this state refers to + */ + struct drm_bridge *bridge; +}; + +static inline struct drm_bridge_state * +drm_priv_to_bridge_state(struct drm_private_state *priv) +{ + return container_of(priv, struct drm_bridge_state, base); +} + +struct drm_bridge_state * +drm_atomic_get_bridge_state(struct drm_atomic_state *state, + struct drm_bridge *bridge); +struct drm_bridge_state * +drm_atomic_get_old_bridge_state(struct drm_atomic_state *state, + struct drm_bridge *bridge); +struct drm_bridge_state * +drm_atomic_get_new_bridge_state(struct drm_atomic_state *state, + struct drm_bridge *bridge); + #endif /* DRM_ATOMIC_H_ */ diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index 8171dea4cc22..3f8f1d627f7c 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -26,6 +26,8 @@ #include <linux/types.h> +struct drm_bridge; +struct drm_bridge_state; struct drm_crtc; struct drm_crtc_state; struct drm_plane; @@ -80,3 +82,14 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state); void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, struct drm_private_state *state); + +void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge, + struct drm_bridge_state *state); +struct drm_bridge_state * +drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge); +void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge, + struct drm_bridge_state *state); +void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge, + struct drm_bridge_state *state); +struct drm_bridge_state * +drm_atomic_helper_bridge_reset(struct drm_bridge *bridge); diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 694e153a7531..8883dcfe63cb 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -25,6 +25,8 @@ #include <linux/list.h> #include <linux/ctype.h> + +#include <drm/drm_atomic.h> #include <drm/drm_encoder.h> #include <drm/drm_mode_object.h> #include <drm/drm_modes.h> @@ -338,6 +340,56 @@ struct drm_bridge_funcs { */ void (*atomic_post_disable)(struct drm_bridge *bridge, struct drm_atomic_state *old_state); + + /** + * @atomic_duplicate_state: + * + * Duplicate the current bridge state object (which is guaranteed to be + * non-NULL). + * + * The atomic_duplicate_state() is optional. When not implemented the + * core allocates a drm_bridge_state object and calls + * &__drm_atomic_helper_bridge_duplicate_state() to initialize it. + * + * RETURNS: + * A valid drm_bridge_state object or NULL if the allocation fails. + */ + struct drm_bridge_state *(*atomic_duplicate_state)(struct drm_bridge *bridge); + + /** + * @atomic_destroy_state: + * + * Destroy a bridge state object previously allocated by + * &drm_bridge_funcs.atomic_duplicate_state(). + * + * The atomic_destroy_state hook is optional. When not implemented the + * core calls kfree() on the state. + */ + void (*atomic_destroy_state)(struct drm_bridge *bridge, + struct drm_bridge_state *state); + + /** + * @atomic_reset: + * + * Reset the bridge to a predefined state (or retrieve its current + * state) and return a &drm_bridge_state object matching this state. + * This function is called at attach time. + * + * The atomic_reset hook is mandatory if the bridge implements any of + * the atomic hooks, and should be left unassigned otherwise. + * + * Note that the atomic_reset() semantics is not exactly matching the + * reset() semantics found on other components (connector, plane, ...). + * 1/ The reset operation happens when the bridge is attached, not when + * drm_mode_config_reset() is called + * 2/ It's meant to be used exclusively on bridges that have been + * converted to the ATOMIC API + * + * RETURNS: + * A valid drm_bridge_state object in case of success, an ERR_PTR() + * giving the reason of the failure otherwise. + */ + struct drm_bridge_state *(*atomic_reset)(struct drm_bridge *bridge); }; /** @@ -380,6 +432,8 @@ struct drm_bridge_timings { * struct drm_bridge - central DRM bridge control structure */ struct drm_bridge { + /** @base: inherit from &drm_private_object */ + struct drm_private_obj base; /** @dev: DRM device this bridge belongs to */ struct drm_device *dev; /** @encoder: encoder to which this bridge is connected */ @@ -404,6 +458,12 @@ struct drm_bridge { void *driver_private; }; +static inline struct drm_bridge * +drm_priv_to_bridge(struct drm_private_obj *priv) +{ + return container_of(priv, struct drm_bridge, base); +} + void drm_bridge_add(struct drm_bridge *bridge); void drm_bridge_remove(struct drm_bridge *bridge); struct drm_bridge *of_drm_find_bridge(struct device_node *np); -- cgit