Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
0004  * Copyright (C) 2017 Broadcom
0005  */
0006 
0007 #include <drm/drm_atomic_helper.h>
0008 #include <drm/drm_bridge.h>
0009 #include <drm/drm_connector.h>
0010 #include <drm/drm_encoder.h>
0011 #include <drm/drm_modeset_helper_vtables.h>
0012 #include <drm/drm_of.h>
0013 #include <drm/drm_panel.h>
0014 #include <drm/drm_print.h>
0015 #include <drm/drm_probe_helper.h>
0016 
0017 struct panel_bridge {
0018     struct drm_bridge bridge;
0019     struct drm_connector connector;
0020     struct drm_panel *panel;
0021     u32 connector_type;
0022 };
0023 
0024 static inline struct panel_bridge *
0025 drm_bridge_to_panel_bridge(struct drm_bridge *bridge)
0026 {
0027     return container_of(bridge, struct panel_bridge, bridge);
0028 }
0029 
0030 static inline struct panel_bridge *
0031 drm_connector_to_panel_bridge(struct drm_connector *connector)
0032 {
0033     return container_of(connector, struct panel_bridge, connector);
0034 }
0035 
0036 static int panel_bridge_connector_get_modes(struct drm_connector *connector)
0037 {
0038     struct panel_bridge *panel_bridge =
0039         drm_connector_to_panel_bridge(connector);
0040 
0041     return drm_panel_get_modes(panel_bridge->panel, connector);
0042 }
0043 
0044 static const struct drm_connector_helper_funcs
0045 panel_bridge_connector_helper_funcs = {
0046     .get_modes = panel_bridge_connector_get_modes,
0047 };
0048 
0049 static const struct drm_connector_funcs panel_bridge_connector_funcs = {
0050     .reset = drm_atomic_helper_connector_reset,
0051     .fill_modes = drm_helper_probe_single_connector_modes,
0052     .destroy = drm_connector_cleanup,
0053     .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0054     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0055 };
0056 
0057 static int panel_bridge_attach(struct drm_bridge *bridge,
0058                    enum drm_bridge_attach_flags flags)
0059 {
0060     struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
0061     struct drm_connector *connector = &panel_bridge->connector;
0062     int ret;
0063 
0064     if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
0065         return 0;
0066 
0067     if (!bridge->encoder) {
0068         DRM_ERROR("Missing encoder\n");
0069         return -ENODEV;
0070     }
0071 
0072     drm_connector_helper_add(connector,
0073                  &panel_bridge_connector_helper_funcs);
0074 
0075     ret = drm_connector_init(bridge->dev, connector,
0076                  &panel_bridge_connector_funcs,
0077                  panel_bridge->connector_type);
0078     if (ret) {
0079         DRM_ERROR("Failed to initialize connector\n");
0080         return ret;
0081     }
0082 
0083     drm_connector_attach_encoder(&panel_bridge->connector,
0084                       bridge->encoder);
0085 
0086     if (bridge->dev->registered) {
0087         if (connector->funcs->reset)
0088             connector->funcs->reset(connector);
0089         drm_connector_register(connector);
0090     }
0091 
0092     return 0;
0093 }
0094 
0095 static void panel_bridge_detach(struct drm_bridge *bridge)
0096 {
0097     struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
0098     struct drm_connector *connector = &panel_bridge->connector;
0099 
0100     /*
0101      * Cleanup the connector if we know it was initialized.
0102      *
0103      * FIXME: This wouldn't be needed if the panel_bridge structure was
0104      * allocated with drmm_kzalloc(). This might be tricky since the
0105      * drm_device pointer can only be retrieved when the bridge is attached.
0106      */
0107     if (connector->dev)
0108         drm_connector_cleanup(connector);
0109 }
0110 
0111 static void panel_bridge_pre_enable(struct drm_bridge *bridge)
0112 {
0113     struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
0114 
0115     drm_panel_prepare(panel_bridge->panel);
0116 }
0117 
0118 static void panel_bridge_enable(struct drm_bridge *bridge)
0119 {
0120     struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
0121 
0122     drm_panel_enable(panel_bridge->panel);
0123 }
0124 
0125 static void panel_bridge_disable(struct drm_bridge *bridge)
0126 {
0127     struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
0128 
0129     drm_panel_disable(panel_bridge->panel);
0130 }
0131 
0132 static void panel_bridge_post_disable(struct drm_bridge *bridge)
0133 {
0134     struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
0135 
0136     drm_panel_unprepare(panel_bridge->panel);
0137 }
0138 
0139 static int panel_bridge_get_modes(struct drm_bridge *bridge,
0140                   struct drm_connector *connector)
0141 {
0142     struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
0143 
0144     return drm_panel_get_modes(panel_bridge->panel, connector);
0145 }
0146 
0147 static void panel_bridge_debugfs_init(struct drm_bridge *bridge,
0148                       struct dentry *root)
0149 {
0150     struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
0151     struct drm_panel *panel = panel_bridge->panel;
0152 
0153     root = debugfs_create_dir("panel", root);
0154     if (panel->funcs->debugfs_init)
0155         panel->funcs->debugfs_init(panel, root);
0156 }
0157 
0158 static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
0159     .attach = panel_bridge_attach,
0160     .detach = panel_bridge_detach,
0161     .pre_enable = panel_bridge_pre_enable,
0162     .enable = panel_bridge_enable,
0163     .disable = panel_bridge_disable,
0164     .post_disable = panel_bridge_post_disable,
0165     .get_modes = panel_bridge_get_modes,
0166     .atomic_reset = drm_atomic_helper_bridge_reset,
0167     .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
0168     .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
0169     .atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
0170     .debugfs_init = panel_bridge_debugfs_init,
0171 };
0172 
0173 /**
0174  * drm_bridge_is_panel - Checks if a drm_bridge is a panel_bridge.
0175  *
0176  * @bridge: The drm_bridge to be checked.
0177  *
0178  * Returns true if the bridge is a panel bridge, or false otherwise.
0179  */
0180 bool drm_bridge_is_panel(const struct drm_bridge *bridge)
0181 {
0182     return bridge->funcs == &panel_bridge_bridge_funcs;
0183 }
0184 EXPORT_SYMBOL(drm_bridge_is_panel);
0185 
0186 /**
0187  * drm_panel_bridge_add - Creates a &drm_bridge and &drm_connector that
0188  * just calls the appropriate functions from &drm_panel.
0189  *
0190  * @panel: The drm_panel being wrapped.  Must be non-NULL.
0191  *
0192  * For drivers converting from directly using drm_panel: The expected
0193  * usage pattern is that during either encoder module probe or DSI
0194  * host attach, a drm_panel will be looked up through
0195  * drm_of_find_panel_or_bridge().  drm_panel_bridge_add() is used to
0196  * wrap that panel in the new bridge, and the result can then be
0197  * passed to drm_bridge_attach().  The drm_panel_prepare() and related
0198  * functions can be dropped from the encoder driver (they're now
0199  * called by the KMS helpers before calling into the encoder), along
0200  * with connector creation.  When done with the bridge (after
0201  * drm_mode_config_cleanup() if the bridge has already been attached), then
0202  * drm_panel_bridge_remove() to free it.
0203  *
0204  * The connector type is set to @panel->connector_type, which must be set to a
0205  * known type. Calling this function with a panel whose connector type is
0206  * DRM_MODE_CONNECTOR_Unknown will return ERR_PTR(-EINVAL).
0207  *
0208  * See devm_drm_panel_bridge_add() for an automatically managed version of this
0209  * function.
0210  */
0211 struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel)
0212 {
0213     if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
0214         return ERR_PTR(-EINVAL);
0215 
0216     return drm_panel_bridge_add_typed(panel, panel->connector_type);
0217 }
0218 EXPORT_SYMBOL(drm_panel_bridge_add);
0219 
0220 /**
0221  * drm_panel_bridge_add_typed - Creates a &drm_bridge and &drm_connector with
0222  * an explicit connector type.
0223  * @panel: The drm_panel being wrapped.  Must be non-NULL.
0224  * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
0225  *
0226  * This is just like drm_panel_bridge_add(), but forces the connector type to
0227  * @connector_type instead of infering it from the panel.
0228  *
0229  * This function is deprecated and should not be used in new drivers. Use
0230  * drm_panel_bridge_add() instead, and fix panel drivers as necessary if they
0231  * don't report a connector type.
0232  */
0233 struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,
0234                           u32 connector_type)
0235 {
0236     struct panel_bridge *panel_bridge;
0237 
0238     if (!panel)
0239         return ERR_PTR(-EINVAL);
0240 
0241     panel_bridge = devm_kzalloc(panel->dev, sizeof(*panel_bridge),
0242                     GFP_KERNEL);
0243     if (!panel_bridge)
0244         return ERR_PTR(-ENOMEM);
0245 
0246     panel_bridge->connector_type = connector_type;
0247     panel_bridge->panel = panel;
0248 
0249     panel_bridge->bridge.funcs = &panel_bridge_bridge_funcs;
0250 #ifdef CONFIG_OF
0251     panel_bridge->bridge.of_node = panel->dev->of_node;
0252 #endif
0253     panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
0254     panel_bridge->bridge.type = connector_type;
0255 
0256     drm_bridge_add(&panel_bridge->bridge);
0257 
0258     return &panel_bridge->bridge;
0259 }
0260 EXPORT_SYMBOL(drm_panel_bridge_add_typed);
0261 
0262 /**
0263  * drm_panel_bridge_remove - Unregisters and frees a drm_bridge
0264  * created by drm_panel_bridge_add().
0265  *
0266  * @bridge: The drm_bridge being freed.
0267  */
0268 void drm_panel_bridge_remove(struct drm_bridge *bridge)
0269 {
0270     struct panel_bridge *panel_bridge;
0271 
0272     if (!bridge)
0273         return;
0274 
0275     if (bridge->funcs != &panel_bridge_bridge_funcs)
0276         return;
0277 
0278     panel_bridge = drm_bridge_to_panel_bridge(bridge);
0279 
0280     drm_bridge_remove(bridge);
0281     devm_kfree(panel_bridge->panel->dev, bridge);
0282 }
0283 EXPORT_SYMBOL(drm_panel_bridge_remove);
0284 
0285 /**
0286  * drm_panel_bridge_set_orientation - Set the connector's panel orientation
0287  * from the bridge that can be transformed to panel bridge.
0288  *
0289  * @connector: The connector to be set panel orientation.
0290  * @bridge: The drm_bridge to be transformed to panel bridge.
0291  *
0292  * Returns 0 on success, negative errno on failure.
0293  */
0294 int drm_panel_bridge_set_orientation(struct drm_connector *connector,
0295                      struct drm_bridge *bridge)
0296 {
0297     struct panel_bridge *panel_bridge;
0298 
0299     panel_bridge = drm_bridge_to_panel_bridge(bridge);
0300 
0301     return drm_connector_set_orientation_from_panel(connector,
0302                             panel_bridge->panel);
0303 }
0304 EXPORT_SYMBOL(drm_panel_bridge_set_orientation);
0305 
0306 static void devm_drm_panel_bridge_release(struct device *dev, void *res)
0307 {
0308     struct drm_bridge **bridge = res;
0309 
0310     drm_panel_bridge_remove(*bridge);
0311 }
0312 
0313 /**
0314  * devm_drm_panel_bridge_add - Creates a managed &drm_bridge and &drm_connector
0315  * that just calls the appropriate functions from &drm_panel.
0316  * @dev: device to tie the bridge lifetime to
0317  * @panel: The drm_panel being wrapped.  Must be non-NULL.
0318  *
0319  * This is the managed version of drm_panel_bridge_add() which automatically
0320  * calls drm_panel_bridge_remove() when @dev is unbound.
0321  */
0322 struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
0323                          struct drm_panel *panel)
0324 {
0325     if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
0326         return ERR_PTR(-EINVAL);
0327 
0328     return devm_drm_panel_bridge_add_typed(dev, panel,
0329                            panel->connector_type);
0330 }
0331 EXPORT_SYMBOL(devm_drm_panel_bridge_add);
0332 
0333 /**
0334  * devm_drm_panel_bridge_add_typed - Creates a managed &drm_bridge and
0335  * &drm_connector with an explicit connector type.
0336  * @dev: device to tie the bridge lifetime to
0337  * @panel: The drm_panel being wrapped.  Must be non-NULL.
0338  * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
0339  *
0340  * This is just like devm_drm_panel_bridge_add(), but forces the connector type
0341  * to @connector_type instead of infering it from the panel.
0342  *
0343  * This function is deprecated and should not be used in new drivers. Use
0344  * devm_drm_panel_bridge_add() instead, and fix panel drivers as necessary if
0345  * they don't report a connector type.
0346  */
0347 struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
0348                            struct drm_panel *panel,
0349                            u32 connector_type)
0350 {
0351     struct drm_bridge **ptr, *bridge;
0352 
0353     ptr = devres_alloc(devm_drm_panel_bridge_release, sizeof(*ptr),
0354                GFP_KERNEL);
0355     if (!ptr)
0356         return ERR_PTR(-ENOMEM);
0357 
0358     bridge = drm_panel_bridge_add_typed(panel, connector_type);
0359     if (!IS_ERR(bridge)) {
0360         *ptr = bridge;
0361         devres_add(dev, ptr);
0362     } else {
0363         devres_free(ptr);
0364     }
0365 
0366     return bridge;
0367 }
0368 EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
0369 
0370 /**
0371  * drm_panel_bridge_connector - return the connector for the panel bridge
0372  * @bridge: The drm_bridge.
0373  *
0374  * drm_panel_bridge creates the connector.
0375  * This function gives external access to the connector.
0376  *
0377  * Returns: Pointer to drm_connector
0378  */
0379 struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge)
0380 {
0381     struct panel_bridge *panel_bridge;
0382 
0383     panel_bridge = drm_bridge_to_panel_bridge(bridge);
0384 
0385     return &panel_bridge->connector;
0386 }
0387 EXPORT_SYMBOL(drm_panel_bridge_connector);
0388 
0389 #ifdef CONFIG_OF
0390 /**
0391  * devm_drm_of_get_bridge - Return next bridge in the chain
0392  * @dev: device to tie the bridge lifetime to
0393  * @np: device tree node containing encoder output ports
0394  * @port: port in the device tree node
0395  * @endpoint: endpoint in the device tree node
0396  *
0397  * Given a DT node's port and endpoint number, finds the connected node
0398  * and returns the associated bridge if any, or creates and returns a
0399  * drm panel bridge instance if a panel is connected.
0400  *
0401  * Returns a pointer to the bridge if successful, or an error pointer
0402  * otherwise.
0403  */
0404 struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
0405                       struct device_node *np,
0406                       u32 port, u32 endpoint)
0407 {
0408     struct drm_bridge *bridge;
0409     struct drm_panel *panel;
0410     int ret;
0411 
0412     ret = drm_of_find_panel_or_bridge(np, port, endpoint,
0413                       &panel, &bridge);
0414     if (ret)
0415         return ERR_PTR(ret);
0416 
0417     if (panel)
0418         bridge = devm_drm_panel_bridge_add(dev, panel);
0419 
0420     return bridge;
0421 }
0422 EXPORT_SYMBOL(devm_drm_of_get_bridge);
0423 #endif