162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2014 Samsung Electronics Co., Ltd 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license, 862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the 1262306a36Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 1362306a36Sopenharmony_ci * of the Software. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 1862306a36Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1962306a36Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2062306a36Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2162306a36Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <linux/err.h> 2562306a36Sopenharmony_ci#include <linux/media-bus-format.h> 2662306a36Sopenharmony_ci#include <linux/module.h> 2762306a36Sopenharmony_ci#include <linux/mutex.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <drm/drm_atomic_state_helper.h> 3062306a36Sopenharmony_ci#include <drm/drm_debugfs.h> 3162306a36Sopenharmony_ci#include <drm/drm_bridge.h> 3262306a36Sopenharmony_ci#include <drm/drm_encoder.h> 3362306a36Sopenharmony_ci#include <drm/drm_file.h> 3462306a36Sopenharmony_ci#include <drm/drm_of.h> 3562306a36Sopenharmony_ci#include <drm/drm_print.h> 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#include "drm_crtc_internal.h" 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/** 4062306a36Sopenharmony_ci * DOC: overview 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * &struct drm_bridge represents a device that hangs on to an encoder. These are 4362306a36Sopenharmony_ci * handy when a regular &drm_encoder entity isn't enough to represent the entire 4462306a36Sopenharmony_ci * encoder chain. 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * A bridge is always attached to a single &drm_encoder at a time, but can be 4762306a36Sopenharmony_ci * either connected to it directly, or through a chain of bridges:: 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * [ CRTC ---> ] Encoder ---> Bridge A ---> Bridge B 5062306a36Sopenharmony_ci * 5162306a36Sopenharmony_ci * Here, the output of the encoder feeds to bridge A, and that furthers feeds to 5262306a36Sopenharmony_ci * bridge B. Bridge chains can be arbitrarily long, and shall be fully linear: 5362306a36Sopenharmony_ci * Chaining multiple bridges to the output of a bridge, or the same bridge to 5462306a36Sopenharmony_ci * the output of different bridges, is not supported. 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci * &drm_bridge, like &drm_panel, aren't &drm_mode_object entities like planes, 5762306a36Sopenharmony_ci * CRTCs, encoders or connectors and hence are not visible to userspace. They 5862306a36Sopenharmony_ci * just provide additional hooks to get the desired output at the end of the 5962306a36Sopenharmony_ci * encoder chain. 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/** 6362306a36Sopenharmony_ci * DOC: display driver integration 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * Display drivers are responsible for linking encoders with the first bridge 6662306a36Sopenharmony_ci * in the chains. This is done by acquiring the appropriate bridge with 6762306a36Sopenharmony_ci * devm_drm_of_get_bridge(). Once acquired, the bridge shall be attached to the 6862306a36Sopenharmony_ci * encoder with a call to drm_bridge_attach(). 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * Bridges are responsible for linking themselves with the next bridge in the 7162306a36Sopenharmony_ci * chain, if any. This is done the same way as for encoders, with the call to 7262306a36Sopenharmony_ci * drm_bridge_attach() occurring in the &drm_bridge_funcs.attach operation. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * Once these links are created, the bridges can participate along with encoder 7562306a36Sopenharmony_ci * functions to perform mode validation and fixup (through 7662306a36Sopenharmony_ci * drm_bridge_chain_mode_valid() and drm_atomic_bridge_chain_check()), mode 7762306a36Sopenharmony_ci * setting (through drm_bridge_chain_mode_set()), enable (through 7862306a36Sopenharmony_ci * drm_atomic_bridge_chain_pre_enable() and drm_atomic_bridge_chain_enable()) 7962306a36Sopenharmony_ci * and disable (through drm_atomic_bridge_chain_disable() and 8062306a36Sopenharmony_ci * drm_atomic_bridge_chain_post_disable()). Those functions call the 8162306a36Sopenharmony_ci * corresponding operations provided in &drm_bridge_funcs in sequence for all 8262306a36Sopenharmony_ci * bridges in the chain. 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * For display drivers that use the atomic helpers 8562306a36Sopenharmony_ci * drm_atomic_helper_check_modeset(), 8662306a36Sopenharmony_ci * drm_atomic_helper_commit_modeset_enables() and 8762306a36Sopenharmony_ci * drm_atomic_helper_commit_modeset_disables() (either directly in hand-rolled 8862306a36Sopenharmony_ci * commit check and commit tail handlers, or through the higher-level 8962306a36Sopenharmony_ci * drm_atomic_helper_check() and drm_atomic_helper_commit_tail() or 9062306a36Sopenharmony_ci * drm_atomic_helper_commit_tail_rpm() helpers), this is done transparently and 9162306a36Sopenharmony_ci * requires no intervention from the driver. For other drivers, the relevant 9262306a36Sopenharmony_ci * DRM bridge chain functions shall be called manually. 9362306a36Sopenharmony_ci * 9462306a36Sopenharmony_ci * Bridges also participate in implementing the &drm_connector at the end of 9562306a36Sopenharmony_ci * the bridge chain. Display drivers may use the drm_bridge_connector_init() 9662306a36Sopenharmony_ci * helper to create the &drm_connector, or implement it manually on top of the 9762306a36Sopenharmony_ci * connector-related operations exposed by the bridge (see the overview 9862306a36Sopenharmony_ci * documentation of bridge operations for more details). 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/** 10262306a36Sopenharmony_ci * DOC: special care dsi 10362306a36Sopenharmony_ci * 10462306a36Sopenharmony_ci * The interaction between the bridges and other frameworks involved in 10562306a36Sopenharmony_ci * the probing of the upstream driver and the bridge driver can be 10662306a36Sopenharmony_ci * challenging. Indeed, there's multiple cases that needs to be 10762306a36Sopenharmony_ci * considered: 10862306a36Sopenharmony_ci * 10962306a36Sopenharmony_ci * - The upstream driver doesn't use the component framework and isn't a 11062306a36Sopenharmony_ci * MIPI-DSI host. In this case, the bridge driver will probe at some 11162306a36Sopenharmony_ci * point and the upstream driver should try to probe again by returning 11262306a36Sopenharmony_ci * EPROBE_DEFER as long as the bridge driver hasn't probed. 11362306a36Sopenharmony_ci * 11462306a36Sopenharmony_ci * - The upstream driver doesn't use the component framework, but is a 11562306a36Sopenharmony_ci * MIPI-DSI host. The bridge device uses the MIPI-DCS commands to be 11662306a36Sopenharmony_ci * controlled. In this case, the bridge device is a child of the 11762306a36Sopenharmony_ci * display device and when it will probe it's assured that the display 11862306a36Sopenharmony_ci * device (and MIPI-DSI host) is present. The upstream driver will be 11962306a36Sopenharmony_ci * assured that the bridge driver is connected between the 12062306a36Sopenharmony_ci * &mipi_dsi_host_ops.attach and &mipi_dsi_host_ops.detach operations. 12162306a36Sopenharmony_ci * Therefore, it must run mipi_dsi_host_register() in its probe 12262306a36Sopenharmony_ci * function, and then run drm_bridge_attach() in its 12362306a36Sopenharmony_ci * &mipi_dsi_host_ops.attach hook. 12462306a36Sopenharmony_ci * 12562306a36Sopenharmony_ci * - The upstream driver uses the component framework and is a MIPI-DSI 12662306a36Sopenharmony_ci * host. The bridge device uses the MIPI-DCS commands to be 12762306a36Sopenharmony_ci * controlled. This is the same situation than above, and can run 12862306a36Sopenharmony_ci * mipi_dsi_host_register() in either its probe or bind hooks. 12962306a36Sopenharmony_ci * 13062306a36Sopenharmony_ci * - The upstream driver uses the component framework and is a MIPI-DSI 13162306a36Sopenharmony_ci * host. The bridge device uses a separate bus (such as I2C) to be 13262306a36Sopenharmony_ci * controlled. In this case, there's no correlation between the probe 13362306a36Sopenharmony_ci * of the bridge and upstream drivers, so care must be taken to avoid 13462306a36Sopenharmony_ci * an endless EPROBE_DEFER loop, with each driver waiting for the 13562306a36Sopenharmony_ci * other to probe. 13662306a36Sopenharmony_ci * 13762306a36Sopenharmony_ci * The ideal pattern to cover the last item (and all the others in the 13862306a36Sopenharmony_ci * MIPI-DSI host driver case) is to split the operations like this: 13962306a36Sopenharmony_ci * 14062306a36Sopenharmony_ci * - The MIPI-DSI host driver must run mipi_dsi_host_register() in its 14162306a36Sopenharmony_ci * probe hook. It will make sure that the MIPI-DSI host sticks around, 14262306a36Sopenharmony_ci * and that the driver's bind can be called. 14362306a36Sopenharmony_ci * 14462306a36Sopenharmony_ci * - In its probe hook, the bridge driver must try to find its MIPI-DSI 14562306a36Sopenharmony_ci * host, register as a MIPI-DSI device and attach the MIPI-DSI device 14662306a36Sopenharmony_ci * to its host. The bridge driver is now functional. 14762306a36Sopenharmony_ci * 14862306a36Sopenharmony_ci * - In its &struct mipi_dsi_host_ops.attach hook, the MIPI-DSI host can 14962306a36Sopenharmony_ci * now add its component. Its bind hook will now be called and since 15062306a36Sopenharmony_ci * the bridge driver is attached and registered, we can now look for 15162306a36Sopenharmony_ci * and attach it. 15262306a36Sopenharmony_ci * 15362306a36Sopenharmony_ci * At this point, we're now certain that both the upstream driver and 15462306a36Sopenharmony_ci * the bridge driver are functional and we can't have a deadlock-like 15562306a36Sopenharmony_ci * situation when probing. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/** 15962306a36Sopenharmony_ci * DOC: dsi bridge operations 16062306a36Sopenharmony_ci * 16162306a36Sopenharmony_ci * DSI host interfaces are expected to be implemented as bridges rather than 16262306a36Sopenharmony_ci * encoders, however there are a few aspects of their operation that need to 16362306a36Sopenharmony_ci * be defined in order to provide a consistent interface. 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * A DSI host should keep the PHY powered down until the pre_enable operation is 16662306a36Sopenharmony_ci * called. All lanes are in an undefined idle state up to this point, and it 16762306a36Sopenharmony_ci * must not be assumed that it is LP-11. 16862306a36Sopenharmony_ci * pre_enable should initialise the PHY, set the data lanes to LP-11, and the 16962306a36Sopenharmony_ci * clock lane to either LP-11 or HS depending on the mode_flag 17062306a36Sopenharmony_ci * %MIPI_DSI_CLOCK_NON_CONTINUOUS. 17162306a36Sopenharmony_ci * 17262306a36Sopenharmony_ci * Ordinarily the downstream bridge DSI peripheral pre_enable will have been 17362306a36Sopenharmony_ci * called before the DSI host. If the DSI peripheral requires LP-11 and/or 17462306a36Sopenharmony_ci * the clock lane to be in HS mode prior to pre_enable, then it can set the 17562306a36Sopenharmony_ci * &pre_enable_prev_first flag to request the pre_enable (and 17662306a36Sopenharmony_ci * post_disable) order to be altered to enable the DSI host first. 17762306a36Sopenharmony_ci * 17862306a36Sopenharmony_ci * Either the CRTC being enabled, or the DSI host enable operation should switch 17962306a36Sopenharmony_ci * the host to actively transmitting video on the data lanes. 18062306a36Sopenharmony_ci * 18162306a36Sopenharmony_ci * The reverse also applies. The DSI host disable operation or stopping the CRTC 18262306a36Sopenharmony_ci * should stop transmitting video, and the data lanes should return to the LP-11 18362306a36Sopenharmony_ci * state. The DSI host &post_disable operation should disable the PHY. 18462306a36Sopenharmony_ci * If the &pre_enable_prev_first flag is set, then the DSI peripheral's 18562306a36Sopenharmony_ci * bridge &post_disable will be called before the DSI host's post_disable. 18662306a36Sopenharmony_ci * 18762306a36Sopenharmony_ci * Whilst it is valid to call &host_transfer prior to pre_enable or after 18862306a36Sopenharmony_ci * post_disable, the exact state of the lanes is undefined at this point. The 18962306a36Sopenharmony_ci * DSI host should initialise the interface, transmit the data, and then disable 19062306a36Sopenharmony_ci * the interface again. 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * Ultra Low Power State (ULPS) is not explicitly supported by DRM. If 19362306a36Sopenharmony_ci * implemented, it therefore needs to be handled entirely within the DSI Host 19462306a36Sopenharmony_ci * driver. 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic DEFINE_MUTEX(bridge_lock); 19862306a36Sopenharmony_cistatic LIST_HEAD(bridge_list); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/** 20162306a36Sopenharmony_ci * drm_bridge_add - add the given bridge to the global bridge list 20262306a36Sopenharmony_ci * 20362306a36Sopenharmony_ci * @bridge: bridge control structure 20462306a36Sopenharmony_ci */ 20562306a36Sopenharmony_civoid drm_bridge_add(struct drm_bridge *bridge) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci mutex_init(&bridge->hpd_mutex); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci mutex_lock(&bridge_lock); 21062306a36Sopenharmony_ci list_add_tail(&bridge->list, &bridge_list); 21162306a36Sopenharmony_ci mutex_unlock(&bridge_lock); 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ciEXPORT_SYMBOL(drm_bridge_add); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic void drm_bridge_remove_void(void *bridge) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci drm_bridge_remove(bridge); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci/** 22162306a36Sopenharmony_ci * devm_drm_bridge_add - devm managed version of drm_bridge_add() 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci * @dev: device to tie the bridge lifetime to 22462306a36Sopenharmony_ci * @bridge: bridge control structure 22562306a36Sopenharmony_ci * 22662306a36Sopenharmony_ci * This is the managed version of drm_bridge_add() which automatically 22762306a36Sopenharmony_ci * calls drm_bridge_remove() when @dev is unbound. 22862306a36Sopenharmony_ci * 22962306a36Sopenharmony_ci * Return: 0 if no error or negative error code. 23062306a36Sopenharmony_ci */ 23162306a36Sopenharmony_ciint devm_drm_bridge_add(struct device *dev, struct drm_bridge *bridge) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci drm_bridge_add(bridge); 23462306a36Sopenharmony_ci return devm_add_action_or_reset(dev, drm_bridge_remove_void, bridge); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ciEXPORT_SYMBOL(devm_drm_bridge_add); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci/** 23962306a36Sopenharmony_ci * drm_bridge_remove - remove the given bridge from the global bridge list 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci * @bridge: bridge control structure 24262306a36Sopenharmony_ci */ 24362306a36Sopenharmony_civoid drm_bridge_remove(struct drm_bridge *bridge) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci mutex_lock(&bridge_lock); 24662306a36Sopenharmony_ci list_del_init(&bridge->list); 24762306a36Sopenharmony_ci mutex_unlock(&bridge_lock); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci mutex_destroy(&bridge->hpd_mutex); 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ciEXPORT_SYMBOL(drm_bridge_remove); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic struct drm_private_state * 25462306a36Sopenharmony_cidrm_bridge_atomic_duplicate_priv_state(struct drm_private_obj *obj) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci struct drm_bridge *bridge = drm_priv_to_bridge(obj); 25762306a36Sopenharmony_ci struct drm_bridge_state *state; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci state = bridge->funcs->atomic_duplicate_state(bridge); 26062306a36Sopenharmony_ci return state ? &state->base : NULL; 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic void 26462306a36Sopenharmony_cidrm_bridge_atomic_destroy_priv_state(struct drm_private_obj *obj, 26562306a36Sopenharmony_ci struct drm_private_state *s) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci struct drm_bridge_state *state = drm_priv_to_bridge_state(s); 26862306a36Sopenharmony_ci struct drm_bridge *bridge = drm_priv_to_bridge(obj); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci bridge->funcs->atomic_destroy_state(bridge, state); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic const struct drm_private_state_funcs drm_bridge_priv_state_funcs = { 27462306a36Sopenharmony_ci .atomic_duplicate_state = drm_bridge_atomic_duplicate_priv_state, 27562306a36Sopenharmony_ci .atomic_destroy_state = drm_bridge_atomic_destroy_priv_state, 27662306a36Sopenharmony_ci}; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci/** 27962306a36Sopenharmony_ci * drm_bridge_attach - attach the bridge to an encoder's chain 28062306a36Sopenharmony_ci * 28162306a36Sopenharmony_ci * @encoder: DRM encoder 28262306a36Sopenharmony_ci * @bridge: bridge to attach 28362306a36Sopenharmony_ci * @previous: previous bridge in the chain (optional) 28462306a36Sopenharmony_ci * @flags: DRM_BRIDGE_ATTACH_* flags 28562306a36Sopenharmony_ci * 28662306a36Sopenharmony_ci * Called by a kms driver to link the bridge to an encoder's chain. The previous 28762306a36Sopenharmony_ci * argument specifies the previous bridge in the chain. If NULL, the bridge is 28862306a36Sopenharmony_ci * linked directly at the encoder's output. Otherwise it is linked at the 28962306a36Sopenharmony_ci * previous bridge's output. 29062306a36Sopenharmony_ci * 29162306a36Sopenharmony_ci * If non-NULL the previous bridge must be already attached by a call to this 29262306a36Sopenharmony_ci * function. 29362306a36Sopenharmony_ci * 29462306a36Sopenharmony_ci * Note that bridges attached to encoders are auto-detached during encoder 29562306a36Sopenharmony_ci * cleanup in drm_encoder_cleanup(), so drm_bridge_attach() should generally 29662306a36Sopenharmony_ci * *not* be balanced with a drm_bridge_detach() in driver code. 29762306a36Sopenharmony_ci * 29862306a36Sopenharmony_ci * RETURNS: 29962306a36Sopenharmony_ci * Zero on success, error code on failure 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_ciint drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, 30262306a36Sopenharmony_ci struct drm_bridge *previous, 30362306a36Sopenharmony_ci enum drm_bridge_attach_flags flags) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci int ret; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (!encoder || !bridge) 30862306a36Sopenharmony_ci return -EINVAL; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci if (previous && (!previous->dev || previous->encoder != encoder)) 31162306a36Sopenharmony_ci return -EINVAL; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (bridge->dev) 31462306a36Sopenharmony_ci return -EBUSY; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci bridge->dev = encoder->dev; 31762306a36Sopenharmony_ci bridge->encoder = encoder; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (previous) 32062306a36Sopenharmony_ci list_add(&bridge->chain_node, &previous->chain_node); 32162306a36Sopenharmony_ci else 32262306a36Sopenharmony_ci list_add(&bridge->chain_node, &encoder->bridge_chain); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci if (bridge->funcs->attach) { 32562306a36Sopenharmony_ci ret = bridge->funcs->attach(bridge, flags); 32662306a36Sopenharmony_ci if (ret < 0) 32762306a36Sopenharmony_ci goto err_reset_bridge; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (bridge->funcs->atomic_reset) { 33162306a36Sopenharmony_ci struct drm_bridge_state *state; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci state = bridge->funcs->atomic_reset(bridge); 33462306a36Sopenharmony_ci if (IS_ERR(state)) { 33562306a36Sopenharmony_ci ret = PTR_ERR(state); 33662306a36Sopenharmony_ci goto err_detach_bridge; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci drm_atomic_private_obj_init(bridge->dev, &bridge->base, 34062306a36Sopenharmony_ci &state->base, 34162306a36Sopenharmony_ci &drm_bridge_priv_state_funcs); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci return 0; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cierr_detach_bridge: 34762306a36Sopenharmony_ci if (bridge->funcs->detach) 34862306a36Sopenharmony_ci bridge->funcs->detach(bridge); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cierr_reset_bridge: 35162306a36Sopenharmony_ci bridge->dev = NULL; 35262306a36Sopenharmony_ci bridge->encoder = NULL; 35362306a36Sopenharmony_ci list_del(&bridge->chain_node); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci#ifdef CONFIG_OF 35662306a36Sopenharmony_ci DRM_ERROR("failed to attach bridge %pOF to encoder %s: %d\n", 35762306a36Sopenharmony_ci bridge->of_node, encoder->name, ret); 35862306a36Sopenharmony_ci#else 35962306a36Sopenharmony_ci DRM_ERROR("failed to attach bridge to encoder %s: %d\n", 36062306a36Sopenharmony_ci encoder->name, ret); 36162306a36Sopenharmony_ci#endif 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return ret; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ciEXPORT_SYMBOL(drm_bridge_attach); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_civoid drm_bridge_detach(struct drm_bridge *bridge) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci if (WARN_ON(!bridge)) 37062306a36Sopenharmony_ci return; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci if (WARN_ON(!bridge->dev)) 37362306a36Sopenharmony_ci return; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci if (bridge->funcs->atomic_reset) 37662306a36Sopenharmony_ci drm_atomic_private_obj_fini(&bridge->base); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci if (bridge->funcs->detach) 37962306a36Sopenharmony_ci bridge->funcs->detach(bridge); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci list_del(&bridge->chain_node); 38262306a36Sopenharmony_ci bridge->dev = NULL; 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci/** 38662306a36Sopenharmony_ci * DOC: bridge operations 38762306a36Sopenharmony_ci * 38862306a36Sopenharmony_ci * Bridge drivers expose operations through the &drm_bridge_funcs structure. 38962306a36Sopenharmony_ci * The DRM internals (atomic and CRTC helpers) use the helpers defined in 39062306a36Sopenharmony_ci * drm_bridge.c to call bridge operations. Those operations are divided in 39162306a36Sopenharmony_ci * three big categories to support different parts of the bridge usage. 39262306a36Sopenharmony_ci * 39362306a36Sopenharmony_ci * - The encoder-related operations support control of the bridges in the 39462306a36Sopenharmony_ci * chain, and are roughly counterparts to the &drm_encoder_helper_funcs 39562306a36Sopenharmony_ci * operations. They are used by the legacy CRTC and the atomic modeset 39662306a36Sopenharmony_ci * helpers to perform mode validation, fixup and setting, and enable and 39762306a36Sopenharmony_ci * disable the bridge automatically. 39862306a36Sopenharmony_ci * 39962306a36Sopenharmony_ci * The enable and disable operations are split in 40062306a36Sopenharmony_ci * &drm_bridge_funcs.pre_enable, &drm_bridge_funcs.enable, 40162306a36Sopenharmony_ci * &drm_bridge_funcs.disable and &drm_bridge_funcs.post_disable to provide 40262306a36Sopenharmony_ci * finer-grained control. 40362306a36Sopenharmony_ci * 40462306a36Sopenharmony_ci * Bridge drivers may implement the legacy version of those operations, or 40562306a36Sopenharmony_ci * the atomic version (prefixed with atomic\_), in which case they shall also 40662306a36Sopenharmony_ci * implement the atomic state bookkeeping operations 40762306a36Sopenharmony_ci * (&drm_bridge_funcs.atomic_duplicate_state, 40862306a36Sopenharmony_ci * &drm_bridge_funcs.atomic_destroy_state and &drm_bridge_funcs.reset). 40962306a36Sopenharmony_ci * Mixing atomic and non-atomic versions of the operations is not supported. 41062306a36Sopenharmony_ci * 41162306a36Sopenharmony_ci * - The bus format negotiation operations 41262306a36Sopenharmony_ci * &drm_bridge_funcs.atomic_get_output_bus_fmts and 41362306a36Sopenharmony_ci * &drm_bridge_funcs.atomic_get_input_bus_fmts allow bridge drivers to 41462306a36Sopenharmony_ci * negotiate the formats transmitted between bridges in the chain when 41562306a36Sopenharmony_ci * multiple formats are supported. Negotiation for formats is performed 41662306a36Sopenharmony_ci * transparently for display drivers by the atomic modeset helpers. Only 41762306a36Sopenharmony_ci * atomic versions of those operations exist, bridge drivers that need to 41862306a36Sopenharmony_ci * implement them shall thus also implement the atomic version of the 41962306a36Sopenharmony_ci * encoder-related operations. This feature is not supported by the legacy 42062306a36Sopenharmony_ci * CRTC helpers. 42162306a36Sopenharmony_ci * 42262306a36Sopenharmony_ci * - The connector-related operations support implementing a &drm_connector 42362306a36Sopenharmony_ci * based on a chain of bridges. DRM bridges traditionally create a 42462306a36Sopenharmony_ci * &drm_connector for bridges meant to be used at the end of the chain. This 42562306a36Sopenharmony_ci * puts additional burden on bridge drivers, especially for bridges that may 42662306a36Sopenharmony_ci * be used in the middle of a chain or at the end of it. Furthermore, it 42762306a36Sopenharmony_ci * requires all operations of the &drm_connector to be handled by a single 42862306a36Sopenharmony_ci * bridge, which doesn't always match the hardware architecture. 42962306a36Sopenharmony_ci * 43062306a36Sopenharmony_ci * To simplify bridge drivers and make the connector implementation more 43162306a36Sopenharmony_ci * flexible, a new model allows bridges to unconditionally skip creation of 43262306a36Sopenharmony_ci * &drm_connector and instead expose &drm_bridge_funcs operations to support 43362306a36Sopenharmony_ci * an externally-implemented &drm_connector. Those operations are 43462306a36Sopenharmony_ci * &drm_bridge_funcs.detect, &drm_bridge_funcs.get_modes, 43562306a36Sopenharmony_ci * &drm_bridge_funcs.get_edid, &drm_bridge_funcs.hpd_notify, 43662306a36Sopenharmony_ci * &drm_bridge_funcs.hpd_enable and &drm_bridge_funcs.hpd_disable. When 43762306a36Sopenharmony_ci * implemented, display drivers shall create a &drm_connector instance for 43862306a36Sopenharmony_ci * each chain of bridges, and implement those connector instances based on 43962306a36Sopenharmony_ci * the bridge connector operations. 44062306a36Sopenharmony_ci * 44162306a36Sopenharmony_ci * Bridge drivers shall implement the connector-related operations for all 44262306a36Sopenharmony_ci * the features that the bridge hardware support. For instance, if a bridge 44362306a36Sopenharmony_ci * supports reading EDID, the &drm_bridge_funcs.get_edid shall be 44462306a36Sopenharmony_ci * implemented. This however doesn't mean that the DDC lines are wired to the 44562306a36Sopenharmony_ci * bridge on a particular platform, as they could also be connected to an I2C 44662306a36Sopenharmony_ci * controller of the SoC. Support for the connector-related operations on the 44762306a36Sopenharmony_ci * running platform is reported through the &drm_bridge.ops flags. Bridge 44862306a36Sopenharmony_ci * drivers shall detect which operations they can support on the platform 44962306a36Sopenharmony_ci * (usually this information is provided by ACPI or DT), and set the 45062306a36Sopenharmony_ci * &drm_bridge.ops flags for all supported operations. A flag shall only be 45162306a36Sopenharmony_ci * set if the corresponding &drm_bridge_funcs operation is implemented, but 45262306a36Sopenharmony_ci * an implemented operation doesn't necessarily imply that the corresponding 45362306a36Sopenharmony_ci * flag will be set. Display drivers shall use the &drm_bridge.ops flags to 45462306a36Sopenharmony_ci * decide which bridge to delegate a connector operation to. This mechanism 45562306a36Sopenharmony_ci * allows providing a single static const &drm_bridge_funcs instance in 45662306a36Sopenharmony_ci * bridge drivers, improving security by storing function pointers in 45762306a36Sopenharmony_ci * read-only memory. 45862306a36Sopenharmony_ci * 45962306a36Sopenharmony_ci * In order to ease transition, bridge drivers may support both the old and 46062306a36Sopenharmony_ci * new models by making connector creation optional and implementing the 46162306a36Sopenharmony_ci * connected-related bridge operations. Connector creation is then controlled 46262306a36Sopenharmony_ci * by the flags argument to the drm_bridge_attach() function. Display drivers 46362306a36Sopenharmony_ci * that support the new model and create connectors themselves shall set the 46462306a36Sopenharmony_ci * %DRM_BRIDGE_ATTACH_NO_CONNECTOR flag, and bridge drivers shall then skip 46562306a36Sopenharmony_ci * connector creation. For intermediate bridges in the chain, the flag shall 46662306a36Sopenharmony_ci * be passed to the drm_bridge_attach() call for the downstream bridge. 46762306a36Sopenharmony_ci * Bridge drivers that implement the new model only shall return an error 46862306a36Sopenharmony_ci * from their &drm_bridge_funcs.attach handler when the 46962306a36Sopenharmony_ci * %DRM_BRIDGE_ATTACH_NO_CONNECTOR flag is not set. New display drivers 47062306a36Sopenharmony_ci * should use the new model, and convert the bridge drivers they use if 47162306a36Sopenharmony_ci * needed, in order to gradually transition to the new model. 47262306a36Sopenharmony_ci */ 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci/** 47562306a36Sopenharmony_ci * drm_bridge_chain_mode_fixup - fixup proposed mode for all bridges in the 47662306a36Sopenharmony_ci * encoder chain 47762306a36Sopenharmony_ci * @bridge: bridge control structure 47862306a36Sopenharmony_ci * @mode: desired mode to be set for the bridge 47962306a36Sopenharmony_ci * @adjusted_mode: updated mode that works for this bridge 48062306a36Sopenharmony_ci * 48162306a36Sopenharmony_ci * Calls &drm_bridge_funcs.mode_fixup for all the bridges in the 48262306a36Sopenharmony_ci * encoder chain, starting from the first bridge to the last. 48362306a36Sopenharmony_ci * 48462306a36Sopenharmony_ci * Note: the bridge passed should be the one closest to the encoder 48562306a36Sopenharmony_ci * 48662306a36Sopenharmony_ci * RETURNS: 48762306a36Sopenharmony_ci * true on success, false on failure 48862306a36Sopenharmony_ci */ 48962306a36Sopenharmony_cibool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge, 49062306a36Sopenharmony_ci const struct drm_display_mode *mode, 49162306a36Sopenharmony_ci struct drm_display_mode *adjusted_mode) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci struct drm_encoder *encoder; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci if (!bridge) 49662306a36Sopenharmony_ci return true; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci encoder = bridge->encoder; 49962306a36Sopenharmony_ci list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { 50062306a36Sopenharmony_ci if (!bridge->funcs->mode_fixup) 50162306a36Sopenharmony_ci continue; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (!bridge->funcs->mode_fixup(bridge, mode, adjusted_mode)) 50462306a36Sopenharmony_ci return false; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci return true; 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ciEXPORT_SYMBOL(drm_bridge_chain_mode_fixup); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci/** 51262306a36Sopenharmony_ci * drm_bridge_chain_mode_valid - validate the mode against all bridges in the 51362306a36Sopenharmony_ci * encoder chain. 51462306a36Sopenharmony_ci * @bridge: bridge control structure 51562306a36Sopenharmony_ci * @info: display info against which the mode shall be validated 51662306a36Sopenharmony_ci * @mode: desired mode to be validated 51762306a36Sopenharmony_ci * 51862306a36Sopenharmony_ci * Calls &drm_bridge_funcs.mode_valid for all the bridges in the encoder 51962306a36Sopenharmony_ci * chain, starting from the first bridge to the last. If at least one bridge 52062306a36Sopenharmony_ci * does not accept the mode the function returns the error code. 52162306a36Sopenharmony_ci * 52262306a36Sopenharmony_ci * Note: the bridge passed should be the one closest to the encoder. 52362306a36Sopenharmony_ci * 52462306a36Sopenharmony_ci * RETURNS: 52562306a36Sopenharmony_ci * MODE_OK on success, drm_mode_status Enum error code on failure 52662306a36Sopenharmony_ci */ 52762306a36Sopenharmony_cienum drm_mode_status 52862306a36Sopenharmony_cidrm_bridge_chain_mode_valid(struct drm_bridge *bridge, 52962306a36Sopenharmony_ci const struct drm_display_info *info, 53062306a36Sopenharmony_ci const struct drm_display_mode *mode) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci struct drm_encoder *encoder; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (!bridge) 53562306a36Sopenharmony_ci return MODE_OK; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci encoder = bridge->encoder; 53862306a36Sopenharmony_ci list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { 53962306a36Sopenharmony_ci enum drm_mode_status ret; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (!bridge->funcs->mode_valid) 54262306a36Sopenharmony_ci continue; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci ret = bridge->funcs->mode_valid(bridge, info, mode); 54562306a36Sopenharmony_ci if (ret != MODE_OK) 54662306a36Sopenharmony_ci return ret; 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci return MODE_OK; 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ciEXPORT_SYMBOL(drm_bridge_chain_mode_valid); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci/** 55462306a36Sopenharmony_ci * drm_bridge_chain_mode_set - set proposed mode for all bridges in the 55562306a36Sopenharmony_ci * encoder chain 55662306a36Sopenharmony_ci * @bridge: bridge control structure 55762306a36Sopenharmony_ci * @mode: desired mode to be set for the encoder chain 55862306a36Sopenharmony_ci * @adjusted_mode: updated mode that works for this encoder chain 55962306a36Sopenharmony_ci * 56062306a36Sopenharmony_ci * Calls &drm_bridge_funcs.mode_set op for all the bridges in the 56162306a36Sopenharmony_ci * encoder chain, starting from the first bridge to the last. 56262306a36Sopenharmony_ci * 56362306a36Sopenharmony_ci * Note: the bridge passed should be the one closest to the encoder 56462306a36Sopenharmony_ci */ 56562306a36Sopenharmony_civoid drm_bridge_chain_mode_set(struct drm_bridge *bridge, 56662306a36Sopenharmony_ci const struct drm_display_mode *mode, 56762306a36Sopenharmony_ci const struct drm_display_mode *adjusted_mode) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci struct drm_encoder *encoder; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci if (!bridge) 57262306a36Sopenharmony_ci return; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci encoder = bridge->encoder; 57562306a36Sopenharmony_ci list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { 57662306a36Sopenharmony_ci if (bridge->funcs->mode_set) 57762306a36Sopenharmony_ci bridge->funcs->mode_set(bridge, mode, adjusted_mode); 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ciEXPORT_SYMBOL(drm_bridge_chain_mode_set); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci/** 58362306a36Sopenharmony_ci * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain 58462306a36Sopenharmony_ci * @bridge: bridge control structure 58562306a36Sopenharmony_ci * @old_state: old atomic state 58662306a36Sopenharmony_ci * 58762306a36Sopenharmony_ci * Calls &drm_bridge_funcs.atomic_disable (falls back on 58862306a36Sopenharmony_ci * &drm_bridge_funcs.disable) op for all the bridges in the encoder chain, 58962306a36Sopenharmony_ci * starting from the last bridge to the first. These are called before calling 59062306a36Sopenharmony_ci * &drm_encoder_helper_funcs.atomic_disable 59162306a36Sopenharmony_ci * 59262306a36Sopenharmony_ci * Note: the bridge passed should be the one closest to the encoder 59362306a36Sopenharmony_ci */ 59462306a36Sopenharmony_civoid drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, 59562306a36Sopenharmony_ci struct drm_atomic_state *old_state) 59662306a36Sopenharmony_ci{ 59762306a36Sopenharmony_ci struct drm_encoder *encoder; 59862306a36Sopenharmony_ci struct drm_bridge *iter; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci if (!bridge) 60162306a36Sopenharmony_ci return; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci encoder = bridge->encoder; 60462306a36Sopenharmony_ci list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { 60562306a36Sopenharmony_ci if (iter->funcs->atomic_disable) { 60662306a36Sopenharmony_ci struct drm_bridge_state *old_bridge_state; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci old_bridge_state = 60962306a36Sopenharmony_ci drm_atomic_get_old_bridge_state(old_state, 61062306a36Sopenharmony_ci iter); 61162306a36Sopenharmony_ci if (WARN_ON(!old_bridge_state)) 61262306a36Sopenharmony_ci return; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci iter->funcs->atomic_disable(iter, old_bridge_state); 61562306a36Sopenharmony_ci } else if (iter->funcs->disable) { 61662306a36Sopenharmony_ci iter->funcs->disable(iter); 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci if (iter == bridge) 62062306a36Sopenharmony_ci break; 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci} 62362306a36Sopenharmony_ciEXPORT_SYMBOL(drm_atomic_bridge_chain_disable); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_cistatic void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge, 62662306a36Sopenharmony_ci struct drm_atomic_state *old_state) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci if (old_state && bridge->funcs->atomic_post_disable) { 62962306a36Sopenharmony_ci struct drm_bridge_state *old_bridge_state; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci old_bridge_state = 63262306a36Sopenharmony_ci drm_atomic_get_old_bridge_state(old_state, 63362306a36Sopenharmony_ci bridge); 63462306a36Sopenharmony_ci if (WARN_ON(!old_bridge_state)) 63562306a36Sopenharmony_ci return; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci bridge->funcs->atomic_post_disable(bridge, 63862306a36Sopenharmony_ci old_bridge_state); 63962306a36Sopenharmony_ci } else if (bridge->funcs->post_disable) { 64062306a36Sopenharmony_ci bridge->funcs->post_disable(bridge); 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci} 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci/** 64562306a36Sopenharmony_ci * drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges 64662306a36Sopenharmony_ci * in the encoder chain 64762306a36Sopenharmony_ci * @bridge: bridge control structure 64862306a36Sopenharmony_ci * @old_state: old atomic state 64962306a36Sopenharmony_ci * 65062306a36Sopenharmony_ci * Calls &drm_bridge_funcs.atomic_post_disable (falls back on 65162306a36Sopenharmony_ci * &drm_bridge_funcs.post_disable) op for all the bridges in the encoder chain, 65262306a36Sopenharmony_ci * starting from the first bridge to the last. These are called after completing 65362306a36Sopenharmony_ci * &drm_encoder_helper_funcs.atomic_disable 65462306a36Sopenharmony_ci * 65562306a36Sopenharmony_ci * If a bridge sets @pre_enable_prev_first, then the @post_disable for that 65662306a36Sopenharmony_ci * bridge will be called before the previous one to reverse the @pre_enable 65762306a36Sopenharmony_ci * calling direction. 65862306a36Sopenharmony_ci * 65962306a36Sopenharmony_ci * Note: the bridge passed should be the one closest to the encoder 66062306a36Sopenharmony_ci */ 66162306a36Sopenharmony_civoid drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, 66262306a36Sopenharmony_ci struct drm_atomic_state *old_state) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci struct drm_encoder *encoder; 66562306a36Sopenharmony_ci struct drm_bridge *next, *limit; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci if (!bridge) 66862306a36Sopenharmony_ci return; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci encoder = bridge->encoder; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { 67362306a36Sopenharmony_ci limit = NULL; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci if (!list_is_last(&bridge->chain_node, &encoder->bridge_chain)) { 67662306a36Sopenharmony_ci next = list_next_entry(bridge, chain_node); 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci if (next->pre_enable_prev_first) { 67962306a36Sopenharmony_ci /* next bridge had requested that prev 68062306a36Sopenharmony_ci * was enabled first, so disabled last 68162306a36Sopenharmony_ci */ 68262306a36Sopenharmony_ci limit = next; 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci /* Find the next bridge that has NOT requested 68562306a36Sopenharmony_ci * prev to be enabled first / disabled last 68662306a36Sopenharmony_ci */ 68762306a36Sopenharmony_ci list_for_each_entry_from(next, &encoder->bridge_chain, 68862306a36Sopenharmony_ci chain_node) { 68962306a36Sopenharmony_ci if (next->pre_enable_prev_first) { 69062306a36Sopenharmony_ci next = list_prev_entry(next, chain_node); 69162306a36Sopenharmony_ci limit = next; 69262306a36Sopenharmony_ci break; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci /* Call these bridges in reverse order */ 69762306a36Sopenharmony_ci list_for_each_entry_from_reverse(next, &encoder->bridge_chain, 69862306a36Sopenharmony_ci chain_node) { 69962306a36Sopenharmony_ci if (next == bridge) 70062306a36Sopenharmony_ci break; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci drm_atomic_bridge_call_post_disable(next, 70362306a36Sopenharmony_ci old_state); 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci } 70662306a36Sopenharmony_ci } 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci drm_atomic_bridge_call_post_disable(bridge, old_state); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci if (limit) 71162306a36Sopenharmony_ci /* Jump all bridges that we have already post_disabled */ 71262306a36Sopenharmony_ci bridge = limit; 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci} 71562306a36Sopenharmony_ciEXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_cistatic void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge, 71862306a36Sopenharmony_ci struct drm_atomic_state *old_state) 71962306a36Sopenharmony_ci{ 72062306a36Sopenharmony_ci if (old_state && bridge->funcs->atomic_pre_enable) { 72162306a36Sopenharmony_ci struct drm_bridge_state *old_bridge_state; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci old_bridge_state = 72462306a36Sopenharmony_ci drm_atomic_get_old_bridge_state(old_state, 72562306a36Sopenharmony_ci bridge); 72662306a36Sopenharmony_ci if (WARN_ON(!old_bridge_state)) 72762306a36Sopenharmony_ci return; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci bridge->funcs->atomic_pre_enable(bridge, old_bridge_state); 73062306a36Sopenharmony_ci } else if (bridge->funcs->pre_enable) { 73162306a36Sopenharmony_ci bridge->funcs->pre_enable(bridge); 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci} 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci/** 73662306a36Sopenharmony_ci * drm_atomic_bridge_chain_pre_enable - prepares for enabling all bridges in 73762306a36Sopenharmony_ci * the encoder chain 73862306a36Sopenharmony_ci * @bridge: bridge control structure 73962306a36Sopenharmony_ci * @old_state: old atomic state 74062306a36Sopenharmony_ci * 74162306a36Sopenharmony_ci * Calls &drm_bridge_funcs.atomic_pre_enable (falls back on 74262306a36Sopenharmony_ci * &drm_bridge_funcs.pre_enable) op for all the bridges in the encoder chain, 74362306a36Sopenharmony_ci * starting from the last bridge to the first. These are called before calling 74462306a36Sopenharmony_ci * &drm_encoder_helper_funcs.atomic_enable 74562306a36Sopenharmony_ci * 74662306a36Sopenharmony_ci * If a bridge sets @pre_enable_prev_first, then the pre_enable for the 74762306a36Sopenharmony_ci * prev bridge will be called before pre_enable of this bridge. 74862306a36Sopenharmony_ci * 74962306a36Sopenharmony_ci * Note: the bridge passed should be the one closest to the encoder 75062306a36Sopenharmony_ci */ 75162306a36Sopenharmony_civoid drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, 75262306a36Sopenharmony_ci struct drm_atomic_state *old_state) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci struct drm_encoder *encoder; 75562306a36Sopenharmony_ci struct drm_bridge *iter, *next, *limit; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci if (!bridge) 75862306a36Sopenharmony_ci return; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci encoder = bridge->encoder; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { 76362306a36Sopenharmony_ci if (iter->pre_enable_prev_first) { 76462306a36Sopenharmony_ci next = iter; 76562306a36Sopenharmony_ci limit = bridge; 76662306a36Sopenharmony_ci list_for_each_entry_from_reverse(next, 76762306a36Sopenharmony_ci &encoder->bridge_chain, 76862306a36Sopenharmony_ci chain_node) { 76962306a36Sopenharmony_ci if (next == bridge) 77062306a36Sopenharmony_ci break; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci if (!next->pre_enable_prev_first) { 77362306a36Sopenharmony_ci /* Found first bridge that does NOT 77462306a36Sopenharmony_ci * request prev to be enabled first 77562306a36Sopenharmony_ci */ 77662306a36Sopenharmony_ci limit = list_prev_entry(next, chain_node); 77762306a36Sopenharmony_ci break; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci list_for_each_entry_from(next, &encoder->bridge_chain, chain_node) { 78262306a36Sopenharmony_ci /* Call requested prev bridge pre_enable 78362306a36Sopenharmony_ci * in order. 78462306a36Sopenharmony_ci */ 78562306a36Sopenharmony_ci if (next == iter) 78662306a36Sopenharmony_ci /* At the first bridge to request prev 78762306a36Sopenharmony_ci * bridges called first. 78862306a36Sopenharmony_ci */ 78962306a36Sopenharmony_ci break; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci drm_atomic_bridge_call_pre_enable(next, old_state); 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci drm_atomic_bridge_call_pre_enable(iter, old_state); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci if (iter->pre_enable_prev_first) 79862306a36Sopenharmony_ci /* Jump all bridges that we have already pre_enabled */ 79962306a36Sopenharmony_ci iter = limit; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci if (iter == bridge) 80262306a36Sopenharmony_ci break; 80362306a36Sopenharmony_ci } 80462306a36Sopenharmony_ci} 80562306a36Sopenharmony_ciEXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci/** 80862306a36Sopenharmony_ci * drm_atomic_bridge_chain_enable - enables all bridges in the encoder chain 80962306a36Sopenharmony_ci * @bridge: bridge control structure 81062306a36Sopenharmony_ci * @old_state: old atomic state 81162306a36Sopenharmony_ci * 81262306a36Sopenharmony_ci * Calls &drm_bridge_funcs.atomic_enable (falls back on 81362306a36Sopenharmony_ci * &drm_bridge_funcs.enable) op for all the bridges in the encoder chain, 81462306a36Sopenharmony_ci * starting from the first bridge to the last. These are called after completing 81562306a36Sopenharmony_ci * &drm_encoder_helper_funcs.atomic_enable 81662306a36Sopenharmony_ci * 81762306a36Sopenharmony_ci * Note: the bridge passed should be the one closest to the encoder 81862306a36Sopenharmony_ci */ 81962306a36Sopenharmony_civoid drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, 82062306a36Sopenharmony_ci struct drm_atomic_state *old_state) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci struct drm_encoder *encoder; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci if (!bridge) 82562306a36Sopenharmony_ci return; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci encoder = bridge->encoder; 82862306a36Sopenharmony_ci list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { 82962306a36Sopenharmony_ci if (bridge->funcs->atomic_enable) { 83062306a36Sopenharmony_ci struct drm_bridge_state *old_bridge_state; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci old_bridge_state = 83362306a36Sopenharmony_ci drm_atomic_get_old_bridge_state(old_state, 83462306a36Sopenharmony_ci bridge); 83562306a36Sopenharmony_ci if (WARN_ON(!old_bridge_state)) 83662306a36Sopenharmony_ci return; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci bridge->funcs->atomic_enable(bridge, old_bridge_state); 83962306a36Sopenharmony_ci } else if (bridge->funcs->enable) { 84062306a36Sopenharmony_ci bridge->funcs->enable(bridge); 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci } 84362306a36Sopenharmony_ci} 84462306a36Sopenharmony_ciEXPORT_SYMBOL(drm_atomic_bridge_chain_enable); 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_cistatic int drm_atomic_bridge_check(struct drm_bridge *bridge, 84762306a36Sopenharmony_ci struct drm_crtc_state *crtc_state, 84862306a36Sopenharmony_ci struct drm_connector_state *conn_state) 84962306a36Sopenharmony_ci{ 85062306a36Sopenharmony_ci if (bridge->funcs->atomic_check) { 85162306a36Sopenharmony_ci struct drm_bridge_state *bridge_state; 85262306a36Sopenharmony_ci int ret; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state, 85562306a36Sopenharmony_ci bridge); 85662306a36Sopenharmony_ci if (WARN_ON(!bridge_state)) 85762306a36Sopenharmony_ci return -EINVAL; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci ret = bridge->funcs->atomic_check(bridge, bridge_state, 86062306a36Sopenharmony_ci crtc_state, conn_state); 86162306a36Sopenharmony_ci if (ret) 86262306a36Sopenharmony_ci return ret; 86362306a36Sopenharmony_ci } else if (bridge->funcs->mode_fixup) { 86462306a36Sopenharmony_ci if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode, 86562306a36Sopenharmony_ci &crtc_state->adjusted_mode)) 86662306a36Sopenharmony_ci return -EINVAL; 86762306a36Sopenharmony_ci } 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci return 0; 87062306a36Sopenharmony_ci} 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_cistatic int select_bus_fmt_recursive(struct drm_bridge *first_bridge, 87362306a36Sopenharmony_ci struct drm_bridge *cur_bridge, 87462306a36Sopenharmony_ci struct drm_crtc_state *crtc_state, 87562306a36Sopenharmony_ci struct drm_connector_state *conn_state, 87662306a36Sopenharmony_ci u32 out_bus_fmt) 87762306a36Sopenharmony_ci{ 87862306a36Sopenharmony_ci unsigned int i, num_in_bus_fmts = 0; 87962306a36Sopenharmony_ci struct drm_bridge_state *cur_state; 88062306a36Sopenharmony_ci struct drm_bridge *prev_bridge; 88162306a36Sopenharmony_ci u32 *in_bus_fmts; 88262306a36Sopenharmony_ci int ret; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci prev_bridge = drm_bridge_get_prev_bridge(cur_bridge); 88562306a36Sopenharmony_ci cur_state = drm_atomic_get_new_bridge_state(crtc_state->state, 88662306a36Sopenharmony_ci cur_bridge); 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci /* 88962306a36Sopenharmony_ci * If bus format negotiation is not supported by this bridge, let's 89062306a36Sopenharmony_ci * pass MEDIA_BUS_FMT_FIXED to the previous bridge in the chain and 89162306a36Sopenharmony_ci * hope that it can handle this situation gracefully (by providing 89262306a36Sopenharmony_ci * appropriate default values). 89362306a36Sopenharmony_ci */ 89462306a36Sopenharmony_ci if (!cur_bridge->funcs->atomic_get_input_bus_fmts) { 89562306a36Sopenharmony_ci if (cur_bridge != first_bridge) { 89662306a36Sopenharmony_ci ret = select_bus_fmt_recursive(first_bridge, 89762306a36Sopenharmony_ci prev_bridge, crtc_state, 89862306a36Sopenharmony_ci conn_state, 89962306a36Sopenharmony_ci MEDIA_BUS_FMT_FIXED); 90062306a36Sopenharmony_ci if (ret) 90162306a36Sopenharmony_ci return ret; 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci /* 90562306a36Sopenharmony_ci * Driver does not implement the atomic state hooks, but that's 90662306a36Sopenharmony_ci * fine, as long as it does not access the bridge state. 90762306a36Sopenharmony_ci */ 90862306a36Sopenharmony_ci if (cur_state) { 90962306a36Sopenharmony_ci cur_state->input_bus_cfg.format = MEDIA_BUS_FMT_FIXED; 91062306a36Sopenharmony_ci cur_state->output_bus_cfg.format = out_bus_fmt; 91162306a36Sopenharmony_ci } 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci return 0; 91462306a36Sopenharmony_ci } 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci /* 91762306a36Sopenharmony_ci * If the driver implements ->atomic_get_input_bus_fmts() it 91862306a36Sopenharmony_ci * should also implement the atomic state hooks. 91962306a36Sopenharmony_ci */ 92062306a36Sopenharmony_ci if (WARN_ON(!cur_state)) 92162306a36Sopenharmony_ci return -EINVAL; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci in_bus_fmts = cur_bridge->funcs->atomic_get_input_bus_fmts(cur_bridge, 92462306a36Sopenharmony_ci cur_state, 92562306a36Sopenharmony_ci crtc_state, 92662306a36Sopenharmony_ci conn_state, 92762306a36Sopenharmony_ci out_bus_fmt, 92862306a36Sopenharmony_ci &num_in_bus_fmts); 92962306a36Sopenharmony_ci if (!num_in_bus_fmts) 93062306a36Sopenharmony_ci return -ENOTSUPP; 93162306a36Sopenharmony_ci else if (!in_bus_fmts) 93262306a36Sopenharmony_ci return -ENOMEM; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci if (first_bridge == cur_bridge) { 93562306a36Sopenharmony_ci cur_state->input_bus_cfg.format = in_bus_fmts[0]; 93662306a36Sopenharmony_ci cur_state->output_bus_cfg.format = out_bus_fmt; 93762306a36Sopenharmony_ci kfree(in_bus_fmts); 93862306a36Sopenharmony_ci return 0; 93962306a36Sopenharmony_ci } 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci for (i = 0; i < num_in_bus_fmts; i++) { 94262306a36Sopenharmony_ci ret = select_bus_fmt_recursive(first_bridge, prev_bridge, 94362306a36Sopenharmony_ci crtc_state, conn_state, 94462306a36Sopenharmony_ci in_bus_fmts[i]); 94562306a36Sopenharmony_ci if (ret != -ENOTSUPP) 94662306a36Sopenharmony_ci break; 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci if (!ret) { 95062306a36Sopenharmony_ci cur_state->input_bus_cfg.format = in_bus_fmts[i]; 95162306a36Sopenharmony_ci cur_state->output_bus_cfg.format = out_bus_fmt; 95262306a36Sopenharmony_ci } 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci kfree(in_bus_fmts); 95562306a36Sopenharmony_ci return ret; 95662306a36Sopenharmony_ci} 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci/* 95962306a36Sopenharmony_ci * This function is called by &drm_atomic_bridge_chain_check() just before 96062306a36Sopenharmony_ci * calling &drm_bridge_funcs.atomic_check() on all elements of the chain. 96162306a36Sopenharmony_ci * It performs bus format negotiation between bridge elements. The negotiation 96262306a36Sopenharmony_ci * happens in reverse order, starting from the last element in the chain up to 96362306a36Sopenharmony_ci * @bridge. 96462306a36Sopenharmony_ci * 96562306a36Sopenharmony_ci * Negotiation starts by retrieving supported output bus formats on the last 96662306a36Sopenharmony_ci * bridge element and testing them one by one. The test is recursive, meaning 96762306a36Sopenharmony_ci * that for each tested output format, the whole chain will be walked backward, 96862306a36Sopenharmony_ci * and each element will have to choose an input bus format that can be 96962306a36Sopenharmony_ci * transcoded to the requested output format. When a bridge element does not 97062306a36Sopenharmony_ci * support transcoding into a specific output format -ENOTSUPP is returned and 97162306a36Sopenharmony_ci * the next bridge element will have to try a different format. If none of the 97262306a36Sopenharmony_ci * combinations worked, -ENOTSUPP is returned and the atomic modeset will fail. 97362306a36Sopenharmony_ci * 97462306a36Sopenharmony_ci * This implementation is relying on 97562306a36Sopenharmony_ci * &drm_bridge_funcs.atomic_get_output_bus_fmts() and 97662306a36Sopenharmony_ci * &drm_bridge_funcs.atomic_get_input_bus_fmts() to gather supported 97762306a36Sopenharmony_ci * input/output formats. 97862306a36Sopenharmony_ci * 97962306a36Sopenharmony_ci * When &drm_bridge_funcs.atomic_get_output_bus_fmts() is not implemented by 98062306a36Sopenharmony_ci * the last element of the chain, &drm_atomic_bridge_chain_select_bus_fmts() 98162306a36Sopenharmony_ci * tries a single format: &drm_connector.display_info.bus_formats[0] if 98262306a36Sopenharmony_ci * available, MEDIA_BUS_FMT_FIXED otherwise. 98362306a36Sopenharmony_ci * 98462306a36Sopenharmony_ci * When &drm_bridge_funcs.atomic_get_input_bus_fmts() is not implemented, 98562306a36Sopenharmony_ci * &drm_atomic_bridge_chain_select_bus_fmts() skips the negotiation on the 98662306a36Sopenharmony_ci * bridge element that lacks this hook and asks the previous element in the 98762306a36Sopenharmony_ci * chain to try MEDIA_BUS_FMT_FIXED. It's up to bridge drivers to decide what 98862306a36Sopenharmony_ci * to do in that case (fail if they want to enforce bus format negotiation, or 98962306a36Sopenharmony_ci * provide a reasonable default if they need to support pipelines where not 99062306a36Sopenharmony_ci * all elements support bus format negotiation). 99162306a36Sopenharmony_ci */ 99262306a36Sopenharmony_cistatic int 99362306a36Sopenharmony_cidrm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge, 99462306a36Sopenharmony_ci struct drm_crtc_state *crtc_state, 99562306a36Sopenharmony_ci struct drm_connector_state *conn_state) 99662306a36Sopenharmony_ci{ 99762306a36Sopenharmony_ci struct drm_connector *conn = conn_state->connector; 99862306a36Sopenharmony_ci struct drm_encoder *encoder = bridge->encoder; 99962306a36Sopenharmony_ci struct drm_bridge_state *last_bridge_state; 100062306a36Sopenharmony_ci unsigned int i, num_out_bus_fmts = 0; 100162306a36Sopenharmony_ci struct drm_bridge *last_bridge; 100262306a36Sopenharmony_ci u32 *out_bus_fmts; 100362306a36Sopenharmony_ci int ret = 0; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci last_bridge = list_last_entry(&encoder->bridge_chain, 100662306a36Sopenharmony_ci struct drm_bridge, chain_node); 100762306a36Sopenharmony_ci last_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state, 100862306a36Sopenharmony_ci last_bridge); 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci if (last_bridge->funcs->atomic_get_output_bus_fmts) { 101162306a36Sopenharmony_ci const struct drm_bridge_funcs *funcs = last_bridge->funcs; 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci /* 101462306a36Sopenharmony_ci * If the driver implements ->atomic_get_output_bus_fmts() it 101562306a36Sopenharmony_ci * should also implement the atomic state hooks. 101662306a36Sopenharmony_ci */ 101762306a36Sopenharmony_ci if (WARN_ON(!last_bridge_state)) 101862306a36Sopenharmony_ci return -EINVAL; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci out_bus_fmts = funcs->atomic_get_output_bus_fmts(last_bridge, 102162306a36Sopenharmony_ci last_bridge_state, 102262306a36Sopenharmony_ci crtc_state, 102362306a36Sopenharmony_ci conn_state, 102462306a36Sopenharmony_ci &num_out_bus_fmts); 102562306a36Sopenharmony_ci if (!num_out_bus_fmts) 102662306a36Sopenharmony_ci return -ENOTSUPP; 102762306a36Sopenharmony_ci else if (!out_bus_fmts) 102862306a36Sopenharmony_ci return -ENOMEM; 102962306a36Sopenharmony_ci } else { 103062306a36Sopenharmony_ci num_out_bus_fmts = 1; 103162306a36Sopenharmony_ci out_bus_fmts = kmalloc(sizeof(*out_bus_fmts), GFP_KERNEL); 103262306a36Sopenharmony_ci if (!out_bus_fmts) 103362306a36Sopenharmony_ci return -ENOMEM; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci if (conn->display_info.num_bus_formats && 103662306a36Sopenharmony_ci conn->display_info.bus_formats) 103762306a36Sopenharmony_ci out_bus_fmts[0] = conn->display_info.bus_formats[0]; 103862306a36Sopenharmony_ci else 103962306a36Sopenharmony_ci out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED; 104062306a36Sopenharmony_ci } 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci for (i = 0; i < num_out_bus_fmts; i++) { 104362306a36Sopenharmony_ci ret = select_bus_fmt_recursive(bridge, last_bridge, crtc_state, 104462306a36Sopenharmony_ci conn_state, out_bus_fmts[i]); 104562306a36Sopenharmony_ci if (ret != -ENOTSUPP) 104662306a36Sopenharmony_ci break; 104762306a36Sopenharmony_ci } 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci kfree(out_bus_fmts); 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci return ret; 105262306a36Sopenharmony_ci} 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_cistatic void 105562306a36Sopenharmony_cidrm_atomic_bridge_propagate_bus_flags(struct drm_bridge *bridge, 105662306a36Sopenharmony_ci struct drm_connector *conn, 105762306a36Sopenharmony_ci struct drm_atomic_state *state) 105862306a36Sopenharmony_ci{ 105962306a36Sopenharmony_ci struct drm_bridge_state *bridge_state, *next_bridge_state; 106062306a36Sopenharmony_ci struct drm_bridge *next_bridge; 106162306a36Sopenharmony_ci u32 output_flags = 0; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci bridge_state = drm_atomic_get_new_bridge_state(state, bridge); 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci /* No bridge state attached to this bridge => nothing to propagate. */ 106662306a36Sopenharmony_ci if (!bridge_state) 106762306a36Sopenharmony_ci return; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci next_bridge = drm_bridge_get_next_bridge(bridge); 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci /* 107262306a36Sopenharmony_ci * Let's try to apply the most common case here, that is, propagate 107362306a36Sopenharmony_ci * display_info flags for the last bridge, and propagate the input 107462306a36Sopenharmony_ci * flags of the next bridge element to the output end of the current 107562306a36Sopenharmony_ci * bridge when the bridge is not the last one. 107662306a36Sopenharmony_ci * There are exceptions to this rule, like when signal inversion is 107762306a36Sopenharmony_ci * happening at the board level, but that's something drivers can deal 107862306a36Sopenharmony_ci * with from their &drm_bridge_funcs.atomic_check() implementation by 107962306a36Sopenharmony_ci * simply overriding the flags value we've set here. 108062306a36Sopenharmony_ci */ 108162306a36Sopenharmony_ci if (!next_bridge) { 108262306a36Sopenharmony_ci output_flags = conn->display_info.bus_flags; 108362306a36Sopenharmony_ci } else { 108462306a36Sopenharmony_ci next_bridge_state = drm_atomic_get_new_bridge_state(state, 108562306a36Sopenharmony_ci next_bridge); 108662306a36Sopenharmony_ci /* 108762306a36Sopenharmony_ci * No bridge state attached to the next bridge, just leave the 108862306a36Sopenharmony_ci * flags to 0. 108962306a36Sopenharmony_ci */ 109062306a36Sopenharmony_ci if (next_bridge_state) 109162306a36Sopenharmony_ci output_flags = next_bridge_state->input_bus_cfg.flags; 109262306a36Sopenharmony_ci } 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci bridge_state->output_bus_cfg.flags = output_flags; 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci /* 109762306a36Sopenharmony_ci * Propagate the output flags to the input end of the bridge. Again, it's 109862306a36Sopenharmony_ci * not necessarily what all bridges want, but that's what most of them 109962306a36Sopenharmony_ci * do, and by doing that by default we avoid forcing drivers to 110062306a36Sopenharmony_ci * duplicate the "dummy propagation" logic. 110162306a36Sopenharmony_ci */ 110262306a36Sopenharmony_ci bridge_state->input_bus_cfg.flags = output_flags; 110362306a36Sopenharmony_ci} 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci/** 110662306a36Sopenharmony_ci * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain 110762306a36Sopenharmony_ci * @bridge: bridge control structure 110862306a36Sopenharmony_ci * @crtc_state: new CRTC state 110962306a36Sopenharmony_ci * @conn_state: new connector state 111062306a36Sopenharmony_ci * 111162306a36Sopenharmony_ci * First trigger a bus format negotiation before calling 111262306a36Sopenharmony_ci * &drm_bridge_funcs.atomic_check() (falls back on 111362306a36Sopenharmony_ci * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain, 111462306a36Sopenharmony_ci * starting from the last bridge to the first. These are called before calling 111562306a36Sopenharmony_ci * &drm_encoder_helper_funcs.atomic_check() 111662306a36Sopenharmony_ci * 111762306a36Sopenharmony_ci * RETURNS: 111862306a36Sopenharmony_ci * 0 on success, a negative error code on failure 111962306a36Sopenharmony_ci */ 112062306a36Sopenharmony_ciint drm_atomic_bridge_chain_check(struct drm_bridge *bridge, 112162306a36Sopenharmony_ci struct drm_crtc_state *crtc_state, 112262306a36Sopenharmony_ci struct drm_connector_state *conn_state) 112362306a36Sopenharmony_ci{ 112462306a36Sopenharmony_ci struct drm_connector *conn = conn_state->connector; 112562306a36Sopenharmony_ci struct drm_encoder *encoder; 112662306a36Sopenharmony_ci struct drm_bridge *iter; 112762306a36Sopenharmony_ci int ret; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci if (!bridge) 113062306a36Sopenharmony_ci return 0; 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci ret = drm_atomic_bridge_chain_select_bus_fmts(bridge, crtc_state, 113362306a36Sopenharmony_ci conn_state); 113462306a36Sopenharmony_ci if (ret) 113562306a36Sopenharmony_ci return ret; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci encoder = bridge->encoder; 113862306a36Sopenharmony_ci list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { 113962306a36Sopenharmony_ci int ret; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci /* 114262306a36Sopenharmony_ci * Bus flags are propagated by default. If a bridge needs to 114362306a36Sopenharmony_ci * tweak the input bus flags for any reason, it should happen 114462306a36Sopenharmony_ci * in its &drm_bridge_funcs.atomic_check() implementation such 114562306a36Sopenharmony_ci * that preceding bridges in the chain can propagate the new 114662306a36Sopenharmony_ci * bus flags. 114762306a36Sopenharmony_ci */ 114862306a36Sopenharmony_ci drm_atomic_bridge_propagate_bus_flags(iter, conn, 114962306a36Sopenharmony_ci crtc_state->state); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci ret = drm_atomic_bridge_check(iter, crtc_state, conn_state); 115262306a36Sopenharmony_ci if (ret) 115362306a36Sopenharmony_ci return ret; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci if (iter == bridge) 115662306a36Sopenharmony_ci break; 115762306a36Sopenharmony_ci } 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci return 0; 116062306a36Sopenharmony_ci} 116162306a36Sopenharmony_ciEXPORT_SYMBOL(drm_atomic_bridge_chain_check); 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci/** 116462306a36Sopenharmony_ci * drm_bridge_detect - check if anything is attached to the bridge output 116562306a36Sopenharmony_ci * @bridge: bridge control structure 116662306a36Sopenharmony_ci * 116762306a36Sopenharmony_ci * If the bridge supports output detection, as reported by the 116862306a36Sopenharmony_ci * DRM_BRIDGE_OP_DETECT bridge ops flag, call &drm_bridge_funcs.detect for the 116962306a36Sopenharmony_ci * bridge and return the connection status. Otherwise return 117062306a36Sopenharmony_ci * connector_status_unknown. 117162306a36Sopenharmony_ci * 117262306a36Sopenharmony_ci * RETURNS: 117362306a36Sopenharmony_ci * The detection status on success, or connector_status_unknown if the bridge 117462306a36Sopenharmony_ci * doesn't support output detection. 117562306a36Sopenharmony_ci */ 117662306a36Sopenharmony_cienum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge) 117762306a36Sopenharmony_ci{ 117862306a36Sopenharmony_ci if (!(bridge->ops & DRM_BRIDGE_OP_DETECT)) 117962306a36Sopenharmony_ci return connector_status_unknown; 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci return bridge->funcs->detect(bridge); 118262306a36Sopenharmony_ci} 118362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(drm_bridge_detect); 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci/** 118662306a36Sopenharmony_ci * drm_bridge_get_modes - fill all modes currently valid for the sink into the 118762306a36Sopenharmony_ci * @connector 118862306a36Sopenharmony_ci * @bridge: bridge control structure 118962306a36Sopenharmony_ci * @connector: the connector to fill with modes 119062306a36Sopenharmony_ci * 119162306a36Sopenharmony_ci * If the bridge supports output modes retrieval, as reported by the 119262306a36Sopenharmony_ci * DRM_BRIDGE_OP_MODES bridge ops flag, call &drm_bridge_funcs.get_modes to 119362306a36Sopenharmony_ci * fill the connector with all valid modes and return the number of modes 119462306a36Sopenharmony_ci * added. Otherwise return 0. 119562306a36Sopenharmony_ci * 119662306a36Sopenharmony_ci * RETURNS: 119762306a36Sopenharmony_ci * The number of modes added to the connector. 119862306a36Sopenharmony_ci */ 119962306a36Sopenharmony_ciint drm_bridge_get_modes(struct drm_bridge *bridge, 120062306a36Sopenharmony_ci struct drm_connector *connector) 120162306a36Sopenharmony_ci{ 120262306a36Sopenharmony_ci if (!(bridge->ops & DRM_BRIDGE_OP_MODES)) 120362306a36Sopenharmony_ci return 0; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci return bridge->funcs->get_modes(bridge, connector); 120662306a36Sopenharmony_ci} 120762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(drm_bridge_get_modes); 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci/** 121062306a36Sopenharmony_ci * drm_bridge_get_edid - get the EDID data of the connected display 121162306a36Sopenharmony_ci * @bridge: bridge control structure 121262306a36Sopenharmony_ci * @connector: the connector to read EDID for 121362306a36Sopenharmony_ci * 121462306a36Sopenharmony_ci * If the bridge supports output EDID retrieval, as reported by the 121562306a36Sopenharmony_ci * DRM_BRIDGE_OP_EDID bridge ops flag, call &drm_bridge_funcs.get_edid to 121662306a36Sopenharmony_ci * get the EDID and return it. Otherwise return NULL. 121762306a36Sopenharmony_ci * 121862306a36Sopenharmony_ci * RETURNS: 121962306a36Sopenharmony_ci * The retrieved EDID on success, or NULL otherwise. 122062306a36Sopenharmony_ci */ 122162306a36Sopenharmony_cistruct edid *drm_bridge_get_edid(struct drm_bridge *bridge, 122262306a36Sopenharmony_ci struct drm_connector *connector) 122362306a36Sopenharmony_ci{ 122462306a36Sopenharmony_ci if (!(bridge->ops & DRM_BRIDGE_OP_EDID)) 122562306a36Sopenharmony_ci return NULL; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci return bridge->funcs->get_edid(bridge, connector); 122862306a36Sopenharmony_ci} 122962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(drm_bridge_get_edid); 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci/** 123262306a36Sopenharmony_ci * drm_bridge_hpd_enable - enable hot plug detection for the bridge 123362306a36Sopenharmony_ci * @bridge: bridge control structure 123462306a36Sopenharmony_ci * @cb: hot-plug detection callback 123562306a36Sopenharmony_ci * @data: data to be passed to the hot-plug detection callback 123662306a36Sopenharmony_ci * 123762306a36Sopenharmony_ci * Call &drm_bridge_funcs.hpd_enable if implemented and register the given @cb 123862306a36Sopenharmony_ci * and @data as hot plug notification callback. From now on the @cb will be 123962306a36Sopenharmony_ci * called with @data when an output status change is detected by the bridge, 124062306a36Sopenharmony_ci * until hot plug notification gets disabled with drm_bridge_hpd_disable(). 124162306a36Sopenharmony_ci * 124262306a36Sopenharmony_ci * Hot plug detection is supported only if the DRM_BRIDGE_OP_HPD flag is set in 124362306a36Sopenharmony_ci * bridge->ops. This function shall not be called when the flag is not set. 124462306a36Sopenharmony_ci * 124562306a36Sopenharmony_ci * Only one hot plug detection callback can be registered at a time, it is an 124662306a36Sopenharmony_ci * error to call this function when hot plug detection is already enabled for 124762306a36Sopenharmony_ci * the bridge. 124862306a36Sopenharmony_ci */ 124962306a36Sopenharmony_civoid drm_bridge_hpd_enable(struct drm_bridge *bridge, 125062306a36Sopenharmony_ci void (*cb)(void *data, 125162306a36Sopenharmony_ci enum drm_connector_status status), 125262306a36Sopenharmony_ci void *data) 125362306a36Sopenharmony_ci{ 125462306a36Sopenharmony_ci if (!(bridge->ops & DRM_BRIDGE_OP_HPD)) 125562306a36Sopenharmony_ci return; 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci mutex_lock(&bridge->hpd_mutex); 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci if (WARN(bridge->hpd_cb, "Hot plug detection already enabled\n")) 126062306a36Sopenharmony_ci goto unlock; 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci bridge->hpd_cb = cb; 126362306a36Sopenharmony_ci bridge->hpd_data = data; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci if (bridge->funcs->hpd_enable) 126662306a36Sopenharmony_ci bridge->funcs->hpd_enable(bridge); 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ciunlock: 126962306a36Sopenharmony_ci mutex_unlock(&bridge->hpd_mutex); 127062306a36Sopenharmony_ci} 127162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(drm_bridge_hpd_enable); 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci/** 127462306a36Sopenharmony_ci * drm_bridge_hpd_disable - disable hot plug detection for the bridge 127562306a36Sopenharmony_ci * @bridge: bridge control structure 127662306a36Sopenharmony_ci * 127762306a36Sopenharmony_ci * Call &drm_bridge_funcs.hpd_disable if implemented and unregister the hot 127862306a36Sopenharmony_ci * plug detection callback previously registered with drm_bridge_hpd_enable(). 127962306a36Sopenharmony_ci * Once this function returns the callback will not be called by the bridge 128062306a36Sopenharmony_ci * when an output status change occurs. 128162306a36Sopenharmony_ci * 128262306a36Sopenharmony_ci * Hot plug detection is supported only if the DRM_BRIDGE_OP_HPD flag is set in 128362306a36Sopenharmony_ci * bridge->ops. This function shall not be called when the flag is not set. 128462306a36Sopenharmony_ci */ 128562306a36Sopenharmony_civoid drm_bridge_hpd_disable(struct drm_bridge *bridge) 128662306a36Sopenharmony_ci{ 128762306a36Sopenharmony_ci if (!(bridge->ops & DRM_BRIDGE_OP_HPD)) 128862306a36Sopenharmony_ci return; 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci mutex_lock(&bridge->hpd_mutex); 129162306a36Sopenharmony_ci if (bridge->funcs->hpd_disable) 129262306a36Sopenharmony_ci bridge->funcs->hpd_disable(bridge); 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci bridge->hpd_cb = NULL; 129562306a36Sopenharmony_ci bridge->hpd_data = NULL; 129662306a36Sopenharmony_ci mutex_unlock(&bridge->hpd_mutex); 129762306a36Sopenharmony_ci} 129862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(drm_bridge_hpd_disable); 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci/** 130162306a36Sopenharmony_ci * drm_bridge_hpd_notify - notify hot plug detection events 130262306a36Sopenharmony_ci * @bridge: bridge control structure 130362306a36Sopenharmony_ci * @status: output connection status 130462306a36Sopenharmony_ci * 130562306a36Sopenharmony_ci * Bridge drivers shall call this function to report hot plug events when they 130662306a36Sopenharmony_ci * detect a change in the output status, when hot plug detection has been 130762306a36Sopenharmony_ci * enabled by drm_bridge_hpd_enable(). 130862306a36Sopenharmony_ci * 130962306a36Sopenharmony_ci * This function shall be called in a context that can sleep. 131062306a36Sopenharmony_ci */ 131162306a36Sopenharmony_civoid drm_bridge_hpd_notify(struct drm_bridge *bridge, 131262306a36Sopenharmony_ci enum drm_connector_status status) 131362306a36Sopenharmony_ci{ 131462306a36Sopenharmony_ci mutex_lock(&bridge->hpd_mutex); 131562306a36Sopenharmony_ci if (bridge->hpd_cb) 131662306a36Sopenharmony_ci bridge->hpd_cb(bridge->hpd_data, status); 131762306a36Sopenharmony_ci mutex_unlock(&bridge->hpd_mutex); 131862306a36Sopenharmony_ci} 131962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(drm_bridge_hpd_notify); 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci#ifdef CONFIG_OF 132262306a36Sopenharmony_ci/** 132362306a36Sopenharmony_ci * of_drm_find_bridge - find the bridge corresponding to the device node in 132462306a36Sopenharmony_ci * the global bridge list 132562306a36Sopenharmony_ci * 132662306a36Sopenharmony_ci * @np: device node 132762306a36Sopenharmony_ci * 132862306a36Sopenharmony_ci * RETURNS: 132962306a36Sopenharmony_ci * drm_bridge control struct on success, NULL on failure 133062306a36Sopenharmony_ci */ 133162306a36Sopenharmony_cistruct drm_bridge *of_drm_find_bridge(struct device_node *np) 133262306a36Sopenharmony_ci{ 133362306a36Sopenharmony_ci struct drm_bridge *bridge; 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci mutex_lock(&bridge_lock); 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci list_for_each_entry(bridge, &bridge_list, list) { 133862306a36Sopenharmony_ci if (bridge->of_node == np) { 133962306a36Sopenharmony_ci mutex_unlock(&bridge_lock); 134062306a36Sopenharmony_ci return bridge; 134162306a36Sopenharmony_ci } 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci mutex_unlock(&bridge_lock); 134562306a36Sopenharmony_ci return NULL; 134662306a36Sopenharmony_ci} 134762306a36Sopenharmony_ciEXPORT_SYMBOL(of_drm_find_bridge); 134862306a36Sopenharmony_ci#endif 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 135162306a36Sopenharmony_cistatic int drm_bridge_chains_info(struct seq_file *m, void *data) 135262306a36Sopenharmony_ci{ 135362306a36Sopenharmony_ci struct drm_debugfs_entry *entry = m->private; 135462306a36Sopenharmony_ci struct drm_device *dev = entry->dev; 135562306a36Sopenharmony_ci struct drm_printer p = drm_seq_file_printer(m); 135662306a36Sopenharmony_ci struct drm_mode_config *config = &dev->mode_config; 135762306a36Sopenharmony_ci struct drm_encoder *encoder; 135862306a36Sopenharmony_ci unsigned int bridge_idx = 0; 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci list_for_each_entry(encoder, &config->encoder_list, head) { 136162306a36Sopenharmony_ci struct drm_bridge *bridge; 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci drm_printf(&p, "encoder[%u]\n", encoder->base.id); 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci drm_for_each_bridge_in_chain(encoder, bridge) { 136662306a36Sopenharmony_ci drm_printf(&p, "\tbridge[%u] type: %u, ops: %#x", 136762306a36Sopenharmony_ci bridge_idx, bridge->type, bridge->ops); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci#ifdef CONFIG_OF 137062306a36Sopenharmony_ci if (bridge->of_node) 137162306a36Sopenharmony_ci drm_printf(&p, ", OF: %pOFfc", bridge->of_node); 137262306a36Sopenharmony_ci#endif 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci drm_printf(&p, "\n"); 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci bridge_idx++; 137762306a36Sopenharmony_ci } 137862306a36Sopenharmony_ci } 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci return 0; 138162306a36Sopenharmony_ci} 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_cistatic const struct drm_debugfs_info drm_bridge_debugfs_list[] = { 138462306a36Sopenharmony_ci { "bridge_chains", drm_bridge_chains_info, 0 }, 138562306a36Sopenharmony_ci}; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_civoid drm_bridge_debugfs_init(struct drm_minor *minor) 138862306a36Sopenharmony_ci{ 138962306a36Sopenharmony_ci drm_debugfs_add_files(minor->dev, drm_bridge_debugfs_list, 139062306a36Sopenharmony_ci ARRAY_SIZE(drm_bridge_debugfs_list)); 139162306a36Sopenharmony_ci} 139262306a36Sopenharmony_ci#endif 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ciMODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@samsung.com>"); 139562306a36Sopenharmony_ciMODULE_DESCRIPTION("DRM bridge infrastructure"); 139662306a36Sopenharmony_ciMODULE_LICENSE("GPL and additional rights"); 1397