LCOV - code coverage report
Current view: top level - drivers/gpu/drm/bridge - panel.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 135 0.0 %
Date: 2023-07-19 18:55:55 Functions: 0 20 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
       4             :  * Copyright (C) 2017 Broadcom
       5             :  */
       6             : 
       7             : #include <drm/drm_atomic_helper.h>
       8             : #include <drm/drm_bridge.h>
       9             : #include <drm/drm_connector.h>
      10             : #include <drm/drm_encoder.h>
      11             : #include <drm/drm_managed.h>
      12             : #include <drm/drm_modeset_helper_vtables.h>
      13             : #include <drm/drm_of.h>
      14             : #include <drm/drm_panel.h>
      15             : #include <drm/drm_print.h>
      16             : #include <drm/drm_probe_helper.h>
      17             : 
      18             : struct panel_bridge {
      19             :         struct drm_bridge bridge;
      20             :         struct drm_connector connector;
      21             :         struct drm_panel *panel;
      22             :         u32 connector_type;
      23             : };
      24             : 
      25             : static inline struct panel_bridge *
      26             : drm_bridge_to_panel_bridge(struct drm_bridge *bridge)
      27             : {
      28           0 :         return container_of(bridge, struct panel_bridge, bridge);
      29             : }
      30             : 
      31             : static inline struct panel_bridge *
      32             : drm_connector_to_panel_bridge(struct drm_connector *connector)
      33             : {
      34           0 :         return container_of(connector, struct panel_bridge, connector);
      35             : }
      36             : 
      37           0 : static int panel_bridge_connector_get_modes(struct drm_connector *connector)
      38             : {
      39           0 :         struct panel_bridge *panel_bridge =
      40             :                 drm_connector_to_panel_bridge(connector);
      41             : 
      42           0 :         return drm_panel_get_modes(panel_bridge->panel, connector);
      43             : }
      44             : 
      45             : static const struct drm_connector_helper_funcs
      46             : panel_bridge_connector_helper_funcs = {
      47             :         .get_modes = panel_bridge_connector_get_modes,
      48             : };
      49             : 
      50             : static const struct drm_connector_funcs panel_bridge_connector_funcs = {
      51             :         .reset = drm_atomic_helper_connector_reset,
      52             :         .fill_modes = drm_helper_probe_single_connector_modes,
      53             :         .destroy = drm_connector_cleanup,
      54             :         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
      55             :         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
      56             : };
      57             : 
      58           0 : static int panel_bridge_attach(struct drm_bridge *bridge,
      59             :                                enum drm_bridge_attach_flags flags)
      60             : {
      61           0 :         struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
      62           0 :         struct drm_connector *connector = &panel_bridge->connector;
      63             :         int ret;
      64             : 
      65           0 :         if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
      66             :                 return 0;
      67             : 
      68           0 :         if (!bridge->encoder) {
      69           0 :                 DRM_ERROR("Missing encoder\n");
      70           0 :                 return -ENODEV;
      71             :         }
      72             : 
      73           0 :         drm_connector_helper_add(connector,
      74             :                                  &panel_bridge_connector_helper_funcs);
      75             : 
      76           0 :         ret = drm_connector_init(bridge->dev, connector,
      77             :                                  &panel_bridge_connector_funcs,
      78           0 :                                  panel_bridge->connector_type);
      79           0 :         if (ret) {
      80           0 :                 DRM_ERROR("Failed to initialize connector\n");
      81           0 :                 return ret;
      82             :         }
      83             : 
      84           0 :         drm_panel_bridge_set_orientation(connector, bridge);
      85             : 
      86           0 :         drm_connector_attach_encoder(&panel_bridge->connector,
      87             :                                           bridge->encoder);
      88             : 
      89           0 :         if (bridge->dev->registered) {
      90           0 :                 if (connector->funcs->reset)
      91           0 :                         connector->funcs->reset(connector);
      92           0 :                 drm_connector_register(connector);
      93             :         }
      94             : 
      95             :         return 0;
      96             : }
      97             : 
      98           0 : static void panel_bridge_detach(struct drm_bridge *bridge)
      99             : {
     100           0 :         struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
     101           0 :         struct drm_connector *connector = &panel_bridge->connector;
     102             : 
     103             :         /*
     104             :          * Cleanup the connector if we know it was initialized.
     105             :          *
     106             :          * FIXME: This wouldn't be needed if the panel_bridge structure was
     107             :          * allocated with drmm_kzalloc(). This might be tricky since the
     108             :          * drm_device pointer can only be retrieved when the bridge is attached.
     109             :          */
     110           0 :         if (connector->dev)
     111           0 :                 drm_connector_cleanup(connector);
     112           0 : }
     113             : 
     114           0 : static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge,
     115             :                                 struct drm_bridge_state *old_bridge_state)
     116             : {
     117           0 :         struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
     118           0 :         struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
     119           0 :         struct drm_encoder *encoder = bridge->encoder;
     120             :         struct drm_crtc *crtc;
     121             :         struct drm_crtc_state *old_crtc_state;
     122             : 
     123           0 :         crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state, encoder);
     124           0 :         if (!crtc)
     125             :                 return;
     126             : 
     127           0 :         old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc);
     128           0 :         if (old_crtc_state && old_crtc_state->self_refresh_active)
     129             :                 return;
     130             : 
     131           0 :         drm_panel_prepare(panel_bridge->panel);
     132             : }
     133             : 
     134           0 : static void panel_bridge_atomic_enable(struct drm_bridge *bridge,
     135             :                                 struct drm_bridge_state *old_bridge_state)
     136             : {
     137           0 :         struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
     138           0 :         struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
     139           0 :         struct drm_encoder *encoder = bridge->encoder;
     140             :         struct drm_crtc *crtc;
     141             :         struct drm_crtc_state *old_crtc_state;
     142             : 
     143           0 :         crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state, encoder);
     144           0 :         if (!crtc)
     145             :                 return;
     146             : 
     147           0 :         old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc);
     148           0 :         if (old_crtc_state && old_crtc_state->self_refresh_active)
     149             :                 return;
     150             : 
     151           0 :         drm_panel_enable(panel_bridge->panel);
     152             : }
     153             : 
     154           0 : static void panel_bridge_atomic_disable(struct drm_bridge *bridge,
     155             :                                 struct drm_bridge_state *old_bridge_state)
     156             : {
     157           0 :         struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
     158           0 :         struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
     159           0 :         struct drm_encoder *encoder = bridge->encoder;
     160             :         struct drm_crtc *crtc;
     161             :         struct drm_crtc_state *new_crtc_state;
     162             : 
     163           0 :         crtc = drm_atomic_get_old_crtc_for_encoder(atomic_state, encoder);
     164           0 :         if (!crtc)
     165             :                 return;
     166             : 
     167           0 :         new_crtc_state = drm_atomic_get_new_crtc_state(atomic_state, crtc);
     168           0 :         if (new_crtc_state && new_crtc_state->self_refresh_active)
     169             :                 return;
     170             : 
     171           0 :         drm_panel_disable(panel_bridge->panel);
     172             : }
     173             : 
     174           0 : static void panel_bridge_atomic_post_disable(struct drm_bridge *bridge,
     175             :                                 struct drm_bridge_state *old_bridge_state)
     176             : {
     177           0 :         struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
     178           0 :         struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
     179           0 :         struct drm_encoder *encoder = bridge->encoder;
     180             :         struct drm_crtc *crtc;
     181             :         struct drm_crtc_state *new_crtc_state;
     182             : 
     183           0 :         crtc = drm_atomic_get_old_crtc_for_encoder(atomic_state, encoder);
     184           0 :         if (!crtc)
     185             :                 return;
     186             : 
     187           0 :         new_crtc_state = drm_atomic_get_new_crtc_state(atomic_state, crtc);
     188           0 :         if (new_crtc_state && new_crtc_state->self_refresh_active)
     189             :                 return;
     190             : 
     191           0 :         drm_panel_unprepare(panel_bridge->panel);
     192             : }
     193             : 
     194           0 : static int panel_bridge_get_modes(struct drm_bridge *bridge,
     195             :                                   struct drm_connector *connector)
     196             : {
     197           0 :         struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
     198             : 
     199           0 :         return drm_panel_get_modes(panel_bridge->panel, connector);
     200             : }
     201             : 
     202           0 : static void panel_bridge_debugfs_init(struct drm_bridge *bridge,
     203             :                                       struct dentry *root)
     204             : {
     205           0 :         struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
     206           0 :         struct drm_panel *panel = panel_bridge->panel;
     207             : 
     208           0 :         root = debugfs_create_dir("panel", root);
     209           0 :         if (panel->funcs->debugfs_init)
     210           0 :                 panel->funcs->debugfs_init(panel, root);
     211           0 : }
     212             : 
     213             : static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
     214             :         .attach = panel_bridge_attach,
     215             :         .detach = panel_bridge_detach,
     216             :         .atomic_pre_enable = panel_bridge_atomic_pre_enable,
     217             :         .atomic_enable = panel_bridge_atomic_enable,
     218             :         .atomic_disable = panel_bridge_atomic_disable,
     219             :         .atomic_post_disable = panel_bridge_atomic_post_disable,
     220             :         .get_modes = panel_bridge_get_modes,
     221             :         .atomic_reset = drm_atomic_helper_bridge_reset,
     222             :         .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
     223             :         .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
     224             :         .atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
     225             :         .debugfs_init = panel_bridge_debugfs_init,
     226             : };
     227             : 
     228             : /**
     229             :  * drm_bridge_is_panel - Checks if a drm_bridge is a panel_bridge.
     230             :  *
     231             :  * @bridge: The drm_bridge to be checked.
     232             :  *
     233             :  * Returns true if the bridge is a panel bridge, or false otherwise.
     234             :  */
     235           0 : bool drm_bridge_is_panel(const struct drm_bridge *bridge)
     236             : {
     237           0 :         return bridge->funcs == &panel_bridge_bridge_funcs;
     238             : }
     239             : EXPORT_SYMBOL(drm_bridge_is_panel);
     240             : 
     241             : /**
     242             :  * drm_panel_bridge_add - Creates a &drm_bridge and &drm_connector that
     243             :  * just calls the appropriate functions from &drm_panel.
     244             :  *
     245             :  * @panel: The drm_panel being wrapped.  Must be non-NULL.
     246             :  *
     247             :  * For drivers converting from directly using drm_panel: The expected
     248             :  * usage pattern is that during either encoder module probe or DSI
     249             :  * host attach, a drm_panel will be looked up through
     250             :  * drm_of_find_panel_or_bridge().  drm_panel_bridge_add() is used to
     251             :  * wrap that panel in the new bridge, and the result can then be
     252             :  * passed to drm_bridge_attach().  The drm_panel_prepare() and related
     253             :  * functions can be dropped from the encoder driver (they're now
     254             :  * called by the KMS helpers before calling into the encoder), along
     255             :  * with connector creation.  When done with the bridge (after
     256             :  * drm_mode_config_cleanup() if the bridge has already been attached), then
     257             :  * drm_panel_bridge_remove() to free it.
     258             :  *
     259             :  * The connector type is set to @panel->connector_type, which must be set to a
     260             :  * known type. Calling this function with a panel whose connector type is
     261             :  * DRM_MODE_CONNECTOR_Unknown will return ERR_PTR(-EINVAL).
     262             :  *
     263             :  * See devm_drm_panel_bridge_add() for an automatically managed version of this
     264             :  * function.
     265             :  */
     266           0 : struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel)
     267             : {
     268           0 :         if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
     269             :                 return ERR_PTR(-EINVAL);
     270             : 
     271           0 :         return drm_panel_bridge_add_typed(panel, panel->connector_type);
     272             : }
     273             : EXPORT_SYMBOL(drm_panel_bridge_add);
     274             : 
     275             : /**
     276             :  * drm_panel_bridge_add_typed - Creates a &drm_bridge and &drm_connector with
     277             :  * an explicit connector type.
     278             :  * @panel: The drm_panel being wrapped.  Must be non-NULL.
     279             :  * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
     280             :  *
     281             :  * This is just like drm_panel_bridge_add(), but forces the connector type to
     282             :  * @connector_type instead of infering it from the panel.
     283             :  *
     284             :  * This function is deprecated and should not be used in new drivers. Use
     285             :  * drm_panel_bridge_add() instead, and fix panel drivers as necessary if they
     286             :  * don't report a connector type.
     287             :  */
     288           0 : struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,
     289             :                                               u32 connector_type)
     290             : {
     291             :         struct panel_bridge *panel_bridge;
     292             : 
     293           0 :         if (!panel)
     294             :                 return ERR_PTR(-EINVAL);
     295             : 
     296           0 :         panel_bridge = devm_kzalloc(panel->dev, sizeof(*panel_bridge),
     297             :                                     GFP_KERNEL);
     298           0 :         if (!panel_bridge)
     299             :                 return ERR_PTR(-ENOMEM);
     300             : 
     301           0 :         panel_bridge->connector_type = connector_type;
     302           0 :         panel_bridge->panel = panel;
     303             : 
     304           0 :         panel_bridge->bridge.funcs = &panel_bridge_bridge_funcs;
     305             : #ifdef CONFIG_OF
     306             :         panel_bridge->bridge.of_node = panel->dev->of_node;
     307             : #endif
     308           0 :         panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
     309           0 :         panel_bridge->bridge.type = connector_type;
     310             : 
     311           0 :         drm_bridge_add(&panel_bridge->bridge);
     312             : 
     313           0 :         return &panel_bridge->bridge;
     314             : }
     315             : EXPORT_SYMBOL(drm_panel_bridge_add_typed);
     316             : 
     317             : /**
     318             :  * drm_panel_bridge_remove - Unregisters and frees a drm_bridge
     319             :  * created by drm_panel_bridge_add().
     320             :  *
     321             :  * @bridge: The drm_bridge being freed.
     322             :  */
     323           0 : void drm_panel_bridge_remove(struct drm_bridge *bridge)
     324             : {
     325             :         struct panel_bridge *panel_bridge;
     326             : 
     327           0 :         if (!bridge)
     328             :                 return;
     329             : 
     330           0 :         if (bridge->funcs != &panel_bridge_bridge_funcs)
     331             :                 return;
     332             : 
     333           0 :         panel_bridge = drm_bridge_to_panel_bridge(bridge);
     334             : 
     335           0 :         drm_bridge_remove(bridge);
     336           0 :         devm_kfree(panel_bridge->panel->dev, bridge);
     337             : }
     338             : EXPORT_SYMBOL(drm_panel_bridge_remove);
     339             : 
     340             : /**
     341             :  * drm_panel_bridge_set_orientation - Set the connector's panel orientation
     342             :  * from the bridge that can be transformed to panel bridge.
     343             :  *
     344             :  * @connector: The connector to be set panel orientation.
     345             :  * @bridge: The drm_bridge to be transformed to panel bridge.
     346             :  *
     347             :  * Returns 0 on success, negative errno on failure.
     348             :  */
     349           0 : int drm_panel_bridge_set_orientation(struct drm_connector *connector,
     350             :                                      struct drm_bridge *bridge)
     351             : {
     352             :         struct panel_bridge *panel_bridge;
     353             : 
     354           0 :         panel_bridge = drm_bridge_to_panel_bridge(bridge);
     355             : 
     356           0 :         return drm_connector_set_orientation_from_panel(connector,
     357             :                                                         panel_bridge->panel);
     358             : }
     359             : EXPORT_SYMBOL(drm_panel_bridge_set_orientation);
     360             : 
     361           0 : static void devm_drm_panel_bridge_release(struct device *dev, void *res)
     362             : {
     363           0 :         struct drm_bridge **bridge = res;
     364             : 
     365           0 :         drm_panel_bridge_remove(*bridge);
     366           0 : }
     367             : 
     368             : /**
     369             :  * devm_drm_panel_bridge_add - Creates a managed &drm_bridge and &drm_connector
     370             :  * that just calls the appropriate functions from &drm_panel.
     371             :  * @dev: device to tie the bridge lifetime to
     372             :  * @panel: The drm_panel being wrapped.  Must be non-NULL.
     373             :  *
     374             :  * This is the managed version of drm_panel_bridge_add() which automatically
     375             :  * calls drm_panel_bridge_remove() when @dev is unbound.
     376             :  */
     377           0 : struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
     378             :                                              struct drm_panel *panel)
     379             : {
     380           0 :         if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
     381             :                 return ERR_PTR(-EINVAL);
     382             : 
     383           0 :         return devm_drm_panel_bridge_add_typed(dev, panel,
     384           0 :                                                panel->connector_type);
     385             : }
     386             : EXPORT_SYMBOL(devm_drm_panel_bridge_add);
     387             : 
     388             : /**
     389             :  * devm_drm_panel_bridge_add_typed - Creates a managed &drm_bridge and
     390             :  * &drm_connector with an explicit connector type.
     391             :  * @dev: device to tie the bridge lifetime to
     392             :  * @panel: The drm_panel being wrapped.  Must be non-NULL.
     393             :  * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
     394             :  *
     395             :  * This is just like devm_drm_panel_bridge_add(), but forces the connector type
     396             :  * to @connector_type instead of infering it from the panel.
     397             :  *
     398             :  * This function is deprecated and should not be used in new drivers. Use
     399             :  * devm_drm_panel_bridge_add() instead, and fix panel drivers as necessary if
     400             :  * they don't report a connector type.
     401             :  */
     402           0 : struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
     403             :                                                    struct drm_panel *panel,
     404             :                                                    u32 connector_type)
     405             : {
     406             :         struct drm_bridge **ptr, *bridge;
     407             : 
     408           0 :         ptr = devres_alloc(devm_drm_panel_bridge_release, sizeof(*ptr),
     409             :                            GFP_KERNEL);
     410           0 :         if (!ptr)
     411             :                 return ERR_PTR(-ENOMEM);
     412             : 
     413           0 :         bridge = drm_panel_bridge_add_typed(panel, connector_type);
     414           0 :         if (IS_ERR(bridge)) {
     415           0 :                 devres_free(ptr);
     416           0 :                 return bridge;
     417             :         }
     418             : 
     419           0 :         bridge->pre_enable_prev_first = panel->prepare_prev_first;
     420             : 
     421           0 :         *ptr = bridge;
     422           0 :         devres_add(dev, ptr);
     423             : 
     424           0 :         return bridge;
     425             : }
     426             : EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
     427             : 
     428           0 : static void drmm_drm_panel_bridge_release(struct drm_device *drm, void *ptr)
     429             : {
     430           0 :         struct drm_bridge *bridge = ptr;
     431             : 
     432           0 :         drm_panel_bridge_remove(bridge);
     433           0 : }
     434             : 
     435             : /**
     436             :  * drmm_panel_bridge_add - Creates a DRM-managed &drm_bridge and
     437             :  *                         &drm_connector that just calls the
     438             :  *                         appropriate functions from &drm_panel.
     439             :  *
     440             :  * @drm: DRM device to tie the bridge lifetime to
     441             :  * @panel: The drm_panel being wrapped.  Must be non-NULL.
     442             :  *
     443             :  * This is the DRM-managed version of drm_panel_bridge_add() which
     444             :  * automatically calls drm_panel_bridge_remove() when @dev is cleaned
     445             :  * up.
     446             :  */
     447           0 : struct drm_bridge *drmm_panel_bridge_add(struct drm_device *drm,
     448             :                                          struct drm_panel *panel)
     449             : {
     450             :         struct drm_bridge *bridge;
     451             :         int ret;
     452             : 
     453           0 :         bridge = drm_panel_bridge_add_typed(panel, panel->connector_type);
     454           0 :         if (IS_ERR(bridge))
     455             :                 return bridge;
     456             : 
     457           0 :         ret = drmm_add_action_or_reset(drm, drmm_drm_panel_bridge_release,
     458             :                                        bridge);
     459           0 :         if (ret)
     460           0 :                 return ERR_PTR(ret);
     461             : 
     462           0 :         bridge->pre_enable_prev_first = panel->prepare_prev_first;
     463             : 
     464           0 :         return bridge;
     465             : }
     466             : EXPORT_SYMBOL(drmm_panel_bridge_add);
     467             : 
     468             : /**
     469             :  * drm_panel_bridge_connector - return the connector for the panel bridge
     470             :  * @bridge: The drm_bridge.
     471             :  *
     472             :  * drm_panel_bridge creates the connector.
     473             :  * This function gives external access to the connector.
     474             :  *
     475             :  * Returns: Pointer to drm_connector
     476             :  */
     477           0 : struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge)
     478             : {
     479             :         struct panel_bridge *panel_bridge;
     480             : 
     481           0 :         panel_bridge = drm_bridge_to_panel_bridge(bridge);
     482             : 
     483           0 :         return &panel_bridge->connector;
     484             : }
     485             : EXPORT_SYMBOL(drm_panel_bridge_connector);
     486             : 
     487             : #ifdef CONFIG_OF
     488             : /**
     489             :  * devm_drm_of_get_bridge - Return next bridge in the chain
     490             :  * @dev: device to tie the bridge lifetime to
     491             :  * @np: device tree node containing encoder output ports
     492             :  * @port: port in the device tree node
     493             :  * @endpoint: endpoint in the device tree node
     494             :  *
     495             :  * Given a DT node's port and endpoint number, finds the connected node
     496             :  * and returns the associated bridge if any, or creates and returns a
     497             :  * drm panel bridge instance if a panel is connected.
     498             :  *
     499             :  * Returns a pointer to the bridge if successful, or an error pointer
     500             :  * otherwise.
     501             :  */
     502             : struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
     503             :                                           struct device_node *np,
     504             :                                           u32 port, u32 endpoint)
     505             : {
     506             :         struct drm_bridge *bridge;
     507             :         struct drm_panel *panel;
     508             :         int ret;
     509             : 
     510             :         ret = drm_of_find_panel_or_bridge(np, port, endpoint,
     511             :                                           &panel, &bridge);
     512             :         if (ret)
     513             :                 return ERR_PTR(ret);
     514             : 
     515             :         if (panel)
     516             :                 bridge = devm_drm_panel_bridge_add(dev, panel);
     517             : 
     518             :         return bridge;
     519             : }
     520             : EXPORT_SYMBOL(devm_drm_of_get_bridge);
     521             : 
     522             : /**
     523             :  * drmm_of_get_bridge - Return next bridge in the chain
     524             :  * @drm: device to tie the bridge lifetime to
     525             :  * @np: device tree node containing encoder output ports
     526             :  * @port: port in the device tree node
     527             :  * @endpoint: endpoint in the device tree node
     528             :  *
     529             :  * Given a DT node's port and endpoint number, finds the connected node
     530             :  * and returns the associated bridge if any, or creates and returns a
     531             :  * drm panel bridge instance if a panel is connected.
     532             :  *
     533             :  * Returns a drmm managed pointer to the bridge if successful, or an error
     534             :  * pointer otherwise.
     535             :  */
     536             : struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm,
     537             :                                       struct device_node *np,
     538             :                                       u32 port, u32 endpoint)
     539             : {
     540             :         struct drm_bridge *bridge;
     541             :         struct drm_panel *panel;
     542             :         int ret;
     543             : 
     544             :         ret = drm_of_find_panel_or_bridge(np, port, endpoint,
     545             :                                           &panel, &bridge);
     546             :         if (ret)
     547             :                 return ERR_PTR(ret);
     548             : 
     549             :         if (panel)
     550             :                 bridge = drmm_panel_bridge_add(drm, panel);
     551             : 
     552             :         return bridge;
     553             : }
     554             : EXPORT_SYMBOL(drmm_of_get_bridge);
     555             : 
     556             : #endif

Generated by: LCOV version 1.14