diff mbox series

[v7,06/54] drm/bridge: Improve overview documentation

Message ID 20200222150106.22919-7-laurent.pinchart@ideasonboard.com (mailing list archive)
State New, archived
Headers show
Series drm/omap: Replace custom display drivers with drm_bridge and drm_panel | expand

Commit Message

Laurent Pinchart Feb. 22, 2020, 3 p.m. UTC
Clean up the drm_bridge overview documentation, and expand the
operations documentation to provide more details on API usage.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 Documentation/gpu/drm-kms-helpers.rst |  6 +--
 drivers/gpu/drm/drm_bridge.c          | 76 ++++++++++++++++++++-------
 2 files changed, 60 insertions(+), 22 deletions(-)

Comments

Daniel Vetter Feb. 22, 2020, 3:32 p.m. UTC | #1
On Sat, Feb 22, 2020 at 4:01 PM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Clean up the drm_bridge overview documentation, and expand the
> operations documentation to provide more details on API usage.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  Documentation/gpu/drm-kms-helpers.rst |  6 +--
>  drivers/gpu/drm/drm_bridge.c          | 76 ++++++++++++++++++++-------
>  2 files changed, 60 insertions(+), 22 deletions(-)
>
> diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
> index 9668a7fe2408..fe155c6ae175 100644
> --- a/Documentation/gpu/drm-kms-helpers.rst
> +++ b/Documentation/gpu/drm-kms-helpers.rst
> @@ -139,11 +139,11 @@ Overview
>  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
>     :doc: overview
>
> -Default bridge callback sequence
> ---------------------------------
> +Bridge Operations
> +-----------------
>
>  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> -   :doc: bridge callbacks
> +   :doc: bridge operations
>
>
>  Bridge Helper Reference
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 68ab933ee430..5f55a9e17a7c 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -39,25 +39,36 @@
>   * encoder chain.
>   *
>   * A bridge is always attached to a single &drm_encoder at a time, but can be
> - * either connected to it directly, or through an intermediate bridge::
> + * either connected to it directly, or through a chain of bridges::
>   *
> - *     encoder ---> bridge B ---> bridge A
> + *     [ CRTC ---> ] Encoder ---> Bridge A ---> Bridge B
>   *
> - * Here, the output of the encoder feeds to bridge B, and that furthers feeds to
> - * bridge A.
> + * Here, the output of the encoder feeds to bridge A, and that furthers feeds to
> + * bridge B. Bridge chains can be arbitrarily long, and shall be fully linear:
> + * Chaining multiple bridges to the output of a bridge, or the same bridge to
> + * the output of different bridges, is not supported.
>   *
> - * The driver using the bridge is responsible to make the associations between
> - * the encoder and bridges. Once these links are made, the bridges will
> - * participate along with encoder functions to perform mode_set/enable/disable
> - * through the ops provided in &drm_bridge_funcs.
> + * Display drivers are responsible for linking encoders with the first bridge
> + * in the chains. This is done by acquiring the appropriate bridge with
> + * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for a
> + * panel with drm_panel_bridge_add_typed() (or the managed version
> + * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
> + * attached to the encoder with a call to drm_bridge_attach().
>   *
> - * drm_bridge, like drm_panel, aren't drm_mode_object entities like planes,
> + * Bridges are responsible for linking themselves with the next bridge in the
> + * chain, if any. This is done the same way as for encoders, with the call to
> + * drm_bridge_attach() occurring in the &drm_bridge_funcs.attach operation.
> + *
> + * Once these links are created, the bridges will automatically participate
> + * along with encoder functions to perform mode setting, enable and disable
> + * through the corresponding operations provided in &drm_bridge_funcs. This
> + * requires no intervention from display drivers.

This is not quite correct, since this fully automatic behaviour only
happens if you're using the drm_atomic_helper_modeset_disables and
drm_atomic_helper_modeset_enables functions. If you roll your own
(which is totally fine, that's why atomic helpers are modular), you
need to call the relevant bridge functions yourself. I think would be
good to clarify that and add links to the relevant bridge functions in
a sentence here too. At least the bridge chain functions involved in
this modeset stuff. Also, probe side only happens if you use
drm_atomic_helper_check_modeset(), good to mention that too and the
set of relevant bridge chain helpers for ti.

> + * &drm_bridge, like &drm_panel, aren't &drm_mode_object entities like planes,
>   * CRTCs, encoders or connectors and hence are not visible to userspace. They
>   * just provide additional hooks to get the desired output at the end of the
>   * encoder chain.
>   *
> - * Bridges can also be chained up using the &drm_bridge.chain_node field.
> - *
>   * Both legacy CRTC helpers and the new atomic modeset helpers support bridges.
>   */
>
> @@ -212,14 +223,41 @@ void drm_bridge_detach(struct drm_bridge *bridge)
>  }
>
>  /**
> - * DOC: bridge callbacks
> - *
> - * The &drm_bridge_funcs ops are populated by the bridge driver. The DRM
> - * internals (atomic and CRTC helpers) use the helpers defined in drm_bridge.c
> - * These helpers call a specific &drm_bridge_funcs op for all the bridges
> - * during encoder configuration.
> - *
> - * For detailed specification of the bridge callbacks see &drm_bridge_funcs.
> + * DOC: bridge operations
> + *
> + * Bridge drivers expose operations through the &drm_bridge_funcs structure.
> + * The DRM internals (atomic and CRTC helpers) use the helpers defined in
> + * drm_bridge.c to call bridge operations. Those operations are divided in
> + * two big categories to support different parts of the bridge usage.
> + *
> + * - The encoder-related operations support control of the bridges in the
> + *   chain, and are roughly counterparts to the &drm_encoder_helper_funcs
> + *   operations. They are used by the legacy CRTC and the atomic modeset
> + *   helpers to perform mode validation, fixup and setting, and enable and
> + *   disable the bridge automatically.
> + *
> + *   The enable and disable operations are split in
> + *   &drm_bridge_funcs.pre_enable, &drm_bridge_funcs.enable,
> + *   &drm_bridge_funcs.disable and &drm_bridge_funcs.post_disable to provide
> + *   finer-grained control.
> + *
> + *   Bridge drivers may implement the legacy version of those operations, or
> + *   the atomic version (prefixed with atomic\_), in which case they shall also
> + *   implement the atomic state bookkeeping operations
> + *   (&drm_bridge_funcs.atomic_duplicate_state,
> + *   &drm_bridge_funcs.atomic_destroy_state and &drm_bridge_funcs.reset).
> + *   Mixing atomic and non-atomic versions of the operations is not supported.
> + *
> + * - The bus format negotiation operations
> + *   &drm_bridge_funcs.atomic_get_output_bus_fmts and
> + *   &drm_bridge_funcs.atomic_get_input_bus_fmts allow bridge drivers to
> + *   negotiate the formats transmitted between bridges in the chain when
> + *   multiple formats are supported. Negotiation for formats is performed
> + *   transparently for display drivers by the atomic modeset helpers. Only
> + *   atomic versions of those operations exist, bridge drivers that need to
> + *   implement them shall thus also implement the atomic version of the
> + *   encoder-related operations. This feature is not supported by the legacy
> + *   CRTC helpers.
>   */

With the one gap/slight incorrectness addressed:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Thanks a lot for keeping our docs relevant!

Cheers, Daniel

>
>  /**
> --
> Regards,
>
> Laurent Pinchart
>
Laurent Pinchart Feb. 22, 2020, 3:34 p.m. UTC | #2
Hi Daniel,

On Sat, Feb 22, 2020 at 04:32:58PM +0100, Daniel Vetter wrote:
> On Sat, Feb 22, 2020 at 4:01 PM Laurent Pinchart wrote:
> >
> > Clean up the drm_bridge overview documentation, and expand the
> > operations documentation to provide more details on API usage.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  Documentation/gpu/drm-kms-helpers.rst |  6 +--
> >  drivers/gpu/drm/drm_bridge.c          | 76 ++++++++++++++++++++-------
> >  2 files changed, 60 insertions(+), 22 deletions(-)
> >
> > diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
> > index 9668a7fe2408..fe155c6ae175 100644
> > --- a/Documentation/gpu/drm-kms-helpers.rst
> > +++ b/Documentation/gpu/drm-kms-helpers.rst
> > @@ -139,11 +139,11 @@ Overview
> >  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> >     :doc: overview
> >
> > -Default bridge callback sequence
> > ---------------------------------
> > +Bridge Operations
> > +-----------------
> >
> >  .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> > -   :doc: bridge callbacks
> > +   :doc: bridge operations
> >
> >
> >  Bridge Helper Reference
> > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> > index 68ab933ee430..5f55a9e17a7c 100644
> > --- a/drivers/gpu/drm/drm_bridge.c
> > +++ b/drivers/gpu/drm/drm_bridge.c
> > @@ -39,25 +39,36 @@
> >   * encoder chain.
> >   *
> >   * A bridge is always attached to a single &drm_encoder at a time, but can be
> > - * either connected to it directly, or through an intermediate bridge::
> > + * either connected to it directly, or through a chain of bridges::
> >   *
> > - *     encoder ---> bridge B ---> bridge A
> > + *     [ CRTC ---> ] Encoder ---> Bridge A ---> Bridge B
> >   *
> > - * Here, the output of the encoder feeds to bridge B, and that furthers feeds to
> > - * bridge A.
> > + * Here, the output of the encoder feeds to bridge A, and that furthers feeds to
> > + * bridge B. Bridge chains can be arbitrarily long, and shall be fully linear:
> > + * Chaining multiple bridges to the output of a bridge, or the same bridge to
> > + * the output of different bridges, is not supported.
> >   *
> > - * The driver using the bridge is responsible to make the associations between
> > - * the encoder and bridges. Once these links are made, the bridges will
> > - * participate along with encoder functions to perform mode_set/enable/disable
> > - * through the ops provided in &drm_bridge_funcs.
> > + * Display drivers are responsible for linking encoders with the first bridge
> > + * in the chains. This is done by acquiring the appropriate bridge with
> > + * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for a
> > + * panel with drm_panel_bridge_add_typed() (or the managed version
> > + * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
> > + * attached to the encoder with a call to drm_bridge_attach().
> >   *
> > - * drm_bridge, like drm_panel, aren't drm_mode_object entities like planes,
> > + * Bridges are responsible for linking themselves with the next bridge in the
> > + * chain, if any. This is done the same way as for encoders, with the call to
> > + * drm_bridge_attach() occurring in the &drm_bridge_funcs.attach operation.
> > + *
> > + * Once these links are created, the bridges will automatically participate
> > + * along with encoder functions to perform mode setting, enable and disable
> > + * through the corresponding operations provided in &drm_bridge_funcs. This
> > + * requires no intervention from display drivers.
> 
> This is not quite correct, since this fully automatic behaviour only
> happens if you're using the drm_atomic_helper_modeset_disables and
> drm_atomic_helper_modeset_enables functions. If you roll your own
> (which is totally fine, that's why atomic helpers are modular), you
> need to call the relevant bridge functions yourself. I think would be
> good to clarify that and add links to the relevant bridge functions in
> a sentence here too. At least the bridge chain functions involved in
> this modeset stuff. Also, probe side only happens if you use
> drm_atomic_helper_check_modeset(), good to mention that too and the
> set of relevant bridge chain helpers for ti.

Very good point, I'll fix this in v7.1.

> > + * &drm_bridge, like &drm_panel, aren't &drm_mode_object entities like planes,
> >   * CRTCs, encoders or connectors and hence are not visible to userspace. They
> >   * just provide additional hooks to get the desired output at the end of the
> >   * encoder chain.
> >   *
> > - * Bridges can also be chained up using the &drm_bridge.chain_node field.
> > - *
> >   * Both legacy CRTC helpers and the new atomic modeset helpers support bridges.
> >   */
> >
> > @@ -212,14 +223,41 @@ void drm_bridge_detach(struct drm_bridge *bridge)
> >  }
> >
> >  /**
> > - * DOC: bridge callbacks
> > - *
> > - * The &drm_bridge_funcs ops are populated by the bridge driver. The DRM
> > - * internals (atomic and CRTC helpers) use the helpers defined in drm_bridge.c
> > - * These helpers call a specific &drm_bridge_funcs op for all the bridges
> > - * during encoder configuration.
> > - *
> > - * For detailed specification of the bridge callbacks see &drm_bridge_funcs.
> > + * DOC: bridge operations
> > + *
> > + * Bridge drivers expose operations through the &drm_bridge_funcs structure.
> > + * The DRM internals (atomic and CRTC helpers) use the helpers defined in
> > + * drm_bridge.c to call bridge operations. Those operations are divided in
> > + * two big categories to support different parts of the bridge usage.
> > + *
> > + * - The encoder-related operations support control of the bridges in the
> > + *   chain, and are roughly counterparts to the &drm_encoder_helper_funcs
> > + *   operations. They are used by the legacy CRTC and the atomic modeset
> > + *   helpers to perform mode validation, fixup and setting, and enable and
> > + *   disable the bridge automatically.
> > + *
> > + *   The enable and disable operations are split in
> > + *   &drm_bridge_funcs.pre_enable, &drm_bridge_funcs.enable,
> > + *   &drm_bridge_funcs.disable and &drm_bridge_funcs.post_disable to provide
> > + *   finer-grained control.
> > + *
> > + *   Bridge drivers may implement the legacy version of those operations, or
> > + *   the atomic version (prefixed with atomic\_), in which case they shall also
> > + *   implement the atomic state bookkeeping operations
> > + *   (&drm_bridge_funcs.atomic_duplicate_state,
> > + *   &drm_bridge_funcs.atomic_destroy_state and &drm_bridge_funcs.reset).
> > + *   Mixing atomic and non-atomic versions of the operations is not supported.
> > + *
> > + * - The bus format negotiation operations
> > + *   &drm_bridge_funcs.atomic_get_output_bus_fmts and
> > + *   &drm_bridge_funcs.atomic_get_input_bus_fmts allow bridge drivers to
> > + *   negotiate the formats transmitted between bridges in the chain when
> > + *   multiple formats are supported. Negotiation for formats is performed
> > + *   transparently for display drivers by the atomic modeset helpers. Only
> > + *   atomic versions of those operations exist, bridge drivers that need to
> > + *   implement them shall thus also implement the atomic version of the
> > + *   encoder-related operations. This feature is not supported by the legacy
> > + *   CRTC helpers.
> >   */
> 
> With the one gap/slight incorrectness addressed:
> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> Thanks a lot for keeping our docs relevant!

My (sometimes slightly masochistic) pleasure :-)
diff mbox series

Patch

diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index 9668a7fe2408..fe155c6ae175 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -139,11 +139,11 @@  Overview
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
    :doc: overview
 
-Default bridge callback sequence
---------------------------------
+Bridge Operations
+-----------------
 
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
-   :doc: bridge callbacks
+   :doc: bridge operations
 
 
 Bridge Helper Reference
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 68ab933ee430..5f55a9e17a7c 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -39,25 +39,36 @@ 
  * encoder chain.
  *
  * A bridge is always attached to a single &drm_encoder at a time, but can be
- * either connected to it directly, or through an intermediate bridge::
+ * either connected to it directly, or through a chain of bridges::
  *
- *     encoder ---> bridge B ---> bridge A
+ *     [ CRTC ---> ] Encoder ---> Bridge A ---> Bridge B
  *
- * Here, the output of the encoder feeds to bridge B, and that furthers feeds to
- * bridge A.
+ * Here, the output of the encoder feeds to bridge A, and that furthers feeds to
+ * bridge B. Bridge chains can be arbitrarily long, and shall be fully linear:
+ * Chaining multiple bridges to the output of a bridge, or the same bridge to
+ * the output of different bridges, is not supported.
  *
- * The driver using the bridge is responsible to make the associations between
- * the encoder and bridges. Once these links are made, the bridges will
- * participate along with encoder functions to perform mode_set/enable/disable
- * through the ops provided in &drm_bridge_funcs.
+ * Display drivers are responsible for linking encoders with the first bridge
+ * in the chains. This is done by acquiring the appropriate bridge with
+ * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for a
+ * panel with drm_panel_bridge_add_typed() (or the managed version
+ * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
+ * attached to the encoder with a call to drm_bridge_attach().
  *
- * drm_bridge, like drm_panel, aren't drm_mode_object entities like planes,
+ * Bridges are responsible for linking themselves with the next bridge in the
+ * chain, if any. This is done the same way as for encoders, with the call to
+ * drm_bridge_attach() occurring in the &drm_bridge_funcs.attach operation.
+ *
+ * Once these links are created, the bridges will automatically participate
+ * along with encoder functions to perform mode setting, enable and disable
+ * through the corresponding operations provided in &drm_bridge_funcs. This
+ * requires no intervention from display drivers.
+ *
+ * &drm_bridge, like &drm_panel, aren't &drm_mode_object entities like planes,
  * CRTCs, encoders or connectors and hence are not visible to userspace. They
  * just provide additional hooks to get the desired output at the end of the
  * encoder chain.
  *
- * Bridges can also be chained up using the &drm_bridge.chain_node field.
- *
  * Both legacy CRTC helpers and the new atomic modeset helpers support bridges.
  */
 
@@ -212,14 +223,41 @@  void drm_bridge_detach(struct drm_bridge *bridge)
 }
 
 /**
- * DOC: bridge callbacks
- *
- * The &drm_bridge_funcs ops are populated by the bridge driver. The DRM
- * internals (atomic and CRTC helpers) use the helpers defined in drm_bridge.c
- * These helpers call a specific &drm_bridge_funcs op for all the bridges
- * during encoder configuration.
- *
- * For detailed specification of the bridge callbacks see &drm_bridge_funcs.
+ * DOC: bridge operations
+ *
+ * Bridge drivers expose operations through the &drm_bridge_funcs structure.
+ * The DRM internals (atomic and CRTC helpers) use the helpers defined in
+ * drm_bridge.c to call bridge operations. Those operations are divided in
+ * two big categories to support different parts of the bridge usage.
+ *
+ * - The encoder-related operations support control of the bridges in the
+ *   chain, and are roughly counterparts to the &drm_encoder_helper_funcs
+ *   operations. They are used by the legacy CRTC and the atomic modeset
+ *   helpers to perform mode validation, fixup and setting, and enable and
+ *   disable the bridge automatically.
+ *
+ *   The enable and disable operations are split in
+ *   &drm_bridge_funcs.pre_enable, &drm_bridge_funcs.enable,
+ *   &drm_bridge_funcs.disable and &drm_bridge_funcs.post_disable to provide
+ *   finer-grained control.
+ *
+ *   Bridge drivers may implement the legacy version of those operations, or
+ *   the atomic version (prefixed with atomic\_), in which case they shall also
+ *   implement the atomic state bookkeeping operations
+ *   (&drm_bridge_funcs.atomic_duplicate_state,
+ *   &drm_bridge_funcs.atomic_destroy_state and &drm_bridge_funcs.reset).
+ *   Mixing atomic and non-atomic versions of the operations is not supported.
+ *
+ * - The bus format negotiation operations
+ *   &drm_bridge_funcs.atomic_get_output_bus_fmts and
+ *   &drm_bridge_funcs.atomic_get_input_bus_fmts allow bridge drivers to
+ *   negotiate the formats transmitted between bridges in the chain when
+ *   multiple formats are supported. Negotiation for formats is performed
+ *   transparently for display drivers by the atomic modeset helpers. Only
+ *   atomic versions of those operations exist, bridge drivers that need to
+ *   implement them shall thus also implement the atomic version of the
+ *   encoder-related operations. This feature is not supported by the legacy
+ *   CRTC helpers.
  */
 
 /**