18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
48c2ecf20Sopenharmony_ci * Copyright (C) 2017 Broadcom
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <drm/drm_atomic_helper.h>
88c2ecf20Sopenharmony_ci#include <drm/drm_bridge.h>
98c2ecf20Sopenharmony_ci#include <drm/drm_connector.h>
108c2ecf20Sopenharmony_ci#include <drm/drm_encoder.h>
118c2ecf20Sopenharmony_ci#include <drm/drm_modeset_helper_vtables.h>
128c2ecf20Sopenharmony_ci#include <drm/drm_panel.h>
138c2ecf20Sopenharmony_ci#include <drm/drm_print.h>
148c2ecf20Sopenharmony_ci#include <drm/drm_probe_helper.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistruct panel_bridge {
178c2ecf20Sopenharmony_ci	struct drm_bridge bridge;
188c2ecf20Sopenharmony_ci	struct drm_connector connector;
198c2ecf20Sopenharmony_ci	struct drm_panel *panel;
208c2ecf20Sopenharmony_ci	u32 connector_type;
218c2ecf20Sopenharmony_ci};
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic inline struct panel_bridge *
248c2ecf20Sopenharmony_cidrm_bridge_to_panel_bridge(struct drm_bridge *bridge)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	return container_of(bridge, struct panel_bridge, bridge);
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic inline struct panel_bridge *
308c2ecf20Sopenharmony_cidrm_connector_to_panel_bridge(struct drm_connector *connector)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	return container_of(connector, struct panel_bridge, connector);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic int panel_bridge_connector_get_modes(struct drm_connector *connector)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge =
388c2ecf20Sopenharmony_ci		drm_connector_to_panel_bridge(connector);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	return drm_panel_get_modes(panel_bridge->panel, connector);
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic const struct drm_connector_helper_funcs
448c2ecf20Sopenharmony_cipanel_bridge_connector_helper_funcs = {
458c2ecf20Sopenharmony_ci	.get_modes = panel_bridge_connector_get_modes,
468c2ecf20Sopenharmony_ci};
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic const struct drm_connector_funcs panel_bridge_connector_funcs = {
498c2ecf20Sopenharmony_ci	.reset = drm_atomic_helper_connector_reset,
508c2ecf20Sopenharmony_ci	.fill_modes = drm_helper_probe_single_connector_modes,
518c2ecf20Sopenharmony_ci	.destroy = drm_connector_cleanup,
528c2ecf20Sopenharmony_ci	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
538c2ecf20Sopenharmony_ci	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
548c2ecf20Sopenharmony_ci};
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic int panel_bridge_attach(struct drm_bridge *bridge,
578c2ecf20Sopenharmony_ci			       enum drm_bridge_attach_flags flags)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
608c2ecf20Sopenharmony_ci	struct drm_connector *connector = &panel_bridge->connector;
618c2ecf20Sopenharmony_ci	int ret;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
648c2ecf20Sopenharmony_ci		return 0;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (!bridge->encoder) {
678c2ecf20Sopenharmony_ci		DRM_ERROR("Missing encoder\n");
688c2ecf20Sopenharmony_ci		return -ENODEV;
698c2ecf20Sopenharmony_ci	}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	drm_connector_helper_add(connector,
728c2ecf20Sopenharmony_ci				 &panel_bridge_connector_helper_funcs);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	ret = drm_connector_init(bridge->dev, connector,
758c2ecf20Sopenharmony_ci				 &panel_bridge_connector_funcs,
768c2ecf20Sopenharmony_ci				 panel_bridge->connector_type);
778c2ecf20Sopenharmony_ci	if (ret) {
788c2ecf20Sopenharmony_ci		DRM_ERROR("Failed to initialize connector\n");
798c2ecf20Sopenharmony_ci		return ret;
808c2ecf20Sopenharmony_ci	}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	drm_connector_attach_encoder(&panel_bridge->connector,
838c2ecf20Sopenharmony_ci					  bridge->encoder);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	return 0;
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic void panel_bridge_detach(struct drm_bridge *bridge)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
918c2ecf20Sopenharmony_ci	struct drm_connector *connector = &panel_bridge->connector;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	/*
948c2ecf20Sopenharmony_ci	 * Cleanup the connector if we know it was initialized.
958c2ecf20Sopenharmony_ci	 *
968c2ecf20Sopenharmony_ci	 * FIXME: This wouldn't be needed if the panel_bridge structure was
978c2ecf20Sopenharmony_ci	 * allocated with drmm_kzalloc(). This might be tricky since the
988c2ecf20Sopenharmony_ci	 * drm_device pointer can only be retrieved when the bridge is attached.
998c2ecf20Sopenharmony_ci	 */
1008c2ecf20Sopenharmony_ci	if (connector->dev)
1018c2ecf20Sopenharmony_ci		drm_connector_cleanup(connector);
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic void panel_bridge_pre_enable(struct drm_bridge *bridge)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	drm_panel_prepare(panel_bridge->panel);
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic void panel_bridge_enable(struct drm_bridge *bridge)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	drm_panel_enable(panel_bridge->panel);
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic void panel_bridge_disable(struct drm_bridge *bridge)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	drm_panel_disable(panel_bridge->panel);
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic void panel_bridge_post_disable(struct drm_bridge *bridge)
1268c2ecf20Sopenharmony_ci{
1278c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	drm_panel_unprepare(panel_bridge->panel);
1308c2ecf20Sopenharmony_ci}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_cistatic int panel_bridge_get_modes(struct drm_bridge *bridge,
1338c2ecf20Sopenharmony_ci				  struct drm_connector *connector)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	return drm_panel_get_modes(panel_bridge->panel, connector);
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
1418c2ecf20Sopenharmony_ci	.attach = panel_bridge_attach,
1428c2ecf20Sopenharmony_ci	.detach = panel_bridge_detach,
1438c2ecf20Sopenharmony_ci	.pre_enable = panel_bridge_pre_enable,
1448c2ecf20Sopenharmony_ci	.enable = panel_bridge_enable,
1458c2ecf20Sopenharmony_ci	.disable = panel_bridge_disable,
1468c2ecf20Sopenharmony_ci	.post_disable = panel_bridge_post_disable,
1478c2ecf20Sopenharmony_ci	.get_modes = panel_bridge_get_modes,
1488c2ecf20Sopenharmony_ci	.atomic_reset = drm_atomic_helper_bridge_reset,
1498c2ecf20Sopenharmony_ci	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
1508c2ecf20Sopenharmony_ci	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
1518c2ecf20Sopenharmony_ci	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
1528c2ecf20Sopenharmony_ci};
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci/**
1558c2ecf20Sopenharmony_ci * drm_panel_bridge_add - Creates a &drm_bridge and &drm_connector that
1568c2ecf20Sopenharmony_ci * just calls the appropriate functions from &drm_panel.
1578c2ecf20Sopenharmony_ci *
1588c2ecf20Sopenharmony_ci * @panel: The drm_panel being wrapped.  Must be non-NULL.
1598c2ecf20Sopenharmony_ci *
1608c2ecf20Sopenharmony_ci * For drivers converting from directly using drm_panel: The expected
1618c2ecf20Sopenharmony_ci * usage pattern is that during either encoder module probe or DSI
1628c2ecf20Sopenharmony_ci * host attach, a drm_panel will be looked up through
1638c2ecf20Sopenharmony_ci * drm_of_find_panel_or_bridge().  drm_panel_bridge_add() is used to
1648c2ecf20Sopenharmony_ci * wrap that panel in the new bridge, and the result can then be
1658c2ecf20Sopenharmony_ci * passed to drm_bridge_attach().  The drm_panel_prepare() and related
1668c2ecf20Sopenharmony_ci * functions can be dropped from the encoder driver (they're now
1678c2ecf20Sopenharmony_ci * called by the KMS helpers before calling into the encoder), along
1688c2ecf20Sopenharmony_ci * with connector creation.  When done with the bridge (after
1698c2ecf20Sopenharmony_ci * drm_mode_config_cleanup() if the bridge has already been attached), then
1708c2ecf20Sopenharmony_ci * drm_panel_bridge_remove() to free it.
1718c2ecf20Sopenharmony_ci *
1728c2ecf20Sopenharmony_ci * The connector type is set to @panel->connector_type, which must be set to a
1738c2ecf20Sopenharmony_ci * known type. Calling this function with a panel whose connector type is
1748c2ecf20Sopenharmony_ci * DRM_MODE_CONNECTOR_Unknown will return ERR_PTR(-EINVAL).
1758c2ecf20Sopenharmony_ci *
1768c2ecf20Sopenharmony_ci * See devm_drm_panel_bridge_add() for an automatically managed version of this
1778c2ecf20Sopenharmony_ci * function.
1788c2ecf20Sopenharmony_ci */
1798c2ecf20Sopenharmony_cistruct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
1828c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	return drm_panel_bridge_add_typed(panel, panel->connector_type);
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_panel_bridge_add);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci/**
1898c2ecf20Sopenharmony_ci * drm_panel_bridge_add_typed - Creates a &drm_bridge and &drm_connector with
1908c2ecf20Sopenharmony_ci * an explicit connector type.
1918c2ecf20Sopenharmony_ci * @panel: The drm_panel being wrapped.  Must be non-NULL.
1928c2ecf20Sopenharmony_ci * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
1938c2ecf20Sopenharmony_ci *
1948c2ecf20Sopenharmony_ci * This is just like drm_panel_bridge_add(), but forces the connector type to
1958c2ecf20Sopenharmony_ci * @connector_type instead of infering it from the panel.
1968c2ecf20Sopenharmony_ci *
1978c2ecf20Sopenharmony_ci * This function is deprecated and should not be used in new drivers. Use
1988c2ecf20Sopenharmony_ci * drm_panel_bridge_add() instead, and fix panel drivers as necessary if they
1998c2ecf20Sopenharmony_ci * don't report a connector type.
2008c2ecf20Sopenharmony_ci */
2018c2ecf20Sopenharmony_cistruct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,
2028c2ecf20Sopenharmony_ci					      u32 connector_type)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	if (!panel)
2078c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	panel_bridge = devm_kzalloc(panel->dev, sizeof(*panel_bridge),
2108c2ecf20Sopenharmony_ci				    GFP_KERNEL);
2118c2ecf20Sopenharmony_ci	if (!panel_bridge)
2128c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	panel_bridge->connector_type = connector_type;
2158c2ecf20Sopenharmony_ci	panel_bridge->panel = panel;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	panel_bridge->bridge.funcs = &panel_bridge_bridge_funcs;
2188c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
2198c2ecf20Sopenharmony_ci	panel_bridge->bridge.of_node = panel->dev->of_node;
2208c2ecf20Sopenharmony_ci#endif
2218c2ecf20Sopenharmony_ci	panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
2228c2ecf20Sopenharmony_ci	panel_bridge->bridge.type = connector_type;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	drm_bridge_add(&panel_bridge->bridge);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	return &panel_bridge->bridge;
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_panel_bridge_add_typed);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci/**
2318c2ecf20Sopenharmony_ci * drm_panel_bridge_remove - Unregisters and frees a drm_bridge
2328c2ecf20Sopenharmony_ci * created by drm_panel_bridge_add().
2338c2ecf20Sopenharmony_ci *
2348c2ecf20Sopenharmony_ci * @bridge: The drm_bridge being freed.
2358c2ecf20Sopenharmony_ci */
2368c2ecf20Sopenharmony_civoid drm_panel_bridge_remove(struct drm_bridge *bridge)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if (!bridge)
2418c2ecf20Sopenharmony_ci		return;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	if (bridge->funcs != &panel_bridge_bridge_funcs)
2448c2ecf20Sopenharmony_ci		return;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	panel_bridge = drm_bridge_to_panel_bridge(bridge);
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	drm_bridge_remove(bridge);
2498c2ecf20Sopenharmony_ci	devm_kfree(panel_bridge->panel->dev, bridge);
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_panel_bridge_remove);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic void devm_drm_panel_bridge_release(struct device *dev, void *res)
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	struct drm_bridge **bridge = res;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	drm_panel_bridge_remove(*bridge);
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci/**
2618c2ecf20Sopenharmony_ci * devm_drm_panel_bridge_add - Creates a managed &drm_bridge and &drm_connector
2628c2ecf20Sopenharmony_ci * that just calls the appropriate functions from &drm_panel.
2638c2ecf20Sopenharmony_ci * @dev: device to tie the bridge lifetime to
2648c2ecf20Sopenharmony_ci * @panel: The drm_panel being wrapped.  Must be non-NULL.
2658c2ecf20Sopenharmony_ci *
2668c2ecf20Sopenharmony_ci * This is the managed version of drm_panel_bridge_add() which automatically
2678c2ecf20Sopenharmony_ci * calls drm_panel_bridge_remove() when @dev is unbound.
2688c2ecf20Sopenharmony_ci */
2698c2ecf20Sopenharmony_cistruct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
2708c2ecf20Sopenharmony_ci					     struct drm_panel *panel)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
2738c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	return devm_drm_panel_bridge_add_typed(dev, panel,
2768c2ecf20Sopenharmony_ci					       panel->connector_type);
2778c2ecf20Sopenharmony_ci}
2788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(devm_drm_panel_bridge_add);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci/**
2818c2ecf20Sopenharmony_ci * devm_drm_panel_bridge_add_typed - Creates a managed &drm_bridge and
2828c2ecf20Sopenharmony_ci * &drm_connector with an explicit connector type.
2838c2ecf20Sopenharmony_ci * @dev: device to tie the bridge lifetime to
2848c2ecf20Sopenharmony_ci * @panel: The drm_panel being wrapped.  Must be non-NULL.
2858c2ecf20Sopenharmony_ci * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
2868c2ecf20Sopenharmony_ci *
2878c2ecf20Sopenharmony_ci * This is just like devm_drm_panel_bridge_add(), but forces the connector type
2888c2ecf20Sopenharmony_ci * to @connector_type instead of infering it from the panel.
2898c2ecf20Sopenharmony_ci *
2908c2ecf20Sopenharmony_ci * This function is deprecated and should not be used in new drivers. Use
2918c2ecf20Sopenharmony_ci * devm_drm_panel_bridge_add() instead, and fix panel drivers as necessary if
2928c2ecf20Sopenharmony_ci * they don't report a connector type.
2938c2ecf20Sopenharmony_ci */
2948c2ecf20Sopenharmony_cistruct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
2958c2ecf20Sopenharmony_ci						   struct drm_panel *panel,
2968c2ecf20Sopenharmony_ci						   u32 connector_type)
2978c2ecf20Sopenharmony_ci{
2988c2ecf20Sopenharmony_ci	struct drm_bridge **ptr, *bridge;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	ptr = devres_alloc(devm_drm_panel_bridge_release, sizeof(*ptr),
3018c2ecf20Sopenharmony_ci			   GFP_KERNEL);
3028c2ecf20Sopenharmony_ci	if (!ptr)
3038c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	bridge = drm_panel_bridge_add_typed(panel, connector_type);
3068c2ecf20Sopenharmony_ci	if (!IS_ERR(bridge)) {
3078c2ecf20Sopenharmony_ci		*ptr = bridge;
3088c2ecf20Sopenharmony_ci		devres_add(dev, ptr);
3098c2ecf20Sopenharmony_ci	} else {
3108c2ecf20Sopenharmony_ci		devres_free(ptr);
3118c2ecf20Sopenharmony_ci	}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	return bridge;
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ciEXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci/**
3188c2ecf20Sopenharmony_ci * drm_panel_bridge_connector - return the connector for the panel bridge
3198c2ecf20Sopenharmony_ci * @bridge: The drm_bridge.
3208c2ecf20Sopenharmony_ci *
3218c2ecf20Sopenharmony_ci * drm_panel_bridge creates the connector.
3228c2ecf20Sopenharmony_ci * This function gives external access to the connector.
3238c2ecf20Sopenharmony_ci *
3248c2ecf20Sopenharmony_ci * Returns: Pointer to drm_connector
3258c2ecf20Sopenharmony_ci */
3268c2ecf20Sopenharmony_cistruct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	struct panel_bridge *panel_bridge;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	panel_bridge = drm_bridge_to_panel_bridge(bridge);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	return &panel_bridge->connector;
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_panel_bridge_connector);
335