18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef __DRM_OF_H__
38c2ecf20Sopenharmony_ci#define __DRM_OF_H__
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/of_graph.h>
68c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL_BRIDGE)
78c2ecf20Sopenharmony_ci#include <drm/drm_bridge.h>
88c2ecf20Sopenharmony_ci#endif
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cistruct component_master_ops;
118c2ecf20Sopenharmony_cistruct component_match;
128c2ecf20Sopenharmony_cistruct device;
138c2ecf20Sopenharmony_cistruct drm_device;
148c2ecf20Sopenharmony_cistruct drm_encoder;
158c2ecf20Sopenharmony_cistruct drm_panel;
168c2ecf20Sopenharmony_cistruct drm_bridge;
178c2ecf20Sopenharmony_cistruct device_node;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/**
208c2ecf20Sopenharmony_ci * enum drm_lvds_dual_link_pixels - Pixel order of an LVDS dual-link connection
218c2ecf20Sopenharmony_ci * @DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: Even pixels are expected to be generated
228c2ecf20Sopenharmony_ci *    from the first port, odd pixels from the second port
238c2ecf20Sopenharmony_ci * @DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: Odd pixels are expected to be generated
248c2ecf20Sopenharmony_ci *    from the first port, even pixels from the second port
258c2ecf20Sopenharmony_ci */
268c2ecf20Sopenharmony_cienum drm_lvds_dual_link_pixels {
278c2ecf20Sopenharmony_ci	DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS = 0,
288c2ecf20Sopenharmony_ci	DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS = 1,
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
328c2ecf20Sopenharmony_ciuint32_t drm_of_crtc_port_mask(struct drm_device *dev,
338c2ecf20Sopenharmony_ci			    struct device_node *port);
348c2ecf20Sopenharmony_ciuint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
358c2ecf20Sopenharmony_ci				    struct device_node *port);
368c2ecf20Sopenharmony_civoid drm_of_component_match_add(struct device *master,
378c2ecf20Sopenharmony_ci				struct component_match **matchptr,
388c2ecf20Sopenharmony_ci				int (*compare)(struct device *, void *),
398c2ecf20Sopenharmony_ci				struct device_node *node);
408c2ecf20Sopenharmony_ciint drm_of_component_probe(struct device *dev,
418c2ecf20Sopenharmony_ci			   int (*compare_of)(struct device *, void *),
428c2ecf20Sopenharmony_ci			   const struct component_master_ops *m_ops);
438c2ecf20Sopenharmony_ciint drm_of_encoder_active_endpoint(struct device_node *node,
448c2ecf20Sopenharmony_ci				   struct drm_encoder *encoder,
458c2ecf20Sopenharmony_ci				   struct of_endpoint *endpoint);
468c2ecf20Sopenharmony_ciint drm_of_find_panel_or_bridge(const struct device_node *np,
478c2ecf20Sopenharmony_ci				int port, int endpoint,
488c2ecf20Sopenharmony_ci				struct drm_panel **panel,
498c2ecf20Sopenharmony_ci				struct drm_bridge **bridge);
508c2ecf20Sopenharmony_ciint drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
518c2ecf20Sopenharmony_ci					  const struct device_node *port2);
528c2ecf20Sopenharmony_ci#else
538c2ecf20Sopenharmony_cistatic inline uint32_t drm_of_crtc_port_mask(struct drm_device *dev,
548c2ecf20Sopenharmony_ci					  struct device_node *port)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	return 0;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
608c2ecf20Sopenharmony_ci						  struct device_node *port)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	return 0;
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic inline void
668c2ecf20Sopenharmony_cidrm_of_component_match_add(struct device *master,
678c2ecf20Sopenharmony_ci			   struct component_match **matchptr,
688c2ecf20Sopenharmony_ci			   int (*compare)(struct device *, void *),
698c2ecf20Sopenharmony_ci			   struct device_node *node)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistatic inline int
748c2ecf20Sopenharmony_cidrm_of_component_probe(struct device *dev,
758c2ecf20Sopenharmony_ci		       int (*compare_of)(struct device *, void *),
768c2ecf20Sopenharmony_ci		       const struct component_master_ops *m_ops)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	return -EINVAL;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic inline int drm_of_encoder_active_endpoint(struct device_node *node,
828c2ecf20Sopenharmony_ci						 struct drm_encoder *encoder,
838c2ecf20Sopenharmony_ci						 struct of_endpoint *endpoint)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	return -EINVAL;
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_cistatic inline int drm_of_find_panel_or_bridge(const struct device_node *np,
888c2ecf20Sopenharmony_ci					      int port, int endpoint,
898c2ecf20Sopenharmony_ci					      struct drm_panel **panel,
908c2ecf20Sopenharmony_ci					      struct drm_bridge **bridge)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	return -EINVAL;
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic inline int
968c2ecf20Sopenharmony_cidrm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
978c2ecf20Sopenharmony_ci				      const struct device_node *port2)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	return -EINVAL;
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci#endif
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci/*
1048c2ecf20Sopenharmony_ci * drm_of_panel_bridge_remove - remove panel bridge
1058c2ecf20Sopenharmony_ci * @np: device tree node containing panel bridge output ports
1068c2ecf20Sopenharmony_ci *
1078c2ecf20Sopenharmony_ci * Remove the panel bridge of a given DT node's port and endpoint number
1088c2ecf20Sopenharmony_ci *
1098c2ecf20Sopenharmony_ci * Returns zero if successful, or one of the standard error codes if it fails.
1108c2ecf20Sopenharmony_ci */
1118c2ecf20Sopenharmony_cistatic inline int drm_of_panel_bridge_remove(const struct device_node *np,
1128c2ecf20Sopenharmony_ci					     int port, int endpoint)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL_BRIDGE)
1158c2ecf20Sopenharmony_ci	struct drm_bridge *bridge;
1168c2ecf20Sopenharmony_ci	struct device_node *remote;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	remote = of_graph_get_remote_node(np, port, endpoint);
1198c2ecf20Sopenharmony_ci	if (!remote)
1208c2ecf20Sopenharmony_ci		return -ENODEV;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	bridge = of_drm_find_bridge(remote);
1238c2ecf20Sopenharmony_ci	drm_panel_bridge_remove(bridge);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	return 0;
1268c2ecf20Sopenharmony_ci#else
1278c2ecf20Sopenharmony_ci	return -EINVAL;
1288c2ecf20Sopenharmony_ci#endif
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic inline int drm_of_encoder_active_endpoint_id(struct device_node *node,
1328c2ecf20Sopenharmony_ci						    struct drm_encoder *encoder)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	struct of_endpoint endpoint;
1358c2ecf20Sopenharmony_ci	int ret = drm_of_encoder_active_endpoint(node, encoder,
1368c2ecf20Sopenharmony_ci						 &endpoint);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	return ret ?: endpoint.id;
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic inline int drm_of_encoder_active_port_id(struct device_node *node,
1428c2ecf20Sopenharmony_ci						struct drm_encoder *encoder)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	struct of_endpoint endpoint;
1458c2ecf20Sopenharmony_ci	int ret = drm_of_encoder_active_endpoint(node, encoder,
1468c2ecf20Sopenharmony_ci						 &endpoint);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	return ret ?: endpoint.port;
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci#endif /* __DRM_OF_H__ */
152