On Tue, May 19, 2026 at 12:37:47PM +0200, Luca Ceresoli wrote:
> For bridge hotplug we need to successfully probe a card with an incomplete
> bridge chain, i.e. a chain whose last bridge currently in bridge_chain
> needs a next_bridge to work. Such a card would have no connector, and be
> able to add one as soon as the followong bridges are added up to the tail
> bridge (e.g. a panel_bridge or a connector_bridge).
> 
> Currently common DRM code is unable to tell whether the last bridge
> currently in the chain is the tail bridge (= the pipeline is complete) or
> not.
> 
> Add drm_bridge_is_tail(), and a .is_tail func for it to rely on, so common
> code can know whether a bridge is a tail bridge or needs a next_bridge.
> 
> Signed-off-by: Luca Ceresoli <[email protected]>
> ---
>  drivers/gpu/drm/drm_bridge.c | 28 ++++++++++++++++++++++++++++
>  include/drm/drm_bridge.h     | 19 +++++++++++++++++++
>  2 files changed, 47 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index c62d17e84d4f..2b539c9749a6 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -646,6 +646,34 @@ void drm_bridge_detach(struct drm_bridge *bridge)
>       drm_bridge_put(bridge);
>  }
>  
> +/**
> + * drm_bridge_is_tail - check whether the bridge is the last required to
> + *                      have a full pipeline
> + * @bridge: the bridge to check
> + *
> + * Tell whether this is a tail bridge, i.e. a bridge that does not need a
> + * next bridge to work. E.g. a panel_bridge is final, a DSI-to-LVDS bridge
> + * is not.
> + *
> + * In case of hotplug the last bridge currently in the chain (as in
> + * drm_bridge_chain_get_last_bridge()) might not be final, and be waiting
> + * for a pipeline tail to be connected.
> + *
> + * Return: true if this bridge does not need a next bridge to work, false
> + * otherwise
> + */
> +bool drm_bridge_is_tail(struct drm_bridge *bridge)
> +{
> +     if (!(bridge->ops & DRM_BRIDGE_OP_IS_TAIL)) {
> +             drm_warn_once(bridge->dev, "is_tail func not implemented by 
> bridge %ps!",
> +                           bridge->funcs);
> +             return false;
> +     }
> +
> +     return bridge->funcs->is_tail(bridge);
> +}
> +EXPORT_SYMBOL(drm_bridge_is_tail);
> +
>  /**
>   * DOC: bridge operations
>   *
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 4ba3a5deef9a..d783a6fb93a0 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -78,6 +78,19 @@ struct drm_bridge_funcs {
>       int (*attach)(struct drm_bridge *bridge, struct drm_encoder *encoder,
>                     enum drm_bridge_attach_flags flags);
>  
> +     /**
> +      * @is_tail:
> +      *
> +      * Returns true if this is a tail bridge, i.e. it does not need a
> +      * next bridge to work. E.g. a panel_bridge is a tail bridge, a
> +      * DSI-to-LVDS bridge is not a tail bridge (no matter whether the
> +      * next bridge is present or not).

Why a DSI-to-LDVS bridge isn't a tail bridge? It only needs a panel
next, right?

> +      * The @is_tail callback is optional but it is required if the
> +      * bridge is part of a pipeline with hot-pluggable components.
> +      */
> +     bool (*is_tail)(struct drm_bridge *bridge);
> +

I don't think that's the right way to think about it, if only because
you never really know at the driver level if you're supposed to be last
or not. A DSI-to-LVDS bridge might just as well be chained with an
LVDS-to-eDP bridge, or feed the panel directly without any additional
bridge.

I *think* that what you're trying to find out here is whether the chain
is complete or not. I think you can get the same information by checking
whether you have a connector for that bridge chain. If you don't, you
know the chain isn't complete, and if you do, it's supposed to be.
DRM_BRIDGE_ATTACH_NO_CONNECTOR could be useful too, because if all you
bridges support it but there's no connector, there's something wrong.

Anyway.

Maxime

>       /**
>        * @destroy:
>        *
> @@ -1092,6 +1105,11 @@ enum drm_bridge_ops {
>        * &drm_bridge_funcs->hdmi_clear_spd_infoframe callbacks.
>        */
>       DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME = BIT(10),
> +     /**
> +      * @DRM_BRIDGE_OP_IS_TAIL: The bridge implements the
> +      * &drm_bridge_funcs->is_tail callback.
> +      */
> +     DRM_BRIDGE_OP_IS_TAIL = BIT(11),
>  };

That part is confusing to me. This is meant for drm_bridge_connector,
but since we need to handle the case where we don't have a connector
(and thus no drm_bridge_connector) I don't think this should be used at
all?

Maxime

Attachment: signature.asc
Description: PGP signature

Reply via email to