xref: /openbmc/linux/drivers/gpu/drm/drm_bridge.c (revision 2b6aaf7b)
13d3f8b1fSAjay Kumar /*
23d3f8b1fSAjay Kumar  * Copyright (c) 2014 Samsung Electronics Co., Ltd
33d3f8b1fSAjay Kumar  *
43d3f8b1fSAjay Kumar  * Permission is hereby granted, free of charge, to any person obtaining a
53d3f8b1fSAjay Kumar  * copy of this software and associated documentation files (the "Software"),
63d3f8b1fSAjay Kumar  * to deal in the Software without restriction, including without limitation
73d3f8b1fSAjay Kumar  * the rights to use, copy, modify, merge, publish, distribute, sub license,
83d3f8b1fSAjay Kumar  * and/or sell copies of the Software, and to permit persons to whom the
93d3f8b1fSAjay Kumar  * Software is furnished to do so, subject to the following conditions:
103d3f8b1fSAjay Kumar  *
113d3f8b1fSAjay Kumar  * The above copyright notice and this permission notice (including the
123d3f8b1fSAjay Kumar  * next paragraph) shall be included in all copies or substantial portions
133d3f8b1fSAjay Kumar  * of the Software.
143d3f8b1fSAjay Kumar  *
153d3f8b1fSAjay Kumar  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
163d3f8b1fSAjay Kumar  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173d3f8b1fSAjay Kumar  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
183d3f8b1fSAjay Kumar  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
193d3f8b1fSAjay Kumar  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
203d3f8b1fSAjay Kumar  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
213d3f8b1fSAjay Kumar  * DEALINGS IN THE SOFTWARE.
223d3f8b1fSAjay Kumar  */
233d3f8b1fSAjay Kumar 
243d3f8b1fSAjay Kumar #include <linux/err.h>
2572bd9ea3SVille Syrjälä #include <linux/media-bus-format.h>
263d3f8b1fSAjay Kumar #include <linux/module.h>
27199e4e96SDaniel Vetter #include <linux/mutex.h>
283d3f8b1fSAjay Kumar 
2975146591SBoris Brezillon #include <drm/drm_atomic_state_helper.h>
30199e4e96SDaniel Vetter #include <drm/drm_bridge.h>
312b6aaf7bSJani Nikula #include <drm/drm_debugfs.h>
322b6aaf7bSJani Nikula #include <drm/drm_edid.h>
333bb80f24SLaurent Pinchart #include <drm/drm_encoder.h>
348e4bb53cSTomi Valkeinen #include <drm/drm_file.h>
3587ea9580SMaxime Ripard #include <drm/drm_of.h>
36fb8d617fSLaurent Pinchart #include <drm/drm_print.h>
373d3f8b1fSAjay Kumar 
384a878c03SLaurent Pinchart #include "drm_crtc_internal.h"
394a878c03SLaurent Pinchart 
402331b4e4SArchit Taneja /**
412331b4e4SArchit Taneja  * DOC: overview
422331b4e4SArchit Taneja  *
43ea0dd85aSDaniel Vetter  * &struct drm_bridge represents a device that hangs on to an encoder. These are
44da024fe5SDaniel Vetter  * handy when a regular &drm_encoder entity isn't enough to represent the entire
452331b4e4SArchit Taneja  * encoder chain.
462331b4e4SArchit Taneja  *
47da024fe5SDaniel Vetter  * A bridge is always attached to a single &drm_encoder at a time, but can be
480451369bSLaurent Pinchart  * either connected to it directly, or through a chain of bridges::
492331b4e4SArchit Taneja  *
500451369bSLaurent Pinchart  *     [ CRTC ---> ] Encoder ---> Bridge A ---> Bridge B
512331b4e4SArchit Taneja  *
520451369bSLaurent Pinchart  * Here, the output of the encoder feeds to bridge A, and that furthers feeds to
530451369bSLaurent Pinchart  * bridge B. Bridge chains can be arbitrarily long, and shall be fully linear:
540451369bSLaurent Pinchart  * Chaining multiple bridges to the output of a bridge, or the same bridge to
550451369bSLaurent Pinchart  * the output of different bridges, is not supported.
562331b4e4SArchit Taneja  *
578886815fSMaxime Ripard  * &drm_bridge, like &drm_panel, aren't &drm_mode_object entities like planes,
588886815fSMaxime Ripard  * CRTCs, encoders or connectors and hence are not visible to userspace. They
598886815fSMaxime Ripard  * just provide additional hooks to get the desired output at the end of the
608886815fSMaxime Ripard  * encoder chain.
618886815fSMaxime Ripard  */
628886815fSMaxime Ripard 
638886815fSMaxime Ripard /**
648886815fSMaxime Ripard  * DOC:	display driver integration
658886815fSMaxime Ripard  *
660451369bSLaurent Pinchart  * Display drivers are responsible for linking encoders with the first bridge
670451369bSLaurent Pinchart  * in the chains. This is done by acquiring the appropriate bridge with
6887ea9580SMaxime Ripard  * devm_drm_of_get_bridge(). Once acquired, the bridge shall be attached to the
6987ea9580SMaxime Ripard  * encoder with a call to drm_bridge_attach().
702331b4e4SArchit Taneja  *
710451369bSLaurent Pinchart  * Bridges are responsible for linking themselves with the next bridge in the
720451369bSLaurent Pinchart  * chain, if any. This is done the same way as for encoders, with the call to
730451369bSLaurent Pinchart  * drm_bridge_attach() occurring in the &drm_bridge_funcs.attach operation.
740451369bSLaurent Pinchart  *
750451369bSLaurent Pinchart  * Once these links are created, the bridges can participate along with encoder
760451369bSLaurent Pinchart  * functions to perform mode validation and fixup (through
770451369bSLaurent Pinchart  * drm_bridge_chain_mode_valid() and drm_atomic_bridge_chain_check()), mode
780451369bSLaurent Pinchart  * setting (through drm_bridge_chain_mode_set()), enable (through
790451369bSLaurent Pinchart  * drm_atomic_bridge_chain_pre_enable() and drm_atomic_bridge_chain_enable())
800451369bSLaurent Pinchart  * and disable (through drm_atomic_bridge_chain_disable() and
810451369bSLaurent Pinchart  * drm_atomic_bridge_chain_post_disable()). Those functions call the
820451369bSLaurent Pinchart  * corresponding operations provided in &drm_bridge_funcs in sequence for all
830451369bSLaurent Pinchart  * bridges in the chain.
840451369bSLaurent Pinchart  *
850451369bSLaurent Pinchart  * For display drivers that use the atomic helpers
860451369bSLaurent Pinchart  * drm_atomic_helper_check_modeset(),
870451369bSLaurent Pinchart  * drm_atomic_helper_commit_modeset_enables() and
880451369bSLaurent Pinchart  * drm_atomic_helper_commit_modeset_disables() (either directly in hand-rolled
890451369bSLaurent Pinchart  * commit check and commit tail handlers, or through the higher-level
900451369bSLaurent Pinchart  * drm_atomic_helper_check() and drm_atomic_helper_commit_tail() or
910451369bSLaurent Pinchart  * drm_atomic_helper_commit_tail_rpm() helpers), this is done transparently and
920451369bSLaurent Pinchart  * requires no intervention from the driver. For other drivers, the relevant
930451369bSLaurent Pinchart  * DRM bridge chain functions shall be called manually.
940451369bSLaurent Pinchart  *
955e20bdf3SLaurent Pinchart  * Bridges also participate in implementing the &drm_connector at the end of
965e20bdf3SLaurent Pinchart  * the bridge chain. Display drivers may use the drm_bridge_connector_init()
975e20bdf3SLaurent Pinchart  * helper to create the &drm_connector, or implement it manually on top of the
985e20bdf3SLaurent Pinchart  * connector-related operations exposed by the bridge (see the overview
995e20bdf3SLaurent Pinchart  * documentation of bridge operations for more details).
1002331b4e4SArchit Taneja  */
1012331b4e4SArchit Taneja 
102209264a8SMaxime Ripard /**
103209264a8SMaxime Ripard  * DOC: special care dsi
104209264a8SMaxime Ripard  *
105209264a8SMaxime Ripard  * The interaction between the bridges and other frameworks involved in
106209264a8SMaxime Ripard  * the probing of the upstream driver and the bridge driver can be
107209264a8SMaxime Ripard  * challenging. Indeed, there's multiple cases that needs to be
108209264a8SMaxime Ripard  * considered:
109209264a8SMaxime Ripard  *
110209264a8SMaxime Ripard  * - The upstream driver doesn't use the component framework and isn't a
111209264a8SMaxime Ripard  *   MIPI-DSI host. In this case, the bridge driver will probe at some
112209264a8SMaxime Ripard  *   point and the upstream driver should try to probe again by returning
113209264a8SMaxime Ripard  *   EPROBE_DEFER as long as the bridge driver hasn't probed.
114209264a8SMaxime Ripard  *
115209264a8SMaxime Ripard  * - The upstream driver doesn't use the component framework, but is a
116209264a8SMaxime Ripard  *   MIPI-DSI host. The bridge device uses the MIPI-DCS commands to be
117209264a8SMaxime Ripard  *   controlled. In this case, the bridge device is a child of the
118209264a8SMaxime Ripard  *   display device and when it will probe it's assured that the display
119209264a8SMaxime Ripard  *   device (and MIPI-DSI host) is present. The upstream driver will be
120209264a8SMaxime Ripard  *   assured that the bridge driver is connected between the
121209264a8SMaxime Ripard  *   &mipi_dsi_host_ops.attach and &mipi_dsi_host_ops.detach operations.
122209264a8SMaxime Ripard  *   Therefore, it must run mipi_dsi_host_register() in its probe
123209264a8SMaxime Ripard  *   function, and then run drm_bridge_attach() in its
124209264a8SMaxime Ripard  *   &mipi_dsi_host_ops.attach hook.
125209264a8SMaxime Ripard  *
126209264a8SMaxime Ripard  * - The upstream driver uses the component framework and is a MIPI-DSI
127209264a8SMaxime Ripard  *   host. The bridge device uses the MIPI-DCS commands to be
128209264a8SMaxime Ripard  *   controlled. This is the same situation than above, and can run
129209264a8SMaxime Ripard  *   mipi_dsi_host_register() in either its probe or bind hooks.
130209264a8SMaxime Ripard  *
131209264a8SMaxime Ripard  * - The upstream driver uses the component framework and is a MIPI-DSI
132209264a8SMaxime Ripard  *   host. The bridge device uses a separate bus (such as I2C) to be
133209264a8SMaxime Ripard  *   controlled. In this case, there's no correlation between the probe
134209264a8SMaxime Ripard  *   of the bridge and upstream drivers, so care must be taken to avoid
135209264a8SMaxime Ripard  *   an endless EPROBE_DEFER loop, with each driver waiting for the
136209264a8SMaxime Ripard  *   other to probe.
137209264a8SMaxime Ripard  *
138209264a8SMaxime Ripard  * The ideal pattern to cover the last item (and all the others in the
139209264a8SMaxime Ripard  * MIPI-DSI host driver case) is to split the operations like this:
140209264a8SMaxime Ripard  *
141209264a8SMaxime Ripard  * - The MIPI-DSI host driver must run mipi_dsi_host_register() in its
142209264a8SMaxime Ripard  *   probe hook. It will make sure that the MIPI-DSI host sticks around,
143209264a8SMaxime Ripard  *   and that the driver's bind can be called.
144209264a8SMaxime Ripard  *
145209264a8SMaxime Ripard  * - In its probe hook, the bridge driver must try to find its MIPI-DSI
146209264a8SMaxime Ripard  *   host, register as a MIPI-DSI device and attach the MIPI-DSI device
147209264a8SMaxime Ripard  *   to its host. The bridge driver is now functional.
148209264a8SMaxime Ripard  *
149209264a8SMaxime Ripard  * - In its &struct mipi_dsi_host_ops.attach hook, the MIPI-DSI host can
150209264a8SMaxime Ripard  *   now add its component. Its bind hook will now be called and since
151209264a8SMaxime Ripard  *   the bridge driver is attached and registered, we can now look for
152209264a8SMaxime Ripard  *   and attach it.
153209264a8SMaxime Ripard  *
154209264a8SMaxime Ripard  * At this point, we're now certain that both the upstream driver and
155209264a8SMaxime Ripard  * the bridge driver are functional and we can't have a deadlock-like
156209264a8SMaxime Ripard  * situation when probing.
157209264a8SMaxime Ripard  */
158209264a8SMaxime Ripard 
159e373cdbeSDave Stevenson /**
160e373cdbeSDave Stevenson  * DOC: dsi bridge operations
161e373cdbeSDave Stevenson  *
162e373cdbeSDave Stevenson  * DSI host interfaces are expected to be implemented as bridges rather than
163e373cdbeSDave Stevenson  * encoders, however there are a few aspects of their operation that need to
164e373cdbeSDave Stevenson  * be defined in order to provide a consistent interface.
165e373cdbeSDave Stevenson  *
166e373cdbeSDave Stevenson  * A DSI host should keep the PHY powered down until the pre_enable operation is
167e373cdbeSDave Stevenson  * called. All lanes are in an undefined idle state up to this point, and it
168e373cdbeSDave Stevenson  * must not be assumed that it is LP-11.
169e373cdbeSDave Stevenson  * pre_enable should initialise the PHY, set the data lanes to LP-11, and the
170e373cdbeSDave Stevenson  * clock lane to either LP-11 or HS depending on the mode_flag
171e373cdbeSDave Stevenson  * %MIPI_DSI_CLOCK_NON_CONTINUOUS.
172e373cdbeSDave Stevenson  *
173e373cdbeSDave Stevenson  * Ordinarily the downstream bridge DSI peripheral pre_enable will have been
174e373cdbeSDave Stevenson  * called before the DSI host. If the DSI peripheral requires LP-11 and/or
175e373cdbeSDave Stevenson  * the clock lane to be in HS mode prior to pre_enable, then it can set the
176e373cdbeSDave Stevenson  * &pre_enable_prev_first flag to request the pre_enable (and
177e373cdbeSDave Stevenson  * post_disable) order to be altered to enable the DSI host first.
178e373cdbeSDave Stevenson  *
179e373cdbeSDave Stevenson  * Either the CRTC being enabled, or the DSI host enable operation should switch
180e373cdbeSDave Stevenson  * the host to actively transmitting video on the data lanes.
181e373cdbeSDave Stevenson  *
182e373cdbeSDave Stevenson  * The reverse also applies. The DSI host disable operation or stopping the CRTC
183e373cdbeSDave Stevenson  * should stop transmitting video, and the data lanes should return to the LP-11
184e373cdbeSDave Stevenson  * state. The DSI host &post_disable operation should disable the PHY.
185e373cdbeSDave Stevenson  * If the &pre_enable_prev_first flag is set, then the DSI peripheral's
186e373cdbeSDave Stevenson  * bridge &post_disable will be called before the DSI host's post_disable.
187e373cdbeSDave Stevenson  *
188e373cdbeSDave Stevenson  * Whilst it is valid to call &host_transfer prior to pre_enable or after
189e373cdbeSDave Stevenson  * post_disable, the exact state of the lanes is undefined at this point. The
190e373cdbeSDave Stevenson  * DSI host should initialise the interface, transmit the data, and then disable
191e373cdbeSDave Stevenson  * the interface again.
192e373cdbeSDave Stevenson  *
193e373cdbeSDave Stevenson  * Ultra Low Power State (ULPS) is not explicitly supported by DRM. If
194e373cdbeSDave Stevenson  * implemented, it therefore needs to be handled entirely within the DSI Host
195e373cdbeSDave Stevenson  * driver.
196e373cdbeSDave Stevenson  */
197e373cdbeSDave Stevenson 
1983d3f8b1fSAjay Kumar static DEFINE_MUTEX(bridge_lock);
1993d3f8b1fSAjay Kumar static LIST_HEAD(bridge_list);
2003d3f8b1fSAjay Kumar 
2012331b4e4SArchit Taneja /**
2022331b4e4SArchit Taneja  * drm_bridge_add - add the given bridge to the global bridge list
2032331b4e4SArchit Taneja  *
2042331b4e4SArchit Taneja  * @bridge: bridge control structure
2052331b4e4SArchit Taneja  */
drm_bridge_add(struct drm_bridge * bridge)20699286884SInki Dae void drm_bridge_add(struct drm_bridge *bridge)
2073d3f8b1fSAjay Kumar {
20811f6c4b1SLaurent Pinchart 	mutex_init(&bridge->hpd_mutex);
20911f6c4b1SLaurent Pinchart 
2103d3f8b1fSAjay Kumar 	mutex_lock(&bridge_lock);
2113d3f8b1fSAjay Kumar 	list_add_tail(&bridge->list, &bridge_list);
2123d3f8b1fSAjay Kumar 	mutex_unlock(&bridge_lock);
2133d3f8b1fSAjay Kumar }
2143d3f8b1fSAjay Kumar EXPORT_SYMBOL(drm_bridge_add);
2153d3f8b1fSAjay Kumar 
drm_bridge_remove_void(void * bridge)21650e156bdSDouglas Anderson static void drm_bridge_remove_void(void *bridge)
21750e156bdSDouglas Anderson {
21850e156bdSDouglas Anderson 	drm_bridge_remove(bridge);
21950e156bdSDouglas Anderson }
22050e156bdSDouglas Anderson 
22150e156bdSDouglas Anderson /**
22250e156bdSDouglas Anderson  * devm_drm_bridge_add - devm managed version of drm_bridge_add()
22350e156bdSDouglas Anderson  *
22450e156bdSDouglas Anderson  * @dev: device to tie the bridge lifetime to
22550e156bdSDouglas Anderson  * @bridge: bridge control structure
22650e156bdSDouglas Anderson  *
22750e156bdSDouglas Anderson  * This is the managed version of drm_bridge_add() which automatically
22850e156bdSDouglas Anderson  * calls drm_bridge_remove() when @dev is unbound.
22950e156bdSDouglas Anderson  *
23050e156bdSDouglas Anderson  * Return: 0 if no error or negative error code.
23150e156bdSDouglas Anderson  */
devm_drm_bridge_add(struct device * dev,struct drm_bridge * bridge)23250e156bdSDouglas Anderson int devm_drm_bridge_add(struct device *dev, struct drm_bridge *bridge)
23350e156bdSDouglas Anderson {
23450e156bdSDouglas Anderson 	drm_bridge_add(bridge);
23550e156bdSDouglas Anderson 	return devm_add_action_or_reset(dev, drm_bridge_remove_void, bridge);
23650e156bdSDouglas Anderson }
23750e156bdSDouglas Anderson EXPORT_SYMBOL(devm_drm_bridge_add);
23850e156bdSDouglas Anderson 
2392331b4e4SArchit Taneja /**
2402331b4e4SArchit Taneja  * drm_bridge_remove - remove the given bridge from the global bridge list
2412331b4e4SArchit Taneja  *
2422331b4e4SArchit Taneja  * @bridge: bridge control structure
2432331b4e4SArchit Taneja  */
drm_bridge_remove(struct drm_bridge * bridge)2443d3f8b1fSAjay Kumar void drm_bridge_remove(struct drm_bridge *bridge)
2453d3f8b1fSAjay Kumar {
2463d3f8b1fSAjay Kumar 	mutex_lock(&bridge_lock);
2473d3f8b1fSAjay Kumar 	list_del_init(&bridge->list);
2483d3f8b1fSAjay Kumar 	mutex_unlock(&bridge_lock);
24911f6c4b1SLaurent Pinchart 
25011f6c4b1SLaurent Pinchart 	mutex_destroy(&bridge->hpd_mutex);
2513d3f8b1fSAjay Kumar }
2523d3f8b1fSAjay Kumar EXPORT_SYMBOL(drm_bridge_remove);
2533d3f8b1fSAjay Kumar 
25475146591SBoris Brezillon static struct drm_private_state *
drm_bridge_atomic_duplicate_priv_state(struct drm_private_obj * obj)25575146591SBoris Brezillon drm_bridge_atomic_duplicate_priv_state(struct drm_private_obj *obj)
25675146591SBoris Brezillon {
25775146591SBoris Brezillon 	struct drm_bridge *bridge = drm_priv_to_bridge(obj);
25875146591SBoris Brezillon 	struct drm_bridge_state *state;
25975146591SBoris Brezillon 
26075146591SBoris Brezillon 	state = bridge->funcs->atomic_duplicate_state(bridge);
26175146591SBoris Brezillon 	return state ? &state->base : NULL;
26275146591SBoris Brezillon }
26375146591SBoris Brezillon 
26475146591SBoris Brezillon static void
drm_bridge_atomic_destroy_priv_state(struct drm_private_obj * obj,struct drm_private_state * s)26575146591SBoris Brezillon drm_bridge_atomic_destroy_priv_state(struct drm_private_obj *obj,
26675146591SBoris Brezillon 				     struct drm_private_state *s)
26775146591SBoris Brezillon {
26875146591SBoris Brezillon 	struct drm_bridge_state *state = drm_priv_to_bridge_state(s);
26975146591SBoris Brezillon 	struct drm_bridge *bridge = drm_priv_to_bridge(obj);
27075146591SBoris Brezillon 
27175146591SBoris Brezillon 	bridge->funcs->atomic_destroy_state(bridge, state);
27275146591SBoris Brezillon }
27375146591SBoris Brezillon 
27475146591SBoris Brezillon static const struct drm_private_state_funcs drm_bridge_priv_state_funcs = {
27575146591SBoris Brezillon 	.atomic_duplicate_state = drm_bridge_atomic_duplicate_priv_state,
27675146591SBoris Brezillon 	.atomic_destroy_state = drm_bridge_atomic_destroy_priv_state,
27775146591SBoris Brezillon };
27875146591SBoris Brezillon 
2792331b4e4SArchit Taneja /**
2803bb80f24SLaurent Pinchart  * drm_bridge_attach - attach the bridge to an encoder's chain
2812331b4e4SArchit Taneja  *
2823bb80f24SLaurent Pinchart  * @encoder: DRM encoder
2833bb80f24SLaurent Pinchart  * @bridge: bridge to attach
2843bb80f24SLaurent Pinchart  * @previous: previous bridge in the chain (optional)
285a25b988fSLaurent Pinchart  * @flags: DRM_BRIDGE_ATTACH_* flags
2862331b4e4SArchit Taneja  *
2873bb80f24SLaurent Pinchart  * Called by a kms driver to link the bridge to an encoder's chain. The previous
2883bb80f24SLaurent Pinchart  * argument specifies the previous bridge in the chain. If NULL, the bridge is
2893bb80f24SLaurent Pinchart  * linked directly at the encoder's output. Otherwise it is linked at the
2903bb80f24SLaurent Pinchart  * previous bridge's output.
2912331b4e4SArchit Taneja  *
2923bb80f24SLaurent Pinchart  * If non-NULL the previous bridge must be already attached by a call to this
2933bb80f24SLaurent Pinchart  * function.
2942331b4e4SArchit Taneja  *
295169cc4c7SPeter Rosin  * Note that bridges attached to encoders are auto-detached during encoder
296169cc4c7SPeter Rosin  * cleanup in drm_encoder_cleanup(), so drm_bridge_attach() should generally
297169cc4c7SPeter Rosin  * *not* be balanced with a drm_bridge_detach() in driver code.
298169cc4c7SPeter Rosin  *
2992331b4e4SArchit Taneja  * RETURNS:
3002331b4e4SArchit Taneja  * Zero on success, error code on failure
3012331b4e4SArchit Taneja  */
drm_bridge_attach(struct drm_encoder * encoder,struct drm_bridge * bridge,struct drm_bridge * previous,enum drm_bridge_attach_flags flags)3023bb80f24SLaurent Pinchart int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
303a25b988fSLaurent Pinchart 		      struct drm_bridge *previous,
304a25b988fSLaurent Pinchart 		      enum drm_bridge_attach_flags flags)
3053d3f8b1fSAjay Kumar {
3063bb80f24SLaurent Pinchart 	int ret;
3073bb80f24SLaurent Pinchart 
3083bb80f24SLaurent Pinchart 	if (!encoder || !bridge)
3093bb80f24SLaurent Pinchart 		return -EINVAL;
3103bb80f24SLaurent Pinchart 
3113bb80f24SLaurent Pinchart 	if (previous && (!previous->dev || previous->encoder != encoder))
3123d3f8b1fSAjay Kumar 		return -EINVAL;
3133d3f8b1fSAjay Kumar 
3143d3f8b1fSAjay Kumar 	if (bridge->dev)
3153d3f8b1fSAjay Kumar 		return -EBUSY;
3163d3f8b1fSAjay Kumar 
3173bb80f24SLaurent Pinchart 	bridge->dev = encoder->dev;
3183bb80f24SLaurent Pinchart 	bridge->encoder = encoder;
3193d3f8b1fSAjay Kumar 
32005193dc3SBoris Brezillon 	if (previous)
32105193dc3SBoris Brezillon 		list_add(&bridge->chain_node, &previous->chain_node);
32205193dc3SBoris Brezillon 	else
32305193dc3SBoris Brezillon 		list_add(&bridge->chain_node, &encoder->bridge_chain);
32405193dc3SBoris Brezillon 
3253bb80f24SLaurent Pinchart 	if (bridge->funcs->attach) {
326a25b988fSLaurent Pinchart 		ret = bridge->funcs->attach(bridge, flags);
32775146591SBoris Brezillon 		if (ret < 0)
32875146591SBoris Brezillon 			goto err_reset_bridge;
3293d3f8b1fSAjay Kumar 	}
33075146591SBoris Brezillon 
33175146591SBoris Brezillon 	if (bridge->funcs->atomic_reset) {
33275146591SBoris Brezillon 		struct drm_bridge_state *state;
33375146591SBoris Brezillon 
33475146591SBoris Brezillon 		state = bridge->funcs->atomic_reset(bridge);
33575146591SBoris Brezillon 		if (IS_ERR(state)) {
33675146591SBoris Brezillon 			ret = PTR_ERR(state);
33775146591SBoris Brezillon 			goto err_detach_bridge;
33875146591SBoris Brezillon 		}
33975146591SBoris Brezillon 
34075146591SBoris Brezillon 		drm_atomic_private_obj_init(bridge->dev, &bridge->base,
34175146591SBoris Brezillon 					    &state->base,
34275146591SBoris Brezillon 					    &drm_bridge_priv_state_funcs);
34309912635SBoris Brezillon 	}
34409912635SBoris Brezillon 
34509912635SBoris Brezillon 	return 0;
34675146591SBoris Brezillon 
34775146591SBoris Brezillon err_detach_bridge:
34875146591SBoris Brezillon 	if (bridge->funcs->detach)
34975146591SBoris Brezillon 		bridge->funcs->detach(bridge);
35075146591SBoris Brezillon 
35175146591SBoris Brezillon err_reset_bridge:
35275146591SBoris Brezillon 	bridge->dev = NULL;
35375146591SBoris Brezillon 	bridge->encoder = NULL;
35475146591SBoris Brezillon 	list_del(&bridge->chain_node);
355fb8d617fSLaurent Pinchart 
356fb8d617fSLaurent Pinchart #ifdef CONFIG_OF
357fb8d617fSLaurent Pinchart 	DRM_ERROR("failed to attach bridge %pOF to encoder %s: %d\n",
358fb8d617fSLaurent Pinchart 		  bridge->of_node, encoder->name, ret);
359fb8d617fSLaurent Pinchart #else
360fb8d617fSLaurent Pinchart 	DRM_ERROR("failed to attach bridge to encoder %s: %d\n",
361fb8d617fSLaurent Pinchart 		  encoder->name, ret);
362fb8d617fSLaurent Pinchart #endif
363fb8d617fSLaurent Pinchart 
36475146591SBoris Brezillon 	return ret;
36509912635SBoris Brezillon }
3663d3f8b1fSAjay Kumar EXPORT_SYMBOL(drm_bridge_attach);
3673d3f8b1fSAjay Kumar 
drm_bridge_detach(struct drm_bridge * bridge)368cf3bef95SAndrea Merello void drm_bridge_detach(struct drm_bridge *bridge)
369cf3bef95SAndrea Merello {
370cf3bef95SAndrea Merello 	if (WARN_ON(!bridge))
371cf3bef95SAndrea Merello 		return;
372cf3bef95SAndrea Merello 
373cf3bef95SAndrea Merello 	if (WARN_ON(!bridge->dev))
374cf3bef95SAndrea Merello 		return;
375cf3bef95SAndrea Merello 
37675146591SBoris Brezillon 	if (bridge->funcs->atomic_reset)
37775146591SBoris Brezillon 		drm_atomic_private_obj_fini(&bridge->base);
37875146591SBoris Brezillon 
379cf3bef95SAndrea Merello 	if (bridge->funcs->detach)
380cf3bef95SAndrea Merello 		bridge->funcs->detach(bridge);
381cf3bef95SAndrea Merello 
38205193dc3SBoris Brezillon 	list_del(&bridge->chain_node);
383cf3bef95SAndrea Merello 	bridge->dev = NULL;
384cf3bef95SAndrea Merello }
385cf3bef95SAndrea Merello 
386cf3bef95SAndrea Merello /**
3870451369bSLaurent Pinchart  * DOC: bridge operations
3882331b4e4SArchit Taneja  *
3890451369bSLaurent Pinchart  * Bridge drivers expose operations through the &drm_bridge_funcs structure.
3900451369bSLaurent Pinchart  * The DRM internals (atomic and CRTC helpers) use the helpers defined in
3910451369bSLaurent Pinchart  * drm_bridge.c to call bridge operations. Those operations are divided in
39211f6c4b1SLaurent Pinchart  * three big categories to support different parts of the bridge usage.
3932331b4e4SArchit Taneja  *
3940451369bSLaurent Pinchart  * - The encoder-related operations support control of the bridges in the
3950451369bSLaurent Pinchart  *   chain, and are roughly counterparts to the &drm_encoder_helper_funcs
3960451369bSLaurent Pinchart  *   operations. They are used by the legacy CRTC and the atomic modeset
3970451369bSLaurent Pinchart  *   helpers to perform mode validation, fixup and setting, and enable and
3980451369bSLaurent Pinchart  *   disable the bridge automatically.
3990451369bSLaurent Pinchart  *
4000451369bSLaurent Pinchart  *   The enable and disable operations are split in
4010451369bSLaurent Pinchart  *   &drm_bridge_funcs.pre_enable, &drm_bridge_funcs.enable,
4020451369bSLaurent Pinchart  *   &drm_bridge_funcs.disable and &drm_bridge_funcs.post_disable to provide
4030451369bSLaurent Pinchart  *   finer-grained control.
4040451369bSLaurent Pinchart  *
4050451369bSLaurent Pinchart  *   Bridge drivers may implement the legacy version of those operations, or
4060451369bSLaurent Pinchart  *   the atomic version (prefixed with atomic\_), in which case they shall also
4070451369bSLaurent Pinchart  *   implement the atomic state bookkeeping operations
4080451369bSLaurent Pinchart  *   (&drm_bridge_funcs.atomic_duplicate_state,
4090451369bSLaurent Pinchart  *   &drm_bridge_funcs.atomic_destroy_state and &drm_bridge_funcs.reset).
4100451369bSLaurent Pinchart  *   Mixing atomic and non-atomic versions of the operations is not supported.
4110451369bSLaurent Pinchart  *
4120451369bSLaurent Pinchart  * - The bus format negotiation operations
4130451369bSLaurent Pinchart  *   &drm_bridge_funcs.atomic_get_output_bus_fmts and
4140451369bSLaurent Pinchart  *   &drm_bridge_funcs.atomic_get_input_bus_fmts allow bridge drivers to
4150451369bSLaurent Pinchart  *   negotiate the formats transmitted between bridges in the chain when
4160451369bSLaurent Pinchart  *   multiple formats are supported. Negotiation for formats is performed
4170451369bSLaurent Pinchart  *   transparently for display drivers by the atomic modeset helpers. Only
4180451369bSLaurent Pinchart  *   atomic versions of those operations exist, bridge drivers that need to
4190451369bSLaurent Pinchart  *   implement them shall thus also implement the atomic version of the
4200451369bSLaurent Pinchart  *   encoder-related operations. This feature is not supported by the legacy
4210451369bSLaurent Pinchart  *   CRTC helpers.
42211f6c4b1SLaurent Pinchart  *
42311f6c4b1SLaurent Pinchart  * - The connector-related operations support implementing a &drm_connector
42411f6c4b1SLaurent Pinchart  *   based on a chain of bridges. DRM bridges traditionally create a
42511f6c4b1SLaurent Pinchart  *   &drm_connector for bridges meant to be used at the end of the chain. This
42611f6c4b1SLaurent Pinchart  *   puts additional burden on bridge drivers, especially for bridges that may
42711f6c4b1SLaurent Pinchart  *   be used in the middle of a chain or at the end of it. Furthermore, it
42811f6c4b1SLaurent Pinchart  *   requires all operations of the &drm_connector to be handled by a single
42911f6c4b1SLaurent Pinchart  *   bridge, which doesn't always match the hardware architecture.
43011f6c4b1SLaurent Pinchart  *
43111f6c4b1SLaurent Pinchart  *   To simplify bridge drivers and make the connector implementation more
43211f6c4b1SLaurent Pinchart  *   flexible, a new model allows bridges to unconditionally skip creation of
43311f6c4b1SLaurent Pinchart  *   &drm_connector and instead expose &drm_bridge_funcs operations to support
43411f6c4b1SLaurent Pinchart  *   an externally-implemented &drm_connector. Those operations are
43511f6c4b1SLaurent Pinchart  *   &drm_bridge_funcs.detect, &drm_bridge_funcs.get_modes,
43611f6c4b1SLaurent Pinchart  *   &drm_bridge_funcs.get_edid, &drm_bridge_funcs.hpd_notify,
43711f6c4b1SLaurent Pinchart  *   &drm_bridge_funcs.hpd_enable and &drm_bridge_funcs.hpd_disable. When
43811f6c4b1SLaurent Pinchart  *   implemented, display drivers shall create a &drm_connector instance for
43911f6c4b1SLaurent Pinchart  *   each chain of bridges, and implement those connector instances based on
44011f6c4b1SLaurent Pinchart  *   the bridge connector operations.
44111f6c4b1SLaurent Pinchart  *
44211f6c4b1SLaurent Pinchart  *   Bridge drivers shall implement the connector-related operations for all
44311f6c4b1SLaurent Pinchart  *   the features that the bridge hardware support. For instance, if a bridge
44411f6c4b1SLaurent Pinchart  *   supports reading EDID, the &drm_bridge_funcs.get_edid shall be
44511f6c4b1SLaurent Pinchart  *   implemented. This however doesn't mean that the DDC lines are wired to the
44611f6c4b1SLaurent Pinchart  *   bridge on a particular platform, as they could also be connected to an I2C
44711f6c4b1SLaurent Pinchart  *   controller of the SoC. Support for the connector-related operations on the
44811f6c4b1SLaurent Pinchart  *   running platform is reported through the &drm_bridge.ops flags. Bridge
44911f6c4b1SLaurent Pinchart  *   drivers shall detect which operations they can support on the platform
45011f6c4b1SLaurent Pinchart  *   (usually this information is provided by ACPI or DT), and set the
45111f6c4b1SLaurent Pinchart  *   &drm_bridge.ops flags for all supported operations. A flag shall only be
45211f6c4b1SLaurent Pinchart  *   set if the corresponding &drm_bridge_funcs operation is implemented, but
45311f6c4b1SLaurent Pinchart  *   an implemented operation doesn't necessarily imply that the corresponding
45411f6c4b1SLaurent Pinchart  *   flag will be set. Display drivers shall use the &drm_bridge.ops flags to
45511f6c4b1SLaurent Pinchart  *   decide which bridge to delegate a connector operation to. This mechanism
45611f6c4b1SLaurent Pinchart  *   allows providing a single static const &drm_bridge_funcs instance in
45711f6c4b1SLaurent Pinchart  *   bridge drivers, improving security by storing function pointers in
45811f6c4b1SLaurent Pinchart  *   read-only memory.
459a25b988fSLaurent Pinchart  *
460a25b988fSLaurent Pinchart  *   In order to ease transition, bridge drivers may support both the old and
461a25b988fSLaurent Pinchart  *   new models by making connector creation optional and implementing the
462a25b988fSLaurent Pinchart  *   connected-related bridge operations. Connector creation is then controlled
463a25b988fSLaurent Pinchart  *   by the flags argument to the drm_bridge_attach() function. Display drivers
464a25b988fSLaurent Pinchart  *   that support the new model and create connectors themselves shall set the
465a25b988fSLaurent Pinchart  *   %DRM_BRIDGE_ATTACH_NO_CONNECTOR flag, and bridge drivers shall then skip
466a25b988fSLaurent Pinchart  *   connector creation. For intermediate bridges in the chain, the flag shall
467a25b988fSLaurent Pinchart  *   be passed to the drm_bridge_attach() call for the downstream bridge.
468a25b988fSLaurent Pinchart  *   Bridge drivers that implement the new model only shall return an error
469a25b988fSLaurent Pinchart  *   from their &drm_bridge_funcs.attach handler when the
470a25b988fSLaurent Pinchart  *   %DRM_BRIDGE_ATTACH_NO_CONNECTOR flag is not set. New display drivers
471a25b988fSLaurent Pinchart  *   should use the new model, and convert the bridge drivers they use if
472a25b988fSLaurent Pinchart  *   needed, in order to gradually transition to the new model.
4732331b4e4SArchit Taneja  */
4742331b4e4SArchit Taneja 
4752331b4e4SArchit Taneja /**
476ea099adfSBoris Brezillon  * drm_bridge_chain_mode_fixup - fixup proposed mode for all bridges in the
477862e686cSArchit Taneja  *				 encoder chain
478862e686cSArchit Taneja  * @bridge: bridge control structure
479862e686cSArchit Taneja  * @mode: desired mode to be set for the bridge
480862e686cSArchit Taneja  * @adjusted_mode: updated mode that works for this bridge
481862e686cSArchit Taneja  *
4824541d31eSDaniel Vetter  * Calls &drm_bridge_funcs.mode_fixup for all the bridges in the
483862e686cSArchit Taneja  * encoder chain, starting from the first bridge to the last.
484862e686cSArchit Taneja  *
485862e686cSArchit Taneja  * Note: the bridge passed should be the one closest to the encoder
486862e686cSArchit Taneja  *
487862e686cSArchit Taneja  * RETURNS:
488862e686cSArchit Taneja  * true on success, false on failure
489862e686cSArchit Taneja  */
drm_bridge_chain_mode_fixup(struct drm_bridge * bridge,const struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)490ea099adfSBoris Brezillon bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
491862e686cSArchit Taneja 				 const struct drm_display_mode *mode,
492862e686cSArchit Taneja 				 struct drm_display_mode *adjusted_mode)
493862e686cSArchit Taneja {
49405193dc3SBoris Brezillon 	struct drm_encoder *encoder;
495862e686cSArchit Taneja 
496862e686cSArchit Taneja 	if (!bridge)
497862e686cSArchit Taneja 		return true;
498862e686cSArchit Taneja 
49905193dc3SBoris Brezillon 	encoder = bridge->encoder;
50005193dc3SBoris Brezillon 	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
50105193dc3SBoris Brezillon 		if (!bridge->funcs->mode_fixup)
50205193dc3SBoris Brezillon 			continue;
503862e686cSArchit Taneja 
50405193dc3SBoris Brezillon 		if (!bridge->funcs->mode_fixup(bridge, mode, adjusted_mode))
50505193dc3SBoris Brezillon 			return false;
50605193dc3SBoris Brezillon 	}
507862e686cSArchit Taneja 
50805193dc3SBoris Brezillon 	return true;
509862e686cSArchit Taneja }
510ea099adfSBoris Brezillon EXPORT_SYMBOL(drm_bridge_chain_mode_fixup);
511862e686cSArchit Taneja 
512862e686cSArchit Taneja /**
513ea099adfSBoris Brezillon  * drm_bridge_chain_mode_valid - validate the mode against all bridges in the
514b1240f81SJose Abreu  *				 encoder chain.
515b1240f81SJose Abreu  * @bridge: bridge control structure
51612c683e1SLaurent Pinchart  * @info: display info against which the mode shall be validated
517b1240f81SJose Abreu  * @mode: desired mode to be validated
518b1240f81SJose Abreu  *
519b1240f81SJose Abreu  * Calls &drm_bridge_funcs.mode_valid for all the bridges in the encoder
520b1240f81SJose Abreu  * chain, starting from the first bridge to the last. If at least one bridge
521b1240f81SJose Abreu  * does not accept the mode the function returns the error code.
522b1240f81SJose Abreu  *
523b1240f81SJose Abreu  * Note: the bridge passed should be the one closest to the encoder.
524b1240f81SJose Abreu  *
525b1240f81SJose Abreu  * RETURNS:
526b1240f81SJose Abreu  * MODE_OK on success, drm_mode_status Enum error code on failure
527b1240f81SJose Abreu  */
528ea099adfSBoris Brezillon enum drm_mode_status
drm_bridge_chain_mode_valid(struct drm_bridge * bridge,const struct drm_display_info * info,const struct drm_display_mode * mode)529ea099adfSBoris Brezillon drm_bridge_chain_mode_valid(struct drm_bridge *bridge,
53012c683e1SLaurent Pinchart 			    const struct drm_display_info *info,
531b1240f81SJose Abreu 			    const struct drm_display_mode *mode)
532b1240f81SJose Abreu {
53305193dc3SBoris Brezillon 	struct drm_encoder *encoder;
534b1240f81SJose Abreu 
535b1240f81SJose Abreu 	if (!bridge)
53605193dc3SBoris Brezillon 		return MODE_OK;
537b1240f81SJose Abreu 
53805193dc3SBoris Brezillon 	encoder = bridge->encoder;
53905193dc3SBoris Brezillon 	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
54005193dc3SBoris Brezillon 		enum drm_mode_status ret;
54105193dc3SBoris Brezillon 
54205193dc3SBoris Brezillon 		if (!bridge->funcs->mode_valid)
54305193dc3SBoris Brezillon 			continue;
54405193dc3SBoris Brezillon 
54512c683e1SLaurent Pinchart 		ret = bridge->funcs->mode_valid(bridge, info, mode);
546b1240f81SJose Abreu 		if (ret != MODE_OK)
547b1240f81SJose Abreu 			return ret;
54805193dc3SBoris Brezillon 	}
549b1240f81SJose Abreu 
55005193dc3SBoris Brezillon 	return MODE_OK;
551b1240f81SJose Abreu }
552ea099adfSBoris Brezillon EXPORT_SYMBOL(drm_bridge_chain_mode_valid);
553b1240f81SJose Abreu 
554b1240f81SJose Abreu /**
555ea099adfSBoris Brezillon  * drm_bridge_chain_mode_set - set proposed mode for all bridges in the
556862e686cSArchit Taneja  *			       encoder chain
557862e686cSArchit Taneja  * @bridge: bridge control structure
558ea099adfSBoris Brezillon  * @mode: desired mode to be set for the encoder chain
559ea099adfSBoris Brezillon  * @adjusted_mode: updated mode that works for this encoder chain
560862e686cSArchit Taneja  *
5614541d31eSDaniel Vetter  * Calls &drm_bridge_funcs.mode_set op for all the bridges in the
562862e686cSArchit Taneja  * encoder chain, starting from the first bridge to the last.
563862e686cSArchit Taneja  *
564862e686cSArchit Taneja  * Note: the bridge passed should be the one closest to the encoder
565862e686cSArchit Taneja  */
drm_bridge_chain_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted_mode)566ea099adfSBoris Brezillon void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
56763f8f3baSLaurent Pinchart 			       const struct drm_display_mode *mode,
56863f8f3baSLaurent Pinchart 			       const struct drm_display_mode *adjusted_mode)
569862e686cSArchit Taneja {
57005193dc3SBoris Brezillon 	struct drm_encoder *encoder;
57105193dc3SBoris Brezillon 
572862e686cSArchit Taneja 	if (!bridge)
573862e686cSArchit Taneja 		return;
574862e686cSArchit Taneja 
57505193dc3SBoris Brezillon 	encoder = bridge->encoder;
57605193dc3SBoris Brezillon 	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
577862e686cSArchit Taneja 		if (bridge->funcs->mode_set)
578862e686cSArchit Taneja 			bridge->funcs->mode_set(bridge, mode, adjusted_mode);
57905193dc3SBoris Brezillon 	}
580862e686cSArchit Taneja }
581ea099adfSBoris Brezillon EXPORT_SYMBOL(drm_bridge_chain_mode_set);
582862e686cSArchit Taneja 
583862e686cSArchit Taneja /**
584ea099adfSBoris Brezillon  * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain
5855ade071bSSean Paul  * @bridge: bridge control structure
586f3fdbc72SBoris Brezillon  * @old_state: old atomic state
5875ade071bSSean Paul  *
5885ade071bSSean Paul  * Calls &drm_bridge_funcs.atomic_disable (falls back on
5895ade071bSSean Paul  * &drm_bridge_funcs.disable) op for all the bridges in the encoder chain,
5905ade071bSSean Paul  * starting from the last bridge to the first. These are called before calling
5915ade071bSSean Paul  * &drm_encoder_helper_funcs.atomic_disable
5925ade071bSSean Paul  *
5935ade071bSSean Paul  * Note: the bridge passed should be the one closest to the encoder
5945ade071bSSean Paul  */
drm_atomic_bridge_chain_disable(struct drm_bridge * bridge,struct drm_atomic_state * old_state)595ea099adfSBoris Brezillon void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
596f3fdbc72SBoris Brezillon 				     struct drm_atomic_state *old_state)
5975ade071bSSean Paul {
59805193dc3SBoris Brezillon 	struct drm_encoder *encoder;
59905193dc3SBoris Brezillon 	struct drm_bridge *iter;
60005193dc3SBoris Brezillon 
6015ade071bSSean Paul 	if (!bridge)
6025ade071bSSean Paul 		return;
6035ade071bSSean Paul 
60405193dc3SBoris Brezillon 	encoder = bridge->encoder;
60505193dc3SBoris Brezillon 	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
60641cf5712SBoris Brezillon 		if (iter->funcs->atomic_disable) {
60741cf5712SBoris Brezillon 			struct drm_bridge_state *old_bridge_state;
60841cf5712SBoris Brezillon 
60941cf5712SBoris Brezillon 			old_bridge_state =
61041cf5712SBoris Brezillon 				drm_atomic_get_old_bridge_state(old_state,
61141cf5712SBoris Brezillon 								iter);
61241cf5712SBoris Brezillon 			if (WARN_ON(!old_bridge_state))
61341cf5712SBoris Brezillon 				return;
61441cf5712SBoris Brezillon 
61541cf5712SBoris Brezillon 			iter->funcs->atomic_disable(iter, old_bridge_state);
61641cf5712SBoris Brezillon 		} else if (iter->funcs->disable) {
61705193dc3SBoris Brezillon 			iter->funcs->disable(iter);
61841cf5712SBoris Brezillon 		}
6195ade071bSSean Paul 
62005193dc3SBoris Brezillon 		if (iter == bridge)
62105193dc3SBoris Brezillon 			break;
62205193dc3SBoris Brezillon 	}
6235ade071bSSean Paul }
624ea099adfSBoris Brezillon EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
6255ade071bSSean Paul 
drm_atomic_bridge_call_post_disable(struct drm_bridge * bridge,struct drm_atomic_state * old_state)6264fb912e5SDave Stevenson static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge,
627f3fdbc72SBoris Brezillon 						struct drm_atomic_state *old_state)
6285ade071bSSean Paul {
6294fb912e5SDave Stevenson 	if (old_state && bridge->funcs->atomic_post_disable) {
63041cf5712SBoris Brezillon 		struct drm_bridge_state *old_bridge_state;
63141cf5712SBoris Brezillon 
63241cf5712SBoris Brezillon 		old_bridge_state =
63341cf5712SBoris Brezillon 			drm_atomic_get_old_bridge_state(old_state,
63441cf5712SBoris Brezillon 							bridge);
63541cf5712SBoris Brezillon 		if (WARN_ON(!old_bridge_state))
63641cf5712SBoris Brezillon 			return;
63741cf5712SBoris Brezillon 
63841cf5712SBoris Brezillon 		bridge->funcs->atomic_post_disable(bridge,
63941cf5712SBoris Brezillon 						   old_bridge_state);
64041cf5712SBoris Brezillon 	} else if (bridge->funcs->post_disable) {
6415ade071bSSean Paul 		bridge->funcs->post_disable(bridge);
64205193dc3SBoris Brezillon 	}
6435ade071bSSean Paul }
6444fb912e5SDave Stevenson 
6454fb912e5SDave Stevenson /**
6464fb912e5SDave Stevenson  * drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges
6474fb912e5SDave Stevenson  *					  in the encoder chain
6484fb912e5SDave Stevenson  * @bridge: bridge control structure
6494fb912e5SDave Stevenson  * @old_state: old atomic state
6504fb912e5SDave Stevenson  *
6514fb912e5SDave Stevenson  * Calls &drm_bridge_funcs.atomic_post_disable (falls back on
6524fb912e5SDave Stevenson  * &drm_bridge_funcs.post_disable) op for all the bridges in the encoder chain,
6534fb912e5SDave Stevenson  * starting from the first bridge to the last. These are called after completing
6544fb912e5SDave Stevenson  * &drm_encoder_helper_funcs.atomic_disable
6554fb912e5SDave Stevenson  *
6564fb912e5SDave Stevenson  * If a bridge sets @pre_enable_prev_first, then the @post_disable for that
6574fb912e5SDave Stevenson  * bridge will be called before the previous one to reverse the @pre_enable
6584fb912e5SDave Stevenson  * calling direction.
6594fb912e5SDave Stevenson  *
6604fb912e5SDave Stevenson  * Note: the bridge passed should be the one closest to the encoder
6614fb912e5SDave Stevenson  */
drm_atomic_bridge_chain_post_disable(struct drm_bridge * bridge,struct drm_atomic_state * old_state)6624fb912e5SDave Stevenson void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
6634fb912e5SDave Stevenson 					  struct drm_atomic_state *old_state)
6644fb912e5SDave Stevenson {
6654fb912e5SDave Stevenson 	struct drm_encoder *encoder;
6664fb912e5SDave Stevenson 	struct drm_bridge *next, *limit;
6674fb912e5SDave Stevenson 
6684fb912e5SDave Stevenson 	if (!bridge)
6694fb912e5SDave Stevenson 		return;
6704fb912e5SDave Stevenson 
6714fb912e5SDave Stevenson 	encoder = bridge->encoder;
6724fb912e5SDave Stevenson 
6734fb912e5SDave Stevenson 	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
6744fb912e5SDave Stevenson 		limit = NULL;
6754fb912e5SDave Stevenson 
6764fb912e5SDave Stevenson 		if (!list_is_last(&bridge->chain_node, &encoder->bridge_chain)) {
6774fb912e5SDave Stevenson 			next = list_next_entry(bridge, chain_node);
6784fb912e5SDave Stevenson 
6794fb912e5SDave Stevenson 			if (next->pre_enable_prev_first) {
6804fb912e5SDave Stevenson 				/* next bridge had requested that prev
6814fb912e5SDave Stevenson 				 * was enabled first, so disabled last
6824fb912e5SDave Stevenson 				 */
6834fb912e5SDave Stevenson 				limit = next;
6844fb912e5SDave Stevenson 
6854fb912e5SDave Stevenson 				/* Find the next bridge that has NOT requested
6864fb912e5SDave Stevenson 				 * prev to be enabled first / disabled last
6874fb912e5SDave Stevenson 				 */
6884fb912e5SDave Stevenson 				list_for_each_entry_from(next, &encoder->bridge_chain,
6894fb912e5SDave Stevenson 							 chain_node) {
6904fb912e5SDave Stevenson 					if (next->pre_enable_prev_first) {
6914fb912e5SDave Stevenson 						next = list_prev_entry(next, chain_node);
6924fb912e5SDave Stevenson 						limit = next;
6934fb912e5SDave Stevenson 						break;
6944fb912e5SDave Stevenson 					}
6954fb912e5SDave Stevenson 				}
6964fb912e5SDave Stevenson 
6974fb912e5SDave Stevenson 				/* Call these bridges in reverse order */
6984fb912e5SDave Stevenson 				list_for_each_entry_from_reverse(next, &encoder->bridge_chain,
6994fb912e5SDave Stevenson 								 chain_node) {
7004fb912e5SDave Stevenson 					if (next == bridge)
7014fb912e5SDave Stevenson 						break;
7024fb912e5SDave Stevenson 
7034fb912e5SDave Stevenson 					drm_atomic_bridge_call_post_disable(next,
7044fb912e5SDave Stevenson 									    old_state);
7054fb912e5SDave Stevenson 				}
7064fb912e5SDave Stevenson 			}
7074fb912e5SDave Stevenson 		}
7084fb912e5SDave Stevenson 
7094fb912e5SDave Stevenson 		drm_atomic_bridge_call_post_disable(bridge, old_state);
7104fb912e5SDave Stevenson 
7114fb912e5SDave Stevenson 		if (limit)
7124fb912e5SDave Stevenson 			/* Jump all bridges that we have already post_disabled */
7134fb912e5SDave Stevenson 			bridge = limit;
7144fb912e5SDave Stevenson 	}
71541cf5712SBoris Brezillon }
716ea099adfSBoris Brezillon EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
7175ade071bSSean Paul 
drm_atomic_bridge_call_pre_enable(struct drm_bridge * bridge,struct drm_atomic_state * old_state)7184fb912e5SDave Stevenson static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge,
7194fb912e5SDave Stevenson 					      struct drm_atomic_state *old_state)
7204fb912e5SDave Stevenson {
7214fb912e5SDave Stevenson 	if (old_state && bridge->funcs->atomic_pre_enable) {
7224fb912e5SDave Stevenson 		struct drm_bridge_state *old_bridge_state;
7234fb912e5SDave Stevenson 
7244fb912e5SDave Stevenson 		old_bridge_state =
7254fb912e5SDave Stevenson 			drm_atomic_get_old_bridge_state(old_state,
7264fb912e5SDave Stevenson 							bridge);
7274fb912e5SDave Stevenson 		if (WARN_ON(!old_bridge_state))
7284fb912e5SDave Stevenson 			return;
7294fb912e5SDave Stevenson 
7304fb912e5SDave Stevenson 		bridge->funcs->atomic_pre_enable(bridge, old_bridge_state);
7314fb912e5SDave Stevenson 	} else if (bridge->funcs->pre_enable) {
7324fb912e5SDave Stevenson 		bridge->funcs->pre_enable(bridge);
7334fb912e5SDave Stevenson 	}
7344fb912e5SDave Stevenson }
7354fb912e5SDave Stevenson 
7365ade071bSSean Paul /**
737ea099adfSBoris Brezillon  * drm_atomic_bridge_chain_pre_enable - prepares for enabling all bridges in
738ea099adfSBoris Brezillon  *					the encoder chain
7395ade071bSSean Paul  * @bridge: bridge control structure
740f3fdbc72SBoris Brezillon  * @old_state: old atomic state
7415ade071bSSean Paul  *
7425ade071bSSean Paul  * Calls &drm_bridge_funcs.atomic_pre_enable (falls back on
7435ade071bSSean Paul  * &drm_bridge_funcs.pre_enable) op for all the bridges in the encoder chain,
7445ade071bSSean Paul  * starting from the last bridge to the first. These are called before calling
7455ade071bSSean Paul  * &drm_encoder_helper_funcs.atomic_enable
7465ade071bSSean Paul  *
7474fb912e5SDave Stevenson  * If a bridge sets @pre_enable_prev_first, then the pre_enable for the
7484fb912e5SDave Stevenson  * prev bridge will be called before pre_enable of this bridge.
7494fb912e5SDave Stevenson  *
7505ade071bSSean Paul  * Note: the bridge passed should be the one closest to the encoder
7515ade071bSSean Paul  */
drm_atomic_bridge_chain_pre_enable(struct drm_bridge * bridge,struct drm_atomic_state * old_state)752ea099adfSBoris Brezillon void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
753f3fdbc72SBoris Brezillon 					struct drm_atomic_state *old_state)
7545ade071bSSean Paul {
75505193dc3SBoris Brezillon 	struct drm_encoder *encoder;
7564fb912e5SDave Stevenson 	struct drm_bridge *iter, *next, *limit;
75705193dc3SBoris Brezillon 
7585ade071bSSean Paul 	if (!bridge)
7595ade071bSSean Paul 		return;
7605ade071bSSean Paul 
76105193dc3SBoris Brezillon 	encoder = bridge->encoder;
7624fb912e5SDave Stevenson 
76305193dc3SBoris Brezillon 	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
7644fb912e5SDave Stevenson 		if (iter->pre_enable_prev_first) {
7654fb912e5SDave Stevenson 			next = iter;
7664fb912e5SDave Stevenson 			limit = bridge;
7674fb912e5SDave Stevenson 			list_for_each_entry_from_reverse(next,
7684fb912e5SDave Stevenson 							 &encoder->bridge_chain,
7694fb912e5SDave Stevenson 							 chain_node) {
7704fb912e5SDave Stevenson 				if (next == bridge)
7714fb912e5SDave Stevenson 					break;
77241cf5712SBoris Brezillon 
7734fb912e5SDave Stevenson 				if (!next->pre_enable_prev_first) {
7744fb912e5SDave Stevenson 					/* Found first bridge that does NOT
7754fb912e5SDave Stevenson 					 * request prev to be enabled first
7764fb912e5SDave Stevenson 					 */
7774fb912e5SDave Stevenson 					limit = list_prev_entry(next, chain_node);
7784fb912e5SDave Stevenson 					break;
77941cf5712SBoris Brezillon 				}
7804fb912e5SDave Stevenson 			}
7814fb912e5SDave Stevenson 
7824fb912e5SDave Stevenson 			list_for_each_entry_from(next, &encoder->bridge_chain, chain_node) {
7834fb912e5SDave Stevenson 				/* Call requested prev bridge pre_enable
7844fb912e5SDave Stevenson 				 * in order.
7854fb912e5SDave Stevenson 				 */
7864fb912e5SDave Stevenson 				if (next == iter)
7874fb912e5SDave Stevenson 					/* At the first bridge to request prev
7884fb912e5SDave Stevenson 					 * bridges called first.
7894fb912e5SDave Stevenson 					 */
7904fb912e5SDave Stevenson 					break;
7914fb912e5SDave Stevenson 
7924fb912e5SDave Stevenson 				drm_atomic_bridge_call_pre_enable(next, old_state);
7934fb912e5SDave Stevenson 			}
7944fb912e5SDave Stevenson 		}
7954fb912e5SDave Stevenson 
7964fb912e5SDave Stevenson 		drm_atomic_bridge_call_pre_enable(iter, old_state);
7974fb912e5SDave Stevenson 
7984fb912e5SDave Stevenson 		if (iter->pre_enable_prev_first)
7994fb912e5SDave Stevenson 			/* Jump all bridges that we have already pre_enabled */
8004fb912e5SDave Stevenson 			iter = limit;
8015ade071bSSean Paul 
80205193dc3SBoris Brezillon 		if (iter == bridge)
80305193dc3SBoris Brezillon 			break;
80405193dc3SBoris Brezillon 	}
8055ade071bSSean Paul }
806ea099adfSBoris Brezillon EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
8075ade071bSSean Paul 
8085ade071bSSean Paul /**
809ea099adfSBoris Brezillon  * drm_atomic_bridge_chain_enable - enables all bridges in the encoder chain
8105ade071bSSean Paul  * @bridge: bridge control structure
811f3fdbc72SBoris Brezillon  * @old_state: old atomic state
8125ade071bSSean Paul  *
8135ade071bSSean Paul  * Calls &drm_bridge_funcs.atomic_enable (falls back on
8145ade071bSSean Paul  * &drm_bridge_funcs.enable) op for all the bridges in the encoder chain,
8155ade071bSSean Paul  * starting from the first bridge to the last. These are called after completing
8165ade071bSSean Paul  * &drm_encoder_helper_funcs.atomic_enable
8175ade071bSSean Paul  *
8185ade071bSSean Paul  * Note: the bridge passed should be the one closest to the encoder
8195ade071bSSean Paul  */
drm_atomic_bridge_chain_enable(struct drm_bridge * bridge,struct drm_atomic_state * old_state)820ea099adfSBoris Brezillon void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
821f3fdbc72SBoris Brezillon 				    struct drm_atomic_state *old_state)
8225ade071bSSean Paul {
82305193dc3SBoris Brezillon 	struct drm_encoder *encoder;
82405193dc3SBoris Brezillon 
8255ade071bSSean Paul 	if (!bridge)
8265ade071bSSean Paul 		return;
8275ade071bSSean Paul 
82805193dc3SBoris Brezillon 	encoder = bridge->encoder;
82905193dc3SBoris Brezillon 	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
83041cf5712SBoris Brezillon 		if (bridge->funcs->atomic_enable) {
83141cf5712SBoris Brezillon 			struct drm_bridge_state *old_bridge_state;
83241cf5712SBoris Brezillon 
83341cf5712SBoris Brezillon 			old_bridge_state =
83441cf5712SBoris Brezillon 				drm_atomic_get_old_bridge_state(old_state,
83541cf5712SBoris Brezillon 								bridge);
83641cf5712SBoris Brezillon 			if (WARN_ON(!old_bridge_state))
83741cf5712SBoris Brezillon 				return;
83841cf5712SBoris Brezillon 
83941cf5712SBoris Brezillon 			bridge->funcs->atomic_enable(bridge, old_bridge_state);
84041cf5712SBoris Brezillon 		} else if (bridge->funcs->enable) {
8415ade071bSSean Paul 			bridge->funcs->enable(bridge);
84205193dc3SBoris Brezillon 		}
8435ade071bSSean Paul 	}
84441cf5712SBoris Brezillon }
845ea099adfSBoris Brezillon EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
8465ade071bSSean Paul 
drm_atomic_bridge_check(struct drm_bridge * bridge,struct drm_crtc_state * crtc_state,struct drm_connector_state * conn_state)8475061b8a9SBoris Brezillon static int drm_atomic_bridge_check(struct drm_bridge *bridge,
8485061b8a9SBoris Brezillon 				   struct drm_crtc_state *crtc_state,
8495061b8a9SBoris Brezillon 				   struct drm_connector_state *conn_state)
8505061b8a9SBoris Brezillon {
8515061b8a9SBoris Brezillon 	if (bridge->funcs->atomic_check) {
8525061b8a9SBoris Brezillon 		struct drm_bridge_state *bridge_state;
8535061b8a9SBoris Brezillon 		int ret;
8545061b8a9SBoris Brezillon 
8555061b8a9SBoris Brezillon 		bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
8565061b8a9SBoris Brezillon 							       bridge);
8575061b8a9SBoris Brezillon 		if (WARN_ON(!bridge_state))
8585061b8a9SBoris Brezillon 			return -EINVAL;
8595061b8a9SBoris Brezillon 
8605061b8a9SBoris Brezillon 		ret = bridge->funcs->atomic_check(bridge, bridge_state,
8615061b8a9SBoris Brezillon 						  crtc_state, conn_state);
8625061b8a9SBoris Brezillon 		if (ret)
8635061b8a9SBoris Brezillon 			return ret;
8645061b8a9SBoris Brezillon 	} else if (bridge->funcs->mode_fixup) {
8655061b8a9SBoris Brezillon 		if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode,
8665061b8a9SBoris Brezillon 					       &crtc_state->adjusted_mode))
8675061b8a9SBoris Brezillon 			return -EINVAL;
8685061b8a9SBoris Brezillon 	}
8695061b8a9SBoris Brezillon 
8705061b8a9SBoris Brezillon 	return 0;
8715061b8a9SBoris Brezillon }
8725061b8a9SBoris Brezillon 
select_bus_fmt_recursive(struct drm_bridge * first_bridge,struct drm_bridge * cur_bridge,struct drm_crtc_state * crtc_state,struct drm_connector_state * conn_state,u32 out_bus_fmt)873f32df58aSBoris Brezillon static int select_bus_fmt_recursive(struct drm_bridge *first_bridge,
874f32df58aSBoris Brezillon 				    struct drm_bridge *cur_bridge,
875f32df58aSBoris Brezillon 				    struct drm_crtc_state *crtc_state,
876f32df58aSBoris Brezillon 				    struct drm_connector_state *conn_state,
877f32df58aSBoris Brezillon 				    u32 out_bus_fmt)
878f32df58aSBoris Brezillon {
8797d120273SDan Carpenter 	unsigned int i, num_in_bus_fmts = 0;
880f32df58aSBoris Brezillon 	struct drm_bridge_state *cur_state;
881f32df58aSBoris Brezillon 	struct drm_bridge *prev_bridge;
882f32df58aSBoris Brezillon 	u32 *in_bus_fmts;
883f32df58aSBoris Brezillon 	int ret;
884f32df58aSBoris Brezillon 
885f32df58aSBoris Brezillon 	prev_bridge = drm_bridge_get_prev_bridge(cur_bridge);
886f32df58aSBoris Brezillon 	cur_state = drm_atomic_get_new_bridge_state(crtc_state->state,
887f32df58aSBoris Brezillon 						    cur_bridge);
888f32df58aSBoris Brezillon 
889f32df58aSBoris Brezillon 	/*
890f32df58aSBoris Brezillon 	 * If bus format negotiation is not supported by this bridge, let's
891f32df58aSBoris Brezillon 	 * pass MEDIA_BUS_FMT_FIXED to the previous bridge in the chain and
892f32df58aSBoris Brezillon 	 * hope that it can handle this situation gracefully (by providing
893f32df58aSBoris Brezillon 	 * appropriate default values).
894f32df58aSBoris Brezillon 	 */
895f32df58aSBoris Brezillon 	if (!cur_bridge->funcs->atomic_get_input_bus_fmts) {
896f32df58aSBoris Brezillon 		if (cur_bridge != first_bridge) {
897f32df58aSBoris Brezillon 			ret = select_bus_fmt_recursive(first_bridge,
898f32df58aSBoris Brezillon 						       prev_bridge, crtc_state,
899f32df58aSBoris Brezillon 						       conn_state,
900f32df58aSBoris Brezillon 						       MEDIA_BUS_FMT_FIXED);
901f32df58aSBoris Brezillon 			if (ret)
902f32df58aSBoris Brezillon 				return ret;
903f32df58aSBoris Brezillon 		}
904f32df58aSBoris Brezillon 
905f32df58aSBoris Brezillon 		/*
906f32df58aSBoris Brezillon 		 * Driver does not implement the atomic state hooks, but that's
907f32df58aSBoris Brezillon 		 * fine, as long as it does not access the bridge state.
908f32df58aSBoris Brezillon 		 */
909f32df58aSBoris Brezillon 		if (cur_state) {
910f32df58aSBoris Brezillon 			cur_state->input_bus_cfg.format = MEDIA_BUS_FMT_FIXED;
911f32df58aSBoris Brezillon 			cur_state->output_bus_cfg.format = out_bus_fmt;
912f32df58aSBoris Brezillon 		}
913f32df58aSBoris Brezillon 
914f32df58aSBoris Brezillon 		return 0;
915f32df58aSBoris Brezillon 	}
916f32df58aSBoris Brezillon 
917f32df58aSBoris Brezillon 	/*
918f32df58aSBoris Brezillon 	 * If the driver implements ->atomic_get_input_bus_fmts() it
919f32df58aSBoris Brezillon 	 * should also implement the atomic state hooks.
920f32df58aSBoris Brezillon 	 */
921f32df58aSBoris Brezillon 	if (WARN_ON(!cur_state))
922f32df58aSBoris Brezillon 		return -EINVAL;
923f32df58aSBoris Brezillon 
924f32df58aSBoris Brezillon 	in_bus_fmts = cur_bridge->funcs->atomic_get_input_bus_fmts(cur_bridge,
925f32df58aSBoris Brezillon 							cur_state,
926f32df58aSBoris Brezillon 							crtc_state,
927f32df58aSBoris Brezillon 							conn_state,
928f32df58aSBoris Brezillon 							out_bus_fmt,
929f32df58aSBoris Brezillon 							&num_in_bus_fmts);
930f32df58aSBoris Brezillon 	if (!num_in_bus_fmts)
931f32df58aSBoris Brezillon 		return -ENOTSUPP;
932f32df58aSBoris Brezillon 	else if (!in_bus_fmts)
933f32df58aSBoris Brezillon 		return -ENOMEM;
934f32df58aSBoris Brezillon 
935f32df58aSBoris Brezillon 	if (first_bridge == cur_bridge) {
936f32df58aSBoris Brezillon 		cur_state->input_bus_cfg.format = in_bus_fmts[0];
937f32df58aSBoris Brezillon 		cur_state->output_bus_cfg.format = out_bus_fmt;
938f32df58aSBoris Brezillon 		kfree(in_bus_fmts);
939f32df58aSBoris Brezillon 		return 0;
940f32df58aSBoris Brezillon 	}
941f32df58aSBoris Brezillon 
942f32df58aSBoris Brezillon 	for (i = 0; i < num_in_bus_fmts; i++) {
943f32df58aSBoris Brezillon 		ret = select_bus_fmt_recursive(first_bridge, prev_bridge,
944f32df58aSBoris Brezillon 					       crtc_state, conn_state,
945f32df58aSBoris Brezillon 					       in_bus_fmts[i]);
946f32df58aSBoris Brezillon 		if (ret != -ENOTSUPP)
947f32df58aSBoris Brezillon 			break;
948f32df58aSBoris Brezillon 	}
949f32df58aSBoris Brezillon 
950f32df58aSBoris Brezillon 	if (!ret) {
951f32df58aSBoris Brezillon 		cur_state->input_bus_cfg.format = in_bus_fmts[i];
952f32df58aSBoris Brezillon 		cur_state->output_bus_cfg.format = out_bus_fmt;
953f32df58aSBoris Brezillon 	}
954f32df58aSBoris Brezillon 
955f32df58aSBoris Brezillon 	kfree(in_bus_fmts);
956f32df58aSBoris Brezillon 	return ret;
957f32df58aSBoris Brezillon }
958f32df58aSBoris Brezillon 
959f32df58aSBoris Brezillon /*
960f32df58aSBoris Brezillon  * This function is called by &drm_atomic_bridge_chain_check() just before
961f32df58aSBoris Brezillon  * calling &drm_bridge_funcs.atomic_check() on all elements of the chain.
962f32df58aSBoris Brezillon  * It performs bus format negotiation between bridge elements. The negotiation
963f32df58aSBoris Brezillon  * happens in reverse order, starting from the last element in the chain up to
964f32df58aSBoris Brezillon  * @bridge.
965f32df58aSBoris Brezillon  *
966f32df58aSBoris Brezillon  * Negotiation starts by retrieving supported output bus formats on the last
967f32df58aSBoris Brezillon  * bridge element and testing them one by one. The test is recursive, meaning
968f32df58aSBoris Brezillon  * that for each tested output format, the whole chain will be walked backward,
969f32df58aSBoris Brezillon  * and each element will have to choose an input bus format that can be
970f32df58aSBoris Brezillon  * transcoded to the requested output format. When a bridge element does not
971f32df58aSBoris Brezillon  * support transcoding into a specific output format -ENOTSUPP is returned and
972f32df58aSBoris Brezillon  * the next bridge element will have to try a different format. If none of the
973f32df58aSBoris Brezillon  * combinations worked, -ENOTSUPP is returned and the atomic modeset will fail.
974f32df58aSBoris Brezillon  *
975f32df58aSBoris Brezillon  * This implementation is relying on
976f32df58aSBoris Brezillon  * &drm_bridge_funcs.atomic_get_output_bus_fmts() and
977f32df58aSBoris Brezillon  * &drm_bridge_funcs.atomic_get_input_bus_fmts() to gather supported
978f32df58aSBoris Brezillon  * input/output formats.
979f32df58aSBoris Brezillon  *
980f32df58aSBoris Brezillon  * When &drm_bridge_funcs.atomic_get_output_bus_fmts() is not implemented by
981f32df58aSBoris Brezillon  * the last element of the chain, &drm_atomic_bridge_chain_select_bus_fmts()
982f32df58aSBoris Brezillon  * tries a single format: &drm_connector.display_info.bus_formats[0] if
983f32df58aSBoris Brezillon  * available, MEDIA_BUS_FMT_FIXED otherwise.
984f32df58aSBoris Brezillon  *
985f32df58aSBoris Brezillon  * When &drm_bridge_funcs.atomic_get_input_bus_fmts() is not implemented,
986f32df58aSBoris Brezillon  * &drm_atomic_bridge_chain_select_bus_fmts() skips the negotiation on the
987f32df58aSBoris Brezillon  * bridge element that lacks this hook and asks the previous element in the
988f32df58aSBoris Brezillon  * chain to try MEDIA_BUS_FMT_FIXED. It's up to bridge drivers to decide what
989f32df58aSBoris Brezillon  * to do in that case (fail if they want to enforce bus format negotiation, or
990f32df58aSBoris Brezillon  * provide a reasonable default if they need to support pipelines where not
991f32df58aSBoris Brezillon  * all elements support bus format negotiation).
992f32df58aSBoris Brezillon  */
993f32df58aSBoris Brezillon static int
drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge * bridge,struct drm_crtc_state * crtc_state,struct drm_connector_state * conn_state)994f32df58aSBoris Brezillon drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge,
995f32df58aSBoris Brezillon 					struct drm_crtc_state *crtc_state,
996f32df58aSBoris Brezillon 					struct drm_connector_state *conn_state)
997f32df58aSBoris Brezillon {
998f32df58aSBoris Brezillon 	struct drm_connector *conn = conn_state->connector;
999f32df58aSBoris Brezillon 	struct drm_encoder *encoder = bridge->encoder;
1000f32df58aSBoris Brezillon 	struct drm_bridge_state *last_bridge_state;
10017d120273SDan Carpenter 	unsigned int i, num_out_bus_fmts = 0;
1002f32df58aSBoris Brezillon 	struct drm_bridge *last_bridge;
1003f32df58aSBoris Brezillon 	u32 *out_bus_fmts;
1004f32df58aSBoris Brezillon 	int ret = 0;
1005f32df58aSBoris Brezillon 
1006f32df58aSBoris Brezillon 	last_bridge = list_last_entry(&encoder->bridge_chain,
1007f32df58aSBoris Brezillon 				      struct drm_bridge, chain_node);
1008f32df58aSBoris Brezillon 	last_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
1009f32df58aSBoris Brezillon 							    last_bridge);
1010f32df58aSBoris Brezillon 
1011f32df58aSBoris Brezillon 	if (last_bridge->funcs->atomic_get_output_bus_fmts) {
1012f32df58aSBoris Brezillon 		const struct drm_bridge_funcs *funcs = last_bridge->funcs;
1013f32df58aSBoris Brezillon 
1014f32df58aSBoris Brezillon 		/*
1015f32df58aSBoris Brezillon 		 * If the driver implements ->atomic_get_output_bus_fmts() it
1016f32df58aSBoris Brezillon 		 * should also implement the atomic state hooks.
1017f32df58aSBoris Brezillon 		 */
1018f32df58aSBoris Brezillon 		if (WARN_ON(!last_bridge_state))
1019f32df58aSBoris Brezillon 			return -EINVAL;
1020f32df58aSBoris Brezillon 
1021f32df58aSBoris Brezillon 		out_bus_fmts = funcs->atomic_get_output_bus_fmts(last_bridge,
1022f32df58aSBoris Brezillon 							last_bridge_state,
1023f32df58aSBoris Brezillon 							crtc_state,
1024f32df58aSBoris Brezillon 							conn_state,
1025f32df58aSBoris Brezillon 							&num_out_bus_fmts);
1026f32df58aSBoris Brezillon 		if (!num_out_bus_fmts)
1027f32df58aSBoris Brezillon 			return -ENOTSUPP;
1028f32df58aSBoris Brezillon 		else if (!out_bus_fmts)
1029f32df58aSBoris Brezillon 			return -ENOMEM;
1030f32df58aSBoris Brezillon 	} else {
1031f32df58aSBoris Brezillon 		num_out_bus_fmts = 1;
1032f32df58aSBoris Brezillon 		out_bus_fmts = kmalloc(sizeof(*out_bus_fmts), GFP_KERNEL);
1033f32df58aSBoris Brezillon 		if (!out_bus_fmts)
1034f32df58aSBoris Brezillon 			return -ENOMEM;
1035f32df58aSBoris Brezillon 
1036f32df58aSBoris Brezillon 		if (conn->display_info.num_bus_formats &&
1037f32df58aSBoris Brezillon 		    conn->display_info.bus_formats)
1038f32df58aSBoris Brezillon 			out_bus_fmts[0] = conn->display_info.bus_formats[0];
1039f32df58aSBoris Brezillon 		else
1040f32df58aSBoris Brezillon 			out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED;
1041f32df58aSBoris Brezillon 	}
1042f32df58aSBoris Brezillon 
1043f32df58aSBoris Brezillon 	for (i = 0; i < num_out_bus_fmts; i++) {
1044f32df58aSBoris Brezillon 		ret = select_bus_fmt_recursive(bridge, last_bridge, crtc_state,
1045f32df58aSBoris Brezillon 					       conn_state, out_bus_fmts[i]);
1046f32df58aSBoris Brezillon 		if (ret != -ENOTSUPP)
1047f32df58aSBoris Brezillon 			break;
1048f32df58aSBoris Brezillon 	}
1049f32df58aSBoris Brezillon 
1050f32df58aSBoris Brezillon 	kfree(out_bus_fmts);
1051f32df58aSBoris Brezillon 
1052f32df58aSBoris Brezillon 	return ret;
1053f32df58aSBoris Brezillon }
1054f32df58aSBoris Brezillon 
1055f32df58aSBoris Brezillon static void
drm_atomic_bridge_propagate_bus_flags(struct drm_bridge * bridge,struct drm_connector * conn,struct drm_atomic_state * state)1056f32df58aSBoris Brezillon drm_atomic_bridge_propagate_bus_flags(struct drm_bridge *bridge,
1057f32df58aSBoris Brezillon 				      struct drm_connector *conn,
1058f32df58aSBoris Brezillon 				      struct drm_atomic_state *state)
1059f32df58aSBoris Brezillon {
1060f32df58aSBoris Brezillon 	struct drm_bridge_state *bridge_state, *next_bridge_state;
1061f32df58aSBoris Brezillon 	struct drm_bridge *next_bridge;
1062f32df58aSBoris Brezillon 	u32 output_flags = 0;
1063f32df58aSBoris Brezillon 
1064f32df58aSBoris Brezillon 	bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
1065f32df58aSBoris Brezillon 
1066f32df58aSBoris Brezillon 	/* No bridge state attached to this bridge => nothing to propagate. */
1067f32df58aSBoris Brezillon 	if (!bridge_state)
1068f32df58aSBoris Brezillon 		return;
1069f32df58aSBoris Brezillon 
1070f32df58aSBoris Brezillon 	next_bridge = drm_bridge_get_next_bridge(bridge);
1071f32df58aSBoris Brezillon 
1072f32df58aSBoris Brezillon 	/*
1073f32df58aSBoris Brezillon 	 * Let's try to apply the most common case here, that is, propagate
1074f32df58aSBoris Brezillon 	 * display_info flags for the last bridge, and propagate the input
1075f32df58aSBoris Brezillon 	 * flags of the next bridge element to the output end of the current
1076f32df58aSBoris Brezillon 	 * bridge when the bridge is not the last one.
1077f32df58aSBoris Brezillon 	 * There are exceptions to this rule, like when signal inversion is
1078f32df58aSBoris Brezillon 	 * happening at the board level, but that's something drivers can deal
1079f32df58aSBoris Brezillon 	 * with from their &drm_bridge_funcs.atomic_check() implementation by
1080f32df58aSBoris Brezillon 	 * simply overriding the flags value we've set here.
1081f32df58aSBoris Brezillon 	 */
1082f32df58aSBoris Brezillon 	if (!next_bridge) {
1083f32df58aSBoris Brezillon 		output_flags = conn->display_info.bus_flags;
1084f32df58aSBoris Brezillon 	} else {
1085f32df58aSBoris Brezillon 		next_bridge_state = drm_atomic_get_new_bridge_state(state,
1086f32df58aSBoris Brezillon 								next_bridge);
1087f32df58aSBoris Brezillon 		/*
1088f32df58aSBoris Brezillon 		 * No bridge state attached to the next bridge, just leave the
1089f32df58aSBoris Brezillon 		 * flags to 0.
1090f32df58aSBoris Brezillon 		 */
1091f32df58aSBoris Brezillon 		if (next_bridge_state)
1092f32df58aSBoris Brezillon 			output_flags = next_bridge_state->input_bus_cfg.flags;
1093f32df58aSBoris Brezillon 	}
1094f32df58aSBoris Brezillon 
1095f32df58aSBoris Brezillon 	bridge_state->output_bus_cfg.flags = output_flags;
1096f32df58aSBoris Brezillon 
1097f32df58aSBoris Brezillon 	/*
10980ae865efSCai Huoqing 	 * Propagate the output flags to the input end of the bridge. Again, it's
1099f32df58aSBoris Brezillon 	 * not necessarily what all bridges want, but that's what most of them
1100f32df58aSBoris Brezillon 	 * do, and by doing that by default we avoid forcing drivers to
1101f32df58aSBoris Brezillon 	 * duplicate the "dummy propagation" logic.
1102f32df58aSBoris Brezillon 	 */
1103f32df58aSBoris Brezillon 	bridge_state->input_bus_cfg.flags = output_flags;
1104f32df58aSBoris Brezillon }
1105f32df58aSBoris Brezillon 
11065061b8a9SBoris Brezillon /**
11075061b8a9SBoris Brezillon  * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain
11085061b8a9SBoris Brezillon  * @bridge: bridge control structure
11095061b8a9SBoris Brezillon  * @crtc_state: new CRTC state
11105061b8a9SBoris Brezillon  * @conn_state: new connector state
11115061b8a9SBoris Brezillon  *
1112f32df58aSBoris Brezillon  * First trigger a bus format negotiation before calling
1113f32df58aSBoris Brezillon  * &drm_bridge_funcs.atomic_check() (falls back on
11145061b8a9SBoris Brezillon  * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain,
11155061b8a9SBoris Brezillon  * starting from the last bridge to the first. These are called before calling
11165061b8a9SBoris Brezillon  * &drm_encoder_helper_funcs.atomic_check()
11175061b8a9SBoris Brezillon  *
11185061b8a9SBoris Brezillon  * RETURNS:
11195061b8a9SBoris Brezillon  * 0 on success, a negative error code on failure
11205061b8a9SBoris Brezillon  */
drm_atomic_bridge_chain_check(struct drm_bridge * bridge,struct drm_crtc_state * crtc_state,struct drm_connector_state * conn_state)11215061b8a9SBoris Brezillon int drm_atomic_bridge_chain_check(struct drm_bridge *bridge,
11225061b8a9SBoris Brezillon 				  struct drm_crtc_state *crtc_state,
11235061b8a9SBoris Brezillon 				  struct drm_connector_state *conn_state)
11245061b8a9SBoris Brezillon {
1125f32df58aSBoris Brezillon 	struct drm_connector *conn = conn_state->connector;
11265061b8a9SBoris Brezillon 	struct drm_encoder *encoder;
11275061b8a9SBoris Brezillon 	struct drm_bridge *iter;
1128f32df58aSBoris Brezillon 	int ret;
11295061b8a9SBoris Brezillon 
11305061b8a9SBoris Brezillon 	if (!bridge)
11315061b8a9SBoris Brezillon 		return 0;
11325061b8a9SBoris Brezillon 
1133f32df58aSBoris Brezillon 	ret = drm_atomic_bridge_chain_select_bus_fmts(bridge, crtc_state,
1134f32df58aSBoris Brezillon 						      conn_state);
1135f32df58aSBoris Brezillon 	if (ret)
1136f32df58aSBoris Brezillon 		return ret;
1137f32df58aSBoris Brezillon 
11385061b8a9SBoris Brezillon 	encoder = bridge->encoder;
11395061b8a9SBoris Brezillon 	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
11405061b8a9SBoris Brezillon 		int ret;
11415061b8a9SBoris Brezillon 
1142f32df58aSBoris Brezillon 		/*
1143f32df58aSBoris Brezillon 		 * Bus flags are propagated by default. If a bridge needs to
1144f32df58aSBoris Brezillon 		 * tweak the input bus flags for any reason, it should happen
1145f32df58aSBoris Brezillon 		 * in its &drm_bridge_funcs.atomic_check() implementation such
1146f32df58aSBoris Brezillon 		 * that preceding bridges in the chain can propagate the new
1147f32df58aSBoris Brezillon 		 * bus flags.
1148f32df58aSBoris Brezillon 		 */
1149f32df58aSBoris Brezillon 		drm_atomic_bridge_propagate_bus_flags(iter, conn,
1150f32df58aSBoris Brezillon 						      crtc_state->state);
1151f32df58aSBoris Brezillon 
11525061b8a9SBoris Brezillon 		ret = drm_atomic_bridge_check(iter, crtc_state, conn_state);
11535061b8a9SBoris Brezillon 		if (ret)
11545061b8a9SBoris Brezillon 			return ret;
11555061b8a9SBoris Brezillon 
11565061b8a9SBoris Brezillon 		if (iter == bridge)
11575061b8a9SBoris Brezillon 			break;
11585061b8a9SBoris Brezillon 	}
11595061b8a9SBoris Brezillon 
11605061b8a9SBoris Brezillon 	return 0;
11615061b8a9SBoris Brezillon }
11625061b8a9SBoris Brezillon EXPORT_SYMBOL(drm_atomic_bridge_chain_check);
11635061b8a9SBoris Brezillon 
116411f6c4b1SLaurent Pinchart /**
116511f6c4b1SLaurent Pinchart  * drm_bridge_detect - check if anything is attached to the bridge output
116611f6c4b1SLaurent Pinchart  * @bridge: bridge control structure
116711f6c4b1SLaurent Pinchart  *
116811f6c4b1SLaurent Pinchart  * If the bridge supports output detection, as reported by the
116911f6c4b1SLaurent Pinchart  * DRM_BRIDGE_OP_DETECT bridge ops flag, call &drm_bridge_funcs.detect for the
117011f6c4b1SLaurent Pinchart  * bridge and return the connection status. Otherwise return
117111f6c4b1SLaurent Pinchart  * connector_status_unknown.
117211f6c4b1SLaurent Pinchart  *
117311f6c4b1SLaurent Pinchart  * RETURNS:
117411f6c4b1SLaurent Pinchart  * The detection status on success, or connector_status_unknown if the bridge
117511f6c4b1SLaurent Pinchart  * doesn't support output detection.
117611f6c4b1SLaurent Pinchart  */
drm_bridge_detect(struct drm_bridge * bridge)117711f6c4b1SLaurent Pinchart enum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge)
117811f6c4b1SLaurent Pinchart {
117911f6c4b1SLaurent Pinchart 	if (!(bridge->ops & DRM_BRIDGE_OP_DETECT))
118011f6c4b1SLaurent Pinchart 		return connector_status_unknown;
118111f6c4b1SLaurent Pinchart 
118211f6c4b1SLaurent Pinchart 	return bridge->funcs->detect(bridge);
118311f6c4b1SLaurent Pinchart }
118411f6c4b1SLaurent Pinchart EXPORT_SYMBOL_GPL(drm_bridge_detect);
118511f6c4b1SLaurent Pinchart 
118611f6c4b1SLaurent Pinchart /**
118711f6c4b1SLaurent Pinchart  * drm_bridge_get_modes - fill all modes currently valid for the sink into the
118811f6c4b1SLaurent Pinchart  * @connector
118911f6c4b1SLaurent Pinchart  * @bridge: bridge control structure
119011f6c4b1SLaurent Pinchart  * @connector: the connector to fill with modes
119111f6c4b1SLaurent Pinchart  *
119211f6c4b1SLaurent Pinchart  * If the bridge supports output modes retrieval, as reported by the
119311f6c4b1SLaurent Pinchart  * DRM_BRIDGE_OP_MODES bridge ops flag, call &drm_bridge_funcs.get_modes to
119411f6c4b1SLaurent Pinchart  * fill the connector with all valid modes and return the number of modes
119511f6c4b1SLaurent Pinchart  * added. Otherwise return 0.
119611f6c4b1SLaurent Pinchart  *
119711f6c4b1SLaurent Pinchart  * RETURNS:
119811f6c4b1SLaurent Pinchart  * The number of modes added to the connector.
119911f6c4b1SLaurent Pinchart  */
drm_bridge_get_modes(struct drm_bridge * bridge,struct drm_connector * connector)120011f6c4b1SLaurent Pinchart int drm_bridge_get_modes(struct drm_bridge *bridge,
120111f6c4b1SLaurent Pinchart 			 struct drm_connector *connector)
120211f6c4b1SLaurent Pinchart {
120311f6c4b1SLaurent Pinchart 	if (!(bridge->ops & DRM_BRIDGE_OP_MODES))
120411f6c4b1SLaurent Pinchart 		return 0;
120511f6c4b1SLaurent Pinchart 
120611f6c4b1SLaurent Pinchart 	return bridge->funcs->get_modes(bridge, connector);
120711f6c4b1SLaurent Pinchart }
120811f6c4b1SLaurent Pinchart EXPORT_SYMBOL_GPL(drm_bridge_get_modes);
120911f6c4b1SLaurent Pinchart 
121011f6c4b1SLaurent Pinchart /**
12112b6aaf7bSJani Nikula  * drm_bridge_edid_read - read the EDID data of the connected display
12122b6aaf7bSJani Nikula  * @bridge: bridge control structure
12132b6aaf7bSJani Nikula  * @connector: the connector to read EDID for
12142b6aaf7bSJani Nikula  *
12152b6aaf7bSJani Nikula  * If the bridge supports output EDID retrieval, as reported by the
12162b6aaf7bSJani Nikula  * DRM_BRIDGE_OP_EDID bridge ops flag, call &drm_bridge_funcs.edid_read to get
12172b6aaf7bSJani Nikula  * the EDID and return it. Otherwise return NULL.
12182b6aaf7bSJani Nikula  *
12192b6aaf7bSJani Nikula  * If &drm_bridge_funcs.edid_read is not set, fall back to using
12202b6aaf7bSJani Nikula  * drm_bridge_get_edid() and wrapping it in struct drm_edid.
12212b6aaf7bSJani Nikula  *
12222b6aaf7bSJani Nikula  * RETURNS:
12232b6aaf7bSJani Nikula  * The retrieved EDID on success, or NULL otherwise.
12242b6aaf7bSJani Nikula  */
drm_bridge_edid_read(struct drm_bridge * bridge,struct drm_connector * connector)12252b6aaf7bSJani Nikula const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge,
12262b6aaf7bSJani Nikula 					    struct drm_connector *connector)
12272b6aaf7bSJani Nikula {
12282b6aaf7bSJani Nikula 	if (!(bridge->ops & DRM_BRIDGE_OP_EDID))
12292b6aaf7bSJani Nikula 		return NULL;
12302b6aaf7bSJani Nikula 
12312b6aaf7bSJani Nikula 	/* Transitional: Fall back to ->get_edid. */
12322b6aaf7bSJani Nikula 	if (!bridge->funcs->edid_read) {
12332b6aaf7bSJani Nikula 		const struct drm_edid *drm_edid;
12342b6aaf7bSJani Nikula 		struct edid *edid;
12352b6aaf7bSJani Nikula 
12362b6aaf7bSJani Nikula 		edid = drm_bridge_get_edid(bridge, connector);
12372b6aaf7bSJani Nikula 		if (!edid)
12382b6aaf7bSJani Nikula 			return NULL;
12392b6aaf7bSJani Nikula 
12402b6aaf7bSJani Nikula 		drm_edid = drm_edid_alloc(edid, (edid->extensions + 1) * EDID_LENGTH);
12412b6aaf7bSJani Nikula 
12422b6aaf7bSJani Nikula 		kfree(edid);
12432b6aaf7bSJani Nikula 
12442b6aaf7bSJani Nikula 		return drm_edid;
12452b6aaf7bSJani Nikula 	}
12462b6aaf7bSJani Nikula 
12472b6aaf7bSJani Nikula 	return bridge->funcs->edid_read(bridge, connector);
12482b6aaf7bSJani Nikula }
12492b6aaf7bSJani Nikula EXPORT_SYMBOL_GPL(drm_bridge_edid_read);
12502b6aaf7bSJani Nikula 
12512b6aaf7bSJani Nikula /**
125211f6c4b1SLaurent Pinchart  * drm_bridge_get_edid - get the EDID data of the connected display
125311f6c4b1SLaurent Pinchart  * @bridge: bridge control structure
125411f6c4b1SLaurent Pinchart  * @connector: the connector to read EDID for
125511f6c4b1SLaurent Pinchart  *
125611f6c4b1SLaurent Pinchart  * If the bridge supports output EDID retrieval, as reported by the
125711f6c4b1SLaurent Pinchart  * DRM_BRIDGE_OP_EDID bridge ops flag, call &drm_bridge_funcs.get_edid to
125811d3cf80SLaurent Pinchart  * get the EDID and return it. Otherwise return NULL.
125911f6c4b1SLaurent Pinchart  *
12602b6aaf7bSJani Nikula  * Deprecated. Prefer using drm_bridge_edid_read().
12612b6aaf7bSJani Nikula  *
126211f6c4b1SLaurent Pinchart  * RETURNS:
126311d3cf80SLaurent Pinchart  * The retrieved EDID on success, or NULL otherwise.
126411f6c4b1SLaurent Pinchart  */
drm_bridge_get_edid(struct drm_bridge * bridge,struct drm_connector * connector)126511f6c4b1SLaurent Pinchart struct edid *drm_bridge_get_edid(struct drm_bridge *bridge,
126611f6c4b1SLaurent Pinchart 				 struct drm_connector *connector)
126711f6c4b1SLaurent Pinchart {
126811f6c4b1SLaurent Pinchart 	if (!(bridge->ops & DRM_BRIDGE_OP_EDID))
126911d3cf80SLaurent Pinchart 		return NULL;
127011f6c4b1SLaurent Pinchart 
127111f6c4b1SLaurent Pinchart 	return bridge->funcs->get_edid(bridge, connector);
127211f6c4b1SLaurent Pinchart }
127311f6c4b1SLaurent Pinchart EXPORT_SYMBOL_GPL(drm_bridge_get_edid);
127411f6c4b1SLaurent Pinchart 
127511f6c4b1SLaurent Pinchart /**
127611f6c4b1SLaurent Pinchart  * drm_bridge_hpd_enable - enable hot plug detection for the bridge
127711f6c4b1SLaurent Pinchart  * @bridge: bridge control structure
127811f6c4b1SLaurent Pinchart  * @cb: hot-plug detection callback
127911f6c4b1SLaurent Pinchart  * @data: data to be passed to the hot-plug detection callback
128011f6c4b1SLaurent Pinchart  *
128111f6c4b1SLaurent Pinchart  * Call &drm_bridge_funcs.hpd_enable if implemented and register the given @cb
128211f6c4b1SLaurent Pinchart  * and @data as hot plug notification callback. From now on the @cb will be
128311f6c4b1SLaurent Pinchart  * called with @data when an output status change is detected by the bridge,
128411f6c4b1SLaurent Pinchart  * until hot plug notification gets disabled with drm_bridge_hpd_disable().
128511f6c4b1SLaurent Pinchart  *
128611f6c4b1SLaurent Pinchart  * Hot plug detection is supported only if the DRM_BRIDGE_OP_HPD flag is set in
128711f6c4b1SLaurent Pinchart  * bridge->ops. This function shall not be called when the flag is not set.
128811f6c4b1SLaurent Pinchart  *
128911f6c4b1SLaurent Pinchart  * Only one hot plug detection callback can be registered at a time, it is an
129011f6c4b1SLaurent Pinchart  * error to call this function when hot plug detection is already enabled for
129111f6c4b1SLaurent Pinchart  * the bridge.
129211f6c4b1SLaurent Pinchart  */
drm_bridge_hpd_enable(struct drm_bridge * bridge,void (* cb)(void * data,enum drm_connector_status status),void * data)129311f6c4b1SLaurent Pinchart void drm_bridge_hpd_enable(struct drm_bridge *bridge,
129411f6c4b1SLaurent Pinchart 			   void (*cb)(void *data,
129511f6c4b1SLaurent Pinchart 				      enum drm_connector_status status),
129611f6c4b1SLaurent Pinchart 			   void *data)
129711f6c4b1SLaurent Pinchart {
129811f6c4b1SLaurent Pinchart 	if (!(bridge->ops & DRM_BRIDGE_OP_HPD))
129911f6c4b1SLaurent Pinchart 		return;
130011f6c4b1SLaurent Pinchart 
130111f6c4b1SLaurent Pinchart 	mutex_lock(&bridge->hpd_mutex);
130211f6c4b1SLaurent Pinchart 
130311f6c4b1SLaurent Pinchart 	if (WARN(bridge->hpd_cb, "Hot plug detection already enabled\n"))
130411f6c4b1SLaurent Pinchart 		goto unlock;
130511f6c4b1SLaurent Pinchart 
130611f6c4b1SLaurent Pinchart 	bridge->hpd_cb = cb;
130711f6c4b1SLaurent Pinchart 	bridge->hpd_data = data;
130811f6c4b1SLaurent Pinchart 
130911f6c4b1SLaurent Pinchart 	if (bridge->funcs->hpd_enable)
131011f6c4b1SLaurent Pinchart 		bridge->funcs->hpd_enable(bridge);
131111f6c4b1SLaurent Pinchart 
131211f6c4b1SLaurent Pinchart unlock:
131311f6c4b1SLaurent Pinchart 	mutex_unlock(&bridge->hpd_mutex);
131411f6c4b1SLaurent Pinchart }
131511f6c4b1SLaurent Pinchart EXPORT_SYMBOL_GPL(drm_bridge_hpd_enable);
131611f6c4b1SLaurent Pinchart 
131711f6c4b1SLaurent Pinchart /**
131811f6c4b1SLaurent Pinchart  * drm_bridge_hpd_disable - disable hot plug detection for the bridge
131911f6c4b1SLaurent Pinchart  * @bridge: bridge control structure
132011f6c4b1SLaurent Pinchart  *
132111f6c4b1SLaurent Pinchart  * Call &drm_bridge_funcs.hpd_disable if implemented and unregister the hot
132211f6c4b1SLaurent Pinchart  * plug detection callback previously registered with drm_bridge_hpd_enable().
132311f6c4b1SLaurent Pinchart  * Once this function returns the callback will not be called by the bridge
132411f6c4b1SLaurent Pinchart  * when an output status change occurs.
132511f6c4b1SLaurent Pinchart  *
132611f6c4b1SLaurent Pinchart  * Hot plug detection is supported only if the DRM_BRIDGE_OP_HPD flag is set in
132711f6c4b1SLaurent Pinchart  * bridge->ops. This function shall not be called when the flag is not set.
132811f6c4b1SLaurent Pinchart  */
drm_bridge_hpd_disable(struct drm_bridge * bridge)132911f6c4b1SLaurent Pinchart void drm_bridge_hpd_disable(struct drm_bridge *bridge)
133011f6c4b1SLaurent Pinchart {
133111f6c4b1SLaurent Pinchart 	if (!(bridge->ops & DRM_BRIDGE_OP_HPD))
133211f6c4b1SLaurent Pinchart 		return;
133311f6c4b1SLaurent Pinchart 
133411f6c4b1SLaurent Pinchart 	mutex_lock(&bridge->hpd_mutex);
133511f6c4b1SLaurent Pinchart 	if (bridge->funcs->hpd_disable)
133611f6c4b1SLaurent Pinchart 		bridge->funcs->hpd_disable(bridge);
133711f6c4b1SLaurent Pinchart 
133811f6c4b1SLaurent Pinchart 	bridge->hpd_cb = NULL;
133911f6c4b1SLaurent Pinchart 	bridge->hpd_data = NULL;
134011f6c4b1SLaurent Pinchart 	mutex_unlock(&bridge->hpd_mutex);
134111f6c4b1SLaurent Pinchart }
134211f6c4b1SLaurent Pinchart EXPORT_SYMBOL_GPL(drm_bridge_hpd_disable);
134311f6c4b1SLaurent Pinchart 
134411f6c4b1SLaurent Pinchart /**
134511f6c4b1SLaurent Pinchart  * drm_bridge_hpd_notify - notify hot plug detection events
134611f6c4b1SLaurent Pinchart  * @bridge: bridge control structure
134711f6c4b1SLaurent Pinchart  * @status: output connection status
134811f6c4b1SLaurent Pinchart  *
134911f6c4b1SLaurent Pinchart  * Bridge drivers shall call this function to report hot plug events when they
135011f6c4b1SLaurent Pinchart  * detect a change in the output status, when hot plug detection has been
135111f6c4b1SLaurent Pinchart  * enabled by drm_bridge_hpd_enable().
135211f6c4b1SLaurent Pinchart  *
135311f6c4b1SLaurent Pinchart  * This function shall be called in a context that can sleep.
135411f6c4b1SLaurent Pinchart  */
drm_bridge_hpd_notify(struct drm_bridge * bridge,enum drm_connector_status status)135511f6c4b1SLaurent Pinchart void drm_bridge_hpd_notify(struct drm_bridge *bridge,
135611f6c4b1SLaurent Pinchart 			   enum drm_connector_status status)
135711f6c4b1SLaurent Pinchart {
135811f6c4b1SLaurent Pinchart 	mutex_lock(&bridge->hpd_mutex);
135911f6c4b1SLaurent Pinchart 	if (bridge->hpd_cb)
136011f6c4b1SLaurent Pinchart 		bridge->hpd_cb(bridge->hpd_data, status);
136111f6c4b1SLaurent Pinchart 	mutex_unlock(&bridge->hpd_mutex);
136211f6c4b1SLaurent Pinchart }
136311f6c4b1SLaurent Pinchart EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify);
136411f6c4b1SLaurent Pinchart 
13653d3f8b1fSAjay Kumar #ifdef CONFIG_OF
13662331b4e4SArchit Taneja /**
13672331b4e4SArchit Taneja  * of_drm_find_bridge - find the bridge corresponding to the device node in
13682331b4e4SArchit Taneja  *			the global bridge list
13692331b4e4SArchit Taneja  *
13702331b4e4SArchit Taneja  * @np: device node
13712331b4e4SArchit Taneja  *
13722331b4e4SArchit Taneja  * RETURNS:
13732331b4e4SArchit Taneja  * drm_bridge control struct on success, NULL on failure
13742331b4e4SArchit Taneja  */
of_drm_find_bridge(struct device_node * np)13753d3f8b1fSAjay Kumar struct drm_bridge *of_drm_find_bridge(struct device_node *np)
13763d3f8b1fSAjay Kumar {
13773d3f8b1fSAjay Kumar 	struct drm_bridge *bridge;
13783d3f8b1fSAjay Kumar 
13793d3f8b1fSAjay Kumar 	mutex_lock(&bridge_lock);
13803d3f8b1fSAjay Kumar 
13813d3f8b1fSAjay Kumar 	list_for_each_entry(bridge, &bridge_list, list) {
13823d3f8b1fSAjay Kumar 		if (bridge->of_node == np) {
13833d3f8b1fSAjay Kumar 			mutex_unlock(&bridge_lock);
13843d3f8b1fSAjay Kumar 			return bridge;
13853d3f8b1fSAjay Kumar 		}
13863d3f8b1fSAjay Kumar 	}
13873d3f8b1fSAjay Kumar 
13883d3f8b1fSAjay Kumar 	mutex_unlock(&bridge_lock);
13893d3f8b1fSAjay Kumar 	return NULL;
13903d3f8b1fSAjay Kumar }
13913d3f8b1fSAjay Kumar EXPORT_SYMBOL(of_drm_find_bridge);
13923d3f8b1fSAjay Kumar #endif
13933d3f8b1fSAjay Kumar 
13948e4bb53cSTomi Valkeinen #ifdef CONFIG_DEBUG_FS
drm_bridge_chains_info(struct seq_file * m,void * data)13958e4bb53cSTomi Valkeinen static int drm_bridge_chains_info(struct seq_file *m, void *data)
13968e4bb53cSTomi Valkeinen {
13978e4bb53cSTomi Valkeinen 	struct drm_debugfs_entry *entry = m->private;
13988e4bb53cSTomi Valkeinen 	struct drm_device *dev = entry->dev;
13998e4bb53cSTomi Valkeinen 	struct drm_printer p = drm_seq_file_printer(m);
14008e4bb53cSTomi Valkeinen 	struct drm_mode_config *config = &dev->mode_config;
14018e4bb53cSTomi Valkeinen 	struct drm_encoder *encoder;
14028e4bb53cSTomi Valkeinen 	unsigned int bridge_idx = 0;
14038e4bb53cSTomi Valkeinen 
14048e4bb53cSTomi Valkeinen 	list_for_each_entry(encoder, &config->encoder_list, head) {
14058e4bb53cSTomi Valkeinen 		struct drm_bridge *bridge;
14068e4bb53cSTomi Valkeinen 
14078e4bb53cSTomi Valkeinen 		drm_printf(&p, "encoder[%u]\n", encoder->base.id);
14088e4bb53cSTomi Valkeinen 
14098e4bb53cSTomi Valkeinen 		drm_for_each_bridge_in_chain(encoder, bridge) {
14108e4bb53cSTomi Valkeinen 			drm_printf(&p, "\tbridge[%u] type: %u, ops: %#x",
14118e4bb53cSTomi Valkeinen 				   bridge_idx, bridge->type, bridge->ops);
14128e4bb53cSTomi Valkeinen 
14138e4bb53cSTomi Valkeinen #ifdef CONFIG_OF
14148e4bb53cSTomi Valkeinen 			if (bridge->of_node)
14158e4bb53cSTomi Valkeinen 				drm_printf(&p, ", OF: %pOFfc", bridge->of_node);
14168e4bb53cSTomi Valkeinen #endif
14178e4bb53cSTomi Valkeinen 
14188e4bb53cSTomi Valkeinen 			drm_printf(&p, "\n");
14198e4bb53cSTomi Valkeinen 
14208e4bb53cSTomi Valkeinen 			bridge_idx++;
14218e4bb53cSTomi Valkeinen 		}
14228e4bb53cSTomi Valkeinen 	}
14238e4bb53cSTomi Valkeinen 
14248e4bb53cSTomi Valkeinen 	return 0;
14258e4bb53cSTomi Valkeinen }
14268e4bb53cSTomi Valkeinen 
14278e4bb53cSTomi Valkeinen static const struct drm_debugfs_info drm_bridge_debugfs_list[] = {
14288e4bb53cSTomi Valkeinen 	{ "bridge_chains", drm_bridge_chains_info, 0 },
14298e4bb53cSTomi Valkeinen };
14308e4bb53cSTomi Valkeinen 
drm_bridge_debugfs_init(struct drm_minor * minor)14318e4bb53cSTomi Valkeinen void drm_bridge_debugfs_init(struct drm_minor *minor)
14328e4bb53cSTomi Valkeinen {
14338e4bb53cSTomi Valkeinen 	drm_debugfs_add_files(minor->dev, drm_bridge_debugfs_list,
14348e4bb53cSTomi Valkeinen 			      ARRAY_SIZE(drm_bridge_debugfs_list));
14358e4bb53cSTomi Valkeinen }
14368e4bb53cSTomi Valkeinen #endif
14378e4bb53cSTomi Valkeinen 
14383d3f8b1fSAjay Kumar MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@samsung.com>");
14393d3f8b1fSAjay Kumar MODULE_DESCRIPTION("DRM bridge infrastructure");
14403d3f8b1fSAjay Kumar MODULE_LICENSE("GPL and additional rights");
1441