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