linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/5] DRM OF graph clean-up
@ 2017-03-22 13:26 Rob Herring
  2017-03-22 13:26 ` [PATCH v3 1/5] drm: make of_drm_find_panel also depend on CONFIG_DRM_PANEL Rob Herring
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Rob Herring @ 2017-03-22 13:26 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, linux-kernel, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner, Alison Wang,
	Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Maxime Ripard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

I've been unhappy with the OF graph API for some time and decided to
do something about it. The problem is drivers have to do too much of the
graph parsing and walking themselves. This has led to the same pattern
duplicated over and over. This series adapts DRM drivers to use a new OF
graph helper and added DRM helper.

The DT dependency went into 4.11, so this series can be applied to the DRM
tree without any cross tree dependencies.

I've done some build testing only, so testing appreciated. A git branch is
here[1].

Rob

[1] git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git of-graph-helpers


Rob Herring (5):
  drm: make of_drm_find_panel also depend on CONFIG_DRM_PANEL
  drm: of: introduce drm_of_find_panel_or_bridge
  drm: convert drivers to use of_graph_get_remote_node
  drm: convert drivers to use drm_of_find_panel_or_bridge
  drm: omap: use common OF graph helpers

 drivers/gpu/drm/arm/hdlcd_drv.c                  |  22 +----
 drivers/gpu/drm/arm/malidp_drv.c                 |  28 +------
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c |  73 +++++-----------
 drivers/gpu/drm/bridge/adv7511/adv7533.c         |  12 +--
 drivers/gpu/drm/bridge/dumb-vga-dac.c            |  15 +---
 drivers/gpu/drm/bridge/nxp-ptn3460.c             |  16 +---
 drivers/gpu/drm/bridge/parade-ps8622.c           |  16 +---
 drivers/gpu/drm/bridge/tc358767.c                |  27 +-----
 drivers/gpu/drm/bridge/ti-tfp410.c               |  15 ++--
 drivers/gpu/drm/drm_of.c                         |  52 ++++++++++++
 drivers/gpu/drm/exynos/exynos_dp.c               |  35 +++-----
 drivers/gpu/drm/exynos/exynos_drm_dpi.c          |  16 +---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c          |  13 +--
 drivers/gpu/drm/exynos/exynos_drm_mic.c          |  25 +-----
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c        |  39 ++-------
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     |  27 +-----
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c  |  30 +------
 drivers/gpu/drm/imx/imx-ldb.c                    |  27 ++----
 drivers/gpu/drm/imx/parallel-display.c           |  36 +-------
 drivers/gpu/drm/mediatek/mtk_dpi.c               |  12 +--
 drivers/gpu/drm/mediatek/mtk_dsi.c               |  23 ++---
 drivers/gpu/drm/mediatek/mtk_hdmi.c              |  26 +-----
 drivers/gpu/drm/meson/meson_venc_cvbs.c          |  19 +----
 drivers/gpu/drm/msm/dsi/dsi_host.c               |   2 +-
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c          |  28 +------
 drivers/gpu/drm/mxsfb/mxsfb_out.c                |  40 ++-------
 drivers/gpu/drm/omapdrm/dss/dpi.c                |   2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c                |   3 +-
 drivers/gpu/drm/omapdrm/dss/dss-of.c             | 102 +----------------------
 drivers/gpu/drm/omapdrm/dss/dss.c                |  61 +++-----------
 drivers/gpu/drm/omapdrm/dss/hdmi4.c              |   3 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c              |   3 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h            |  11 ---
 drivers/gpu/drm/omapdrm/dss/sdi.c                |   2 +-
 drivers/gpu/drm/omapdrm/dss/venc.c               |   3 +-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  |  26 +-----
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c      |  18 ++--
 drivers/gpu/drm/sun4i/sun4i_rgb.c                |  11 +--
 drivers/gpu/drm/sun4i/sun4i_tcon.c               |  90 ++------------------
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c             |  12 +--
 drivers/gpu/drm/tilcdc/tilcdc_external.c         |  68 ++-------------
 drivers/gpu/drm/vc4/vc4_dpi.c                    |  15 +---
 include/drm/drm_of.h                             |  13 +++
 include/drm/drm_panel.h                          |   2 +-
 44 files changed, 238 insertions(+), 881 deletions(-)

--
2.10.1

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 1/5] drm: make of_drm_find_panel also depend on CONFIG_DRM_PANEL
  2017-03-22 13:26 [PATCH v3 0/5] DRM OF graph clean-up Rob Herring
@ 2017-03-22 13:26 ` Rob Herring
  2017-03-22 13:26 ` [PATCH v3 2/5] drm: of: introduce drm_of_find_panel_or_bridge Rob Herring
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2017-03-22 13:26 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, linux-kernel, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner, Alison Wang,
	Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Maxime Ripard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

For drm_of_find_panel_or_bridge() added in the next commit, an empty
version of of_drm_find_panel is needed for !CONFIG_DRM_PANEL.

Signed-off-by: Rob Herring <robh@kernel.org>
---
v3:
- rebase to v4.11-rc2

 include/drm/drm_panel.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 4b76cf2d5a7b..1b364b0100f4 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -192,7 +192,7 @@ void drm_panel_remove(struct drm_panel *panel);
 int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector);
 int drm_panel_detach(struct drm_panel *panel);

-#ifdef CONFIG_OF
+#if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL)
 struct drm_panel *of_drm_find_panel(const struct device_node *np);
 #else
 static inline struct drm_panel *of_drm_find_panel(const struct device_node *np)
--
2.10.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 2/5] drm: of: introduce drm_of_find_panel_or_bridge
  2017-03-22 13:26 [PATCH v3 0/5] DRM OF graph clean-up Rob Herring
  2017-03-22 13:26 ` [PATCH v3 1/5] drm: make of_drm_find_panel also depend on CONFIG_DRM_PANEL Rob Herring
@ 2017-03-22 13:26 ` Rob Herring
  2017-03-22 15:00   ` Philipp Zabel
  2017-03-22 13:26 ` [PATCH v3 3/5] drm: convert drivers to use of_graph_get_remote_node Rob Herring
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Rob Herring @ 2017-03-22 13:26 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, linux-kernel, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner, Alison Wang,
	Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Maxime Ripard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

Many drivers have a common pattern of searching the OF graph for either an
attached panel or bridge and then finding the DRM struct for the panel
or bridge. Also, most drivers need to handle deferred probing when the
DRM device is not yet instantiated. Create a common function,
drm_of_find_panel_or_bridge, to find the connected node and the
associated DRM panel or bridge device.

Signed-off-by: Rob Herring <robh@kernel.org>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
---
v3:
- rebase to v4.11-rc2
- fix comment that DT node is encoder ouput ports

 drivers/gpu/drm/drm_of.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_of.h     | 13 ++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index b5f2f0fece99..2120f33bdf4a 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -3,8 +3,10 @@
 #include <linux/list.h>
 #include <linux/of_graph.h>
 #include <drm/drmP.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
+#include <drm/drm_panel.h>
 #include <drm/drm_of.h>

 static void drm_release_of(struct device *dev, void *data)
@@ -208,3 +210,53 @@ int drm_of_encoder_active_endpoint(struct device_node *node,
 	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint);
+
+/*
+ * drm_of_find_panel_or_bridge - return connected panel or bridge device
+ * @np: device tree node containing encoder output ports
+ * @panel: pointer to hold returned drm_panel
+ * @bridge: pointer to hold returned drm_bridge
+ *
+ * Given a DT node's port and endpoint number, find the connected node and
+ * return either the associated struct drm_panel or drm_bridge device. Either
+ * @panel or @bridge must not be NULL.
+ *
+ * Returns zero if successful, or one of the standard error codes if it fails.
+ */
+int drm_of_find_panel_or_bridge(const struct device_node *np,
+				int port, int endpoint,
+				struct drm_panel **panel,
+				struct drm_bridge **bridge)
+{
+	int ret = -EPROBE_DEFER;
+	struct device_node *remote;
+
+	if (!panel && !bridge)
+		return -EINVAL;
+
+	remote = of_graph_get_remote_node(np, port, endpoint);
+	if (!remote)
+		return -ENODEV;
+
+	if (panel) {
+		*panel = of_drm_find_panel(remote);
+		if (*panel)
+			ret = 0;
+	}
+
+	/* No panel found yet, check for a bridge next. */
+	if (bridge) {
+		if (ret) {
+			*bridge = of_drm_find_bridge(remote);
+			if (*bridge)
+				ret = 0;
+		} else {
+			*bridge = NULL;
+		}
+
+	}
+
+	of_node_put(remote);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge);
diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h
index 26a64805cc15..f86507f0599b 100644
--- a/include/drm/drm_of.h
+++ b/include/drm/drm_of.h
@@ -8,6 +8,8 @@ struct component_match;
 struct device;
 struct drm_device;
 struct drm_encoder;
+struct drm_panel;
+struct drm_bridge;
 struct device_node;

 #ifdef CONFIG_OF
@@ -23,6 +25,10 @@ extern int drm_of_component_probe(struct device *dev,
 extern int drm_of_encoder_active_endpoint(struct device_node *node,
 					  struct drm_encoder *encoder,
 					  struct of_endpoint *endpoint);
+extern int drm_of_find_panel_or_bridge(const struct device_node *np,
+				       int port, int endpoint,
+				       struct drm_panel **panel,
+				       struct drm_bridge **bridge);
 #else
 static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
 						  struct device_node *port)
@@ -52,6 +58,13 @@ static inline int drm_of_encoder_active_endpoint(struct device_node *node,
 {
 	return -EINVAL;
 }
+static inline int drm_of_find_panel_or_bridge(const struct device_node *np,
+					      int port, int endpoint,
+					      struct drm_panel **panel,
+					      struct drm_bridge **bridge)
+{
+	return -EINVAL;
+}
 #endif

 static inline int drm_of_encoder_active_endpoint_id(struct device_node *node,
--
2.10.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 3/5] drm: convert drivers to use of_graph_get_remote_node
  2017-03-22 13:26 [PATCH v3 0/5] DRM OF graph clean-up Rob Herring
  2017-03-22 13:26 ` [PATCH v3 1/5] drm: make of_drm_find_panel also depend on CONFIG_DRM_PANEL Rob Herring
  2017-03-22 13:26 ` [PATCH v3 2/5] drm: of: introduce drm_of_find_panel_or_bridge Rob Herring
@ 2017-03-22 13:26 ` Rob Herring
  2017-03-22 13:26 ` [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge Rob Herring
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2017-03-22 13:26 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, linux-kernel, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner, Alison Wang,
	Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Maxime Ripard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

Convert drivers to use the new of_graph_get_remote_node() helper
instead of parsing the endpoint node and then getting the remote device
node. Now drivers can just specify the device node and which
port/endpoint and get back the connected remote device node. The details
of the graph binding are nicely abstracted into the core OF graph code.

This changes some error messages to debug messages (in the graph core).
Graph connections are often "no connects" depending on the particular
board, so we want to avoid spurious messages. Plus the kernel is not a
DT validator.

Signed-off-by: Rob Herring <robh@kernel.org>
Acked-by: Neil Armstrong <narmstrong@baylibre.com>
Tested-by: Liviu Dudau <liviu.dudau@arm.com>
Tested-by: Eric Anholt <eric@anholt.net>
Tested-by: Jyri Sarha <jsarha@ti.com>
Tested by: Archit Taneja <architt@codeaurora.org>
---
v3:
- rebase to v4.11-rc2

 drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++------
 drivers/gpu/drm/arm/malidp_drv.c                | 28 ++--------
 drivers/gpu/drm/bridge/adv7511/adv7533.c        | 12 +----
 drivers/gpu/drm/bridge/dumb-vga-dac.c           | 15 ++----
 drivers/gpu/drm/bridge/ti-tfp410.c              | 15 ++----
 drivers/gpu/drm/exynos/exynos_drm_dpi.c         | 16 +-----
 drivers/gpu/drm/exynos/exynos_drm_dsi.c         | 13 ++---
 drivers/gpu/drm/exynos/exynos_drm_mic.c         | 25 +--------
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 30 +----------
 drivers/gpu/drm/mediatek/mtk_dpi.c              | 12 ++---
 drivers/gpu/drm/mediatek/mtk_hdmi.c             | 26 ++--------
 drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
 drivers/gpu/drm/msm/dsi/dsi_host.c              |  2 +-
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c         | 28 +---------
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c     | 18 +++----
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c            | 12 +----
 drivers/gpu/drm/tilcdc/tilcdc_external.c        | 68 +++----------------------
 drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
 18 files changed, 54 insertions(+), 322 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 4ce4f970920b..924df354c0ab 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -423,29 +423,13 @@ static int compare_dev(struct device *dev, void *data)

 static int hdlcd_probe(struct platform_device *pdev)
 {
-	struct device_node *port, *ep;
+	struct device_node *port;
 	struct component_match *match = NULL;

-	if (!pdev->dev.of_node)
-		return -ENODEV;
-
 	/* there is only one output port inside each device, find it */
-	ep = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
-	if (!ep)
-		return -ENODEV;
-
-	if (!of_device_is_available(ep)) {
-		of_node_put(ep);
+	port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
+	if (!port)
 		return -ENODEV;
-	}
-
-	/* add the remote encoder port as component */
-	port = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
-	if (!port || !of_device_is_available(port)) {
-		of_node_put(port);
-		return -EAGAIN;
-	}

 	drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
 	of_node_put(port);
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 8b0672d4aee9..3470b8c80777 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -315,7 +315,6 @@ static int malidp_bind(struct device *dev)
 {
 	struct resource *res;
 	struct drm_device *drm;
-	struct device_node *ep;
 	struct malidp_drm *malidp;
 	struct malidp_hw_device *hwdev;
 	struct platform_device *pdev = to_platform_device(dev);
@@ -430,12 +429,7 @@ static int malidp_bind(struct device *dev)
 		goto init_fail;

 	/* Set the CRTC's port so that the encoder component can find it */
-	ep = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (!ep) {
-		ret = -EINVAL;
-		goto port_fail;
-	}
-	malidp->crtc.port = of_get_next_parent(ep);
+	malidp->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);

 	ret = component_bind_all(dev, drm);
 	if (ret) {
@@ -490,7 +484,6 @@ static int malidp_bind(struct device *dev)
 bind_fail:
 	of_node_put(malidp->crtc.port);
 	malidp->crtc.port = NULL;
-port_fail:
 	malidp_fini(drm);
 init_fail:
 	drm->dev_private = NULL;
@@ -548,29 +541,16 @@ static int malidp_compare_dev(struct device *dev, void *data)

 static int malidp_platform_probe(struct platform_device *pdev)
 {
-	struct device_node *port, *ep;
+	struct device_node *port;
 	struct component_match *match = NULL;

 	if (!pdev->dev.of_node)
 		return -ENODEV;

 	/* there is only one output port inside each device, find it */
-	ep = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
-	if (!ep)
-		return -ENODEV;
-
-	if (!of_device_is_available(ep)) {
-		of_node_put(ep);
+	port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
+	if (!port)
 		return -ENODEV;
-	}
-
-	/* add the remote encoder port as component */
-	port = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
-	if (!port || !of_device_is_available(port)) {
-		of_node_put(port);
-		return -EAGAIN;
-	}

 	drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev,
 				   port);
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c
index 8b210373cfa2..ac804f81e2f6 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c
@@ -232,7 +232,6 @@ void adv7533_detach_dsi(struct adv7511 *adv)
 int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
 {
 	u32 num_lanes;
-	struct device_node *endpoint;

 	of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);

@@ -241,17 +240,10 @@ int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)

 	adv->num_dsi_lanes = num_lanes;

-	endpoint = of_graph_get_next_endpoint(np, NULL);
-	if (!endpoint)
+	adv->host_node = of_graph_get_remote_node(np, 0, 0);
+	if (!adv->host_node)
 		return -ENODEV;

-	adv->host_node = of_graph_get_remote_port_parent(endpoint);
-	if (!adv->host_node) {
-		of_node_put(endpoint);
-		return -ENODEV;
-	}
-
-	of_node_put(endpoint);
 	of_node_put(adv->host_node);

 	adv->use_timing_gen = !of_property_read_bool(np,
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index 86e9f9c7b59c..347bc2bb61c8 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -154,21 +154,12 @@ static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {

 static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
 {
-	struct device_node *end_node, *phandle, *remote;
+	struct device_node *phandle, *remote;
 	struct i2c_adapter *ddc;

-	end_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
-	if (!end_node) {
-		dev_err(dev, "Missing connector endpoint\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	remote = of_graph_get_remote_port_parent(end_node);
-	of_node_put(end_node);
-	if (!remote) {
-		dev_err(dev, "Enable to parse remote node\n");
+	remote = of_graph_get_remote_node(dev->of_node, 1, -1);
+	if (!remote)
 		return ERR_PTR(-EINVAL);
-	}

 	phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0);
 	of_node_put(remote);
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index b054ea349952..82a6bdbf6ad0 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -127,18 +127,13 @@ static const struct drm_bridge_funcs tfp410_bridge_funcs = {

 static int tfp410_get_connector_ddc(struct tfp410 *dvi)
 {
-	struct device_node *ep = NULL, *connector_node = NULL;
-	struct device_node *ddc_phandle = NULL;
+	struct device_node *connector_node, *ddc_phandle;
 	int ret = 0;

 	/* port@1 is the connector node */
-	ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 1, -1);
-	if (!ep)
-		goto fail;
-
-	connector_node = of_graph_get_remote_port_parent(ep);
+	connector_node = of_graph_get_remote_node(dvi->dev->of_node, 1, -1);
 	if (!connector_node)
-		goto fail;
+		return -ENODEV;

 	ddc_phandle = of_parse_phandle(connector_node, "ddc-i2c-bus", 0);
 	if (!ddc_phandle)
@@ -150,10 +145,10 @@ static int tfp410_get_connector_ddc(struct tfp410 *dvi)
 	else
 		ret = -EPROBE_DEFER;

+	of_node_put(ddc_phandle);
+
 fail:
-	of_node_put(ep);
 	of_node_put(connector_node);
-	of_node_put(ddc_phandle);
 	return ret;
 }

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
index ad6b73c7fc59..eea529cea19a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -164,27 +164,13 @@ enum {
 	FIMD_PORT_WRB,
 };

-static struct device_node *exynos_dpi_of_find_panel_node(struct device *dev)
-{
-	struct device_node *np, *ep;
-
-	ep = of_graph_get_endpoint_by_regs(dev->of_node, FIMD_PORT_RGB, 0);
-	if (!ep)
-		return NULL;
-
-	np = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
-
-	return np;
-}
-
 static int exynos_dpi_parse_dt(struct exynos_dpi *ctx)
 {
 	struct device *dev = ctx->dev;
 	struct device_node *dn = dev->of_node;
 	struct device_node *np;

-	ctx->panel_node = exynos_dpi_of_find_panel_node(dev);
+	ctx->panel_node = of_graph_get_remote_node(dn, FIMD_PORT_RGB, 0);

 	np = of_get_child_by_name(dn, "display-timings");
 	if (np) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 812e2ec0761d..64daecba3d23 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1670,17 +1670,10 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)

 	of_node_put(ep);

-	ep = of_graph_get_next_endpoint(node, NULL);
-	if (!ep) {
-		ret = -EINVAL;
-		goto end;
-	}
+	dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_OUT, 0);
+	if (!dsi->bridge_node)
+		return -EINVAL;

-	dsi->bridge_node = of_graph_get_remote_port_parent(ep);
-	if (!dsi->bridge_node) {
-		ret = -EINVAL;
-		goto end;
-	}
 end:
 	of_node_put(ep);

diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index 2ef43d403eaa..e45720543a45 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -229,29 +229,6 @@ static void mic_set_reg_on(struct exynos_mic *mic, bool enable)
 	writel(reg, mic->reg + MIC_OP);
 }

-static struct device_node *get_remote_node(struct device_node *from, int reg)
-{
-	struct device_node *endpoint = NULL, *remote_node = NULL;
-
-	endpoint = of_graph_get_endpoint_by_regs(from, reg, -1);
-	if (!endpoint) {
-		DRM_ERROR("mic: Failed to find remote port from %s",
-				from->full_name);
-		goto exit;
-	}
-
-	remote_node = of_graph_get_remote_port_parent(endpoint);
-	if (!remote_node) {
-		DRM_ERROR("mic: Failed to find remote port parent from %s",
-							from->full_name);
-		goto exit;
-	}
-
-exit:
-	of_node_put(endpoint);
-	return remote_node;
-}
-
 static int parse_dt(struct exynos_mic *mic)
 {
 	int ret = 0, i, j;
@@ -263,7 +240,7 @@ static int parse_dt(struct exynos_mic *mic)
 	 * The first node must be for decon and the second one must be for dsi.
 	 */
 	for (i = 0, j = 0; i < NUM_ENDPOINTS; i++) {
-		remote_node = get_remote_node(mic->dev->of_node, i);
+		remote_node = of_graph_get_remote_node(mic->dev->of_node, i, 0);
 		if (!remote_node) {
 			ret = -EPIPE;
 			goto exit;
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 7ec93aec7e88..07f2aae2f1e2 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -240,34 +240,6 @@ static const struct component_master_ops kirin_drm_ops = {
 	.unbind = kirin_drm_unbind,
 };

-static struct device_node *kirin_get_remote_node(struct device_node *np)
-{
-	struct device_node *endpoint, *remote;
-
-	/* get the first endpoint, in our case only one remote node
-	 * is connected to display controller.
-	 */
-	endpoint = of_graph_get_next_endpoint(np, NULL);
-	if (!endpoint) {
-		DRM_ERROR("no valid endpoint node\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	remote = of_graph_get_remote_port_parent(endpoint);
-	of_node_put(endpoint);
-	if (!remote) {
-		DRM_ERROR("no valid remote node\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	if (!of_device_is_available(remote)) {
-		DRM_ERROR("not available for remote node\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	return remote;
-}
-
 static int kirin_drm_platform_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -281,7 +253,7 @@ static int kirin_drm_platform_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}

-	remote = kirin_get_remote_node(np);
+	remote = of_graph_get_remote_node(np, 0, 0);
 	if (IS_ERR(remote))
 		return PTR_ERR(remote);

diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 3bd3bd688d1a..32ca351ecd09 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -661,7 +661,7 @@ static int mtk_dpi_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct mtk_dpi *dpi;
 	struct resource *mem;
-	struct device_node *ep, *bridge_node = NULL;
+	struct device_node *bridge_node;
 	int comp_id;
 	int ret;

@@ -706,15 +706,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}

-	ep = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (ep) {
-		bridge_node = of_graph_get_remote_port_parent(ep);
-		of_node_put(ep);
-	}
-	if (!bridge_node) {
-		dev_err(dev, "Failed to find bridge node\n");
+	bridge_node = of_graph_get_remote_node(dev->of_node, 0, 0);
+	if (!bridge_node)
 		return -ENODEV;
-	}

 	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);

diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index c26251260b83..41a1c03b0347 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1434,7 +1434,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
-	struct device_node *cec_np, *port, *ep, *remote, *i2c_np;
+	struct device_node *cec_np, *remote, *i2c_np;
 	struct platform_device *cec_pdev;
 	struct regmap *regmap;
 	struct resource *mem;
@@ -1486,29 +1486,9 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
 	if (IS_ERR(hdmi->regs))
 		return PTR_ERR(hdmi->regs);

-	port = of_graph_get_port_by_id(np, 1);
-	if (!port) {
-		dev_err(dev, "Missing output port node\n");
+	remote = of_graph_get_remote_node(np, 1, 0);
+	if (!remote)
 		return -EINVAL;
-	}
-
-	ep = of_get_child_by_name(port, "endpoint");
-	if (!ep) {
-		dev_err(dev, "Missing endpoint node in port %s\n",
-			port->full_name);
-		of_node_put(port);
-		return -EINVAL;
-	}
-	of_node_put(port);
-
-	remote = of_graph_get_remote_port_parent(ep);
-	if (!remote) {
-		dev_err(dev, "Missing connector/bridge node for endpoint %s\n",
-			ep->full_name);
-		of_node_put(ep);
-		return -EINVAL;
-	}
-	of_node_put(ep);

 	if (!of_device_is_compatible(remote, "hdmi-connector")) {
 		hdmi->next_bridge = of_drm_find_bridge(remote);
diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
index a2bcc70a03ef..8566de2edb62 100644
--- a/drivers/gpu/drm/meson/meson_venc_cvbs.c
+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
@@ -217,25 +217,14 @@ static const struct drm_encoder_helper_funcs

 static bool meson_venc_cvbs_connector_is_available(struct meson_drm *priv)
 {
-	struct device_node *ep, *remote;
+	struct device_node *remote;

-	/* CVBS VDAC output is on the first port, first endpoint */
-	ep = of_graph_get_endpoint_by_regs(priv->dev->of_node, 0, 0);
-	if (!ep)
+	remote = of_graph_get_remote_node(priv->dev->of_node, 0, 0);
+	if (!remote)
 		return false;

-
-	/* If the endpoint node exists, consider it enabled */
-	remote = of_graph_get_remote_port(ep);
-	if (remote) {
-		of_node_put(ep);
-		return true;
-	}
-
-	of_node_put(ep);
 	of_node_put(remote);
-
-	return false;
+	return true;
 }

 int meson_venc_cvbs_create(struct meson_drm *priv)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 1fc07ce24686..cc0697adf6c5 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1635,7 +1635,7 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 	}

 	/* Get panel node from the output port's endpoint data */
-	device_node = of_graph_get_remote_port_parent(endpoint);
+	device_node = of_graph_get_remote_node(np, 1, 0);
 	if (!device_node) {
 		dev_dbg(dev, "%s: no valid device\n", __func__);
 		goto err;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index 94ea963519b2..5ea7183e66fb 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -225,32 +225,6 @@ int mdp4_enable(struct mdp4_kms *mdp4_kms)
 	return 0;
 }

-static struct device_node *mdp4_detect_lcdc_panel(struct drm_device *dev)
-{
-	struct device_node *endpoint, *panel_node;
-	struct device_node *np = dev->dev->of_node;
-
-	/*
-	 * LVDS/LCDC is the first port described in the list of ports in the
-	 * MDP4 DT node.
-	 */
-	endpoint = of_graph_get_endpoint_by_regs(np, 0, -1);
-	if (!endpoint) {
-		DBG("no LVDS remote endpoint\n");
-		return NULL;
-	}
-
-	panel_node = of_graph_get_remote_port_parent(endpoint);
-	if (!panel_node) {
-		DBG("no valid panel node in LVDS endpoint\n");
-		of_node_put(endpoint);
-		return NULL;
-	}
-
-	of_node_put(endpoint);
-
-	return panel_node;
-}

 static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms,
 				  int intf_type)
@@ -269,7 +243,7 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms,
 		 * bail out early if there is no panel node (no need to
 		 * initialize LCDC encoder and LVDS connector)
 		 */
-		panel_node = mdp4_detect_lcdc_panel(dev);
+		panel_node = of_graph_get_remote_node(dev->dev->of_node, 0, 0);
 		if (!panel_node)
 			return 0;

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index b360e6251836..c481bdd296d2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -367,19 +367,13 @@ static void rockchip_add_endpoints(struct device *dev,
 				   struct component_match **match,
 				   struct device_node *port)
 {
-	struct device_node *ep, *remote;
+	struct device_node *remote;
+	int i;

-	for_each_child_of_node(port, ep) {
-		remote = of_graph_get_remote_port_parent(ep);
-		if (!remote || !of_device_is_available(remote)) {
-			of_node_put(remote);
-			continue;
-		} else if (!of_device_is_available(remote->parent)) {
-			dev_warn(dev, "parent device of %s is not available\n",
-				 remote->full_name);
-			of_node_put(remote);
+	for (i = 0; i < 3; i++) {
+		remote = of_graph_get_remote_node(port, 0, i);
+		if (!remote)
 			continue;
-		}

 		drm_of_component_match_add(dev, match, compare_of, remote);
 		of_node_put(remote);
@@ -458,7 +452,7 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
 			continue;
 		}

-		rockchip_add_endpoints(dev, &match, port);
+		rockchip_add_endpoints(dev, &match, port->parent);
 		of_node_put(port);
 	}

diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index f80bf9385e41..a5cab1c028b9 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -23,6 +23,7 @@
 #include <linux/workqueue.h>
 #include <linux/completion.h>
 #include <linux/dma-mapping.h>
+#include <linux/of_graph.h>

 #include "tilcdc_drv.h"
 #include "tilcdc_regs.h"
@@ -1013,16 +1014,7 @@ int tilcdc_crtc_create(struct drm_device *dev)
 	drm_crtc_helper_add(crtc, &tilcdc_crtc_helper_funcs);

 	if (priv->is_componentized) {
-		struct device_node *ports =
-			of_get_child_by_name(dev->dev->of_node, "ports");
-
-		if (ports) {
-			crtc->port = of_get_child_by_name(ports, "port");
-			of_node_put(ports);
-		} else {
-			crtc->port =
-				of_get_child_by_name(dev->dev->of_node, "port");
-		}
+		crtc->port = of_graph_get_port_by_id(dev->dev->of_node, 0);
 		if (!crtc->port) { /* This should never happen */
 			dev_err(dev->dev, "Port node not found in %s\n",
 				dev->dev->of_node->full_name);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
index b0dd5e8634ae..711c7b3289d3 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -185,39 +185,6 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
 	return ret;
 }

-static int tilcdc_node_has_port(struct device_node *dev_node)
-{
-	struct device_node *node;
-
-	node = of_get_child_by_name(dev_node, "ports");
-	if (!node)
-		node = of_get_child_by_name(dev_node, "port");
-	if (!node)
-		return 0;
-	of_node_put(node);
-
-	return 1;
-}
-
-static
-struct device_node *tilcdc_get_remote_node(struct device_node *node)
-{
-	struct device_node *ep;
-	struct device_node *parent;
-
-	if (!tilcdc_node_has_port(node))
-		return NULL;
-
-	ep = of_graph_get_next_endpoint(node, NULL);
-	if (!ep)
-		return NULL;
-
-	parent = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
-
-	return parent;
-}
-
 int tilcdc_attach_external_device(struct drm_device *ddev)
 {
 	struct tilcdc_drm_private *priv = ddev->dev_private;
@@ -225,7 +192,7 @@ int tilcdc_attach_external_device(struct drm_device *ddev)
 	struct drm_bridge *bridge;
 	int ret;

-	remote_node = tilcdc_get_remote_node(ddev->dev->of_node);
+	remote_node = of_graph_get_remote_node(ddev->dev->of_node, 0, 0);
 	if (!remote_node)
 		return 0;

@@ -264,35 +231,16 @@ int tilcdc_get_external_components(struct device *dev,
 				   struct component_match **match)
 {
 	struct device_node *node;
-	struct device_node *ep = NULL;
-	int count = 0;
-	int ret = 0;
-
-	if (!tilcdc_node_has_port(dev->of_node))
-		return 0;

-	while ((ep = of_graph_get_next_endpoint(dev->of_node, ep))) {
-		node = of_graph_get_remote_port_parent(ep);
-		if (!node || !of_device_is_available(node)) {
-			of_node_put(node);
-			continue;
-		}
-
-		dev_dbg(dev, "Subdevice node '%s' found\n", node->name);
-
-		if (of_device_is_compatible(node, "nxp,tda998x")) {
-			if (match)
-				drm_of_component_match_add(dev, match,
-							   dev_match_of, node);
-			ret = 1;
-		}
+	node = of_graph_get_remote_node(dev->of_node, 0, 0);

+	if (!of_device_is_compatible(node, "nxp,tda998x")) {
 		of_node_put(node);
-		if (count++ > 1) {
-			dev_err(dev, "Only one port is supported\n");
-			return -EINVAL;
-		}
+		return 0;
 	}

-	return ret;
+	if (match)
+		drm_of_component_match_add(dev, match, dev_match_of, node);
+	of_node_put(node);
+	return 1;
 }
diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
index 1e1f6b8184d0..ac9655451b25 100644
--- a/drivers/gpu/drm/vc4/vc4_dpi.c
+++ b/drivers/gpu/drm/vc4/vc4_dpi.c
@@ -366,23 +366,14 @@ static const struct of_device_id vc4_dpi_dt_match[] = {
  */
 static struct drm_panel *vc4_dpi_get_panel(struct device *dev)
 {
-	struct device_node *endpoint, *panel_node;
+	struct device_node *panel_node;
 	struct device_node *np = dev->of_node;
 	struct drm_panel *panel;

-	endpoint = of_graph_get_next_endpoint(np, NULL);
-	if (!endpoint) {
-		dev_err(dev, "no endpoint to fetch DPI panel\n");
-		return NULL;
-	}
-
 	/* don't proceed if we have an endpoint but no panel_node tied to it */
-	panel_node = of_graph_get_remote_port_parent(endpoint);
-	of_node_put(endpoint);
-	if (!panel_node) {
-		dev_err(dev, "no valid panel node\n");
+	panel_node = of_graph_get_remote_node(np, 0, 0);
+	if (!panel_node)
 		return NULL;
-	}

 	panel = of_drm_find_panel(panel_node);
 	of_node_put(panel_node);
--
2.10.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-03-22 13:26 [PATCH v3 0/5] DRM OF graph clean-up Rob Herring
                   ` (2 preceding siblings ...)
  2017-03-22 13:26 ` [PATCH v3 3/5] drm: convert drivers to use of_graph_get_remote_node Rob Herring
@ 2017-03-22 13:26 ` Rob Herring
  2017-03-22 15:01   ` Philipp Zabel
                     ` (3 more replies)
  2017-03-22 13:26 ` [PATCH v3 5/5] drm: omap: use common OF graph helpers Rob Herring
  2017-04-06 21:03 ` [PATCH v3 0/5] DRM OF graph clean-up Sean Paul
  5 siblings, 4 replies; 14+ messages in thread
From: Rob Herring @ 2017-03-22 13:26 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, linux-kernel, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner, Alison Wang,
	Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Maxime Ripard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

Similar to the previous commit, convert drivers open coding OF graph
parsing to use drm_of_find_panel_or_bridge instead.

This changes some error messages to debug messages (in the graph core).
Graph connections are often "no connects" depending on the particular
board, so we want to avoid spurious messages. Plus the kernel is not a
DT validator.

Signed-off-by: Rob Herring <robh@kernel.org>
Reviewed-by: Archit Taneja <architt@codeaurora.org>
---
v3:
- rebase to v4.11-rc2
- rework atmel to support 1 to N connections

 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 73 ++++++-------------
 drivers/gpu/drm/bridge/nxp-ptn3460.c             | 16 ++---
 drivers/gpu/drm/bridge/parade-ps8622.c           | 16 ++---
 drivers/gpu/drm/bridge/tc358767.c                | 27 +------
 drivers/gpu/drm/exynos/exynos_dp.c               | 35 ++++-----
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c        | 39 +++-------
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     | 27 ++-----
 drivers/gpu/drm/imx/imx-ldb.c                    | 27 ++-----
 drivers/gpu/drm/imx/parallel-display.c           | 36 ++--------
 drivers/gpu/drm/mediatek/mtk_dsi.c               | 23 ++----
 drivers/gpu/drm/mxsfb/mxsfb_out.c                | 40 ++---------
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  | 26 ++-----
 drivers/gpu/drm/sun4i/sun4i_rgb.c                | 11 +--
 drivers/gpu/drm/sun4i/sun4i_tcon.c               | 90 ++----------------------
 14 files changed, 92 insertions(+), 394 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index e7799b6ee829..f987b4572d4a 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -22,7 +22,7 @@
 #include <linux/of_graph.h>

 #include <drm/drmP.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_of.h>

 #include "atmel_hlcdc_dc.h"

@@ -152,29 +152,11 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };

-static int atmel_hlcdc_check_endpoint(struct drm_device *dev,
-				      const struct of_endpoint *ep)
-{
-	struct device_node *np;
-	void *obj;
-
-	np = of_graph_get_remote_port_parent(ep->local_node);
-
-	obj = of_drm_find_panel(np);
-	if (!obj)
-		obj = of_drm_find_bridge(np);
-
-	of_node_put(np);
-
-	return obj ? 0 : -EPROBE_DEFER;
-}
-
 static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
-				       const struct of_endpoint *ep)
+				       const struct device_node *np)
 {
 	struct atmel_hlcdc_dc *dc = dev->dev_private;
 	struct atmel_hlcdc_rgb_output *output;
-	struct device_node *np;
 	struct drm_panel *panel;
 	struct drm_bridge *bridge;
 	int ret;
@@ -195,13 +177,11 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,

 	output->encoder.possible_crtcs = 0x1;

-	np = of_graph_get_remote_port_parent(ep->local_node);
-
-	ret = -EPROBE_DEFER;
+	ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge);
+	if (ret)
+		return ret;

-	panel = of_drm_find_panel(np);
 	if (panel) {
-		of_node_put(np);
 		output->connector.dpms = DRM_MODE_DPMS_OFF;
 		output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
 		drm_connector_helper_add(&output->connector,
@@ -226,9 +206,6 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
 		return 0;
 	}

-	bridge = of_drm_find_bridge(np);
-	of_node_put(np);
-
 	if (bridge) {
 		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
 		if (!ret)
@@ -243,31 +220,23 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,

 int atmel_hlcdc_create_outputs(struct drm_device *dev)
 {
-	struct device_node *ep_np = NULL;
-	struct of_endpoint ep;
-	int ret;
-
-	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
-		ret = of_graph_parse_endpoint(ep_np, &ep);
-		if (!ret)
-			ret = atmel_hlcdc_check_endpoint(dev, &ep);
-
-		if (ret) {
-			of_node_put(ep_np);
-			return ret;
-		}
-	}
-
-	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
-		ret = of_graph_parse_endpoint(ep_np, &ep);
-		if (!ret)
-			ret = atmel_hlcdc_attach_endpoint(dev, &ep);
-
-		if (ret) {
-			of_node_put(ep_np);
+	struct device_node *remote;
+	int ret, endpoint = 0;
+
+	while (true) {
+		/* Loop thru possible multiple connections to the output */
+		remote = of_graph_get_remote_node(dev->dev->of_node, 0,
+						  endpoint++);
+		if (!remote)
+			break;
+
+		ret = atmel_hlcdc_attach_endpoint(dev, remote);
+		of_node_put(remote);
+		if (ret)
 			return ret;
-		}
 	}

-	return 0;
+	if (!endpoint)
+		return -ENODEV;
+	return ret;
 }
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index 27f98c518dde..351704390d02 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -20,8 +20,8 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
-#include <linux/of_graph.h>

+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>

 #include "drm_crtc.h"
@@ -292,7 +292,6 @@ static int ptn3460_probe(struct i2c_client *client,
 {
 	struct device *dev = &client->dev;
 	struct ptn3460_bridge *ptn_bridge;
-	struct device_node *endpoint, *panel_node;
 	int ret;

 	ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
@@ -300,16 +299,9 @@ static int ptn3460_probe(struct i2c_client *client,
 		return -ENOMEM;
 	}

-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		panel_node = of_graph_get_remote_port_parent(endpoint);
-		if (panel_node) {
-			ptn_bridge->panel = of_drm_find_panel(panel_node);
-			of_node_put(panel_node);
-			if (!ptn_bridge->panel)
-				return -EPROBE_DEFER;
-		}
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ptn_bridge->panel, NULL);
+	if (ret)
+		return ret;

 	ptn_bridge->client = client;

diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index ac8cc5b50d9f..1dcec3b97e67 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -22,10 +22,10 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_graph.h>
 #include <linux/pm.h>
 #include <linux/regulator/consumer.h>

+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>

 #include "drmP.h"
@@ -536,7 +536,6 @@ static int ps8622_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
-	struct device_node *endpoint, *panel_node;
 	struct ps8622_bridge *ps8622;
 	int ret;

@@ -544,16 +543,9 @@ static int ps8622_probe(struct i2c_client *client,
 	if (!ps8622)
 		return -ENOMEM;

-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		panel_node = of_graph_get_remote_port_parent(endpoint);
-		if (panel_node) {
-			ps8622->panel = of_drm_find_panel(panel_node);
-			of_node_put(panel_node);
-			if (!ps8622->panel)
-				return -EPROBE_DEFER;
-		}
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ps8622->panel, NULL);
+	if (ret)
+		return ret;

 	ps8622->client = client;

diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index de9ffb49e9f6..5c26488e7a2d 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1244,7 +1244,6 @@ static const struct regmap_config tc_regmap_config = {
 static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
-	struct device_node *ep;
 	struct tc_data *tc;
 	int ret;

@@ -1255,29 +1254,9 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	tc->dev = dev;

 	/* port@2 is the output port */
-	ep = of_graph_get_endpoint_by_regs(dev->of_node, 2, -1);
-	if (ep) {
-		struct device_node *remote;
-
-		remote = of_graph_get_remote_port_parent(ep);
-		if (!remote) {
-			dev_warn(dev, "endpoint %s not connected\n",
-				 ep->full_name);
-			of_node_put(ep);
-			return -ENODEV;
-		}
-		of_node_put(ep);
-		tc->panel = of_drm_find_panel(remote);
-		if (tc->panel) {
-			dev_dbg(dev, "found panel %s\n", remote->full_name);
-		} else {
-			dev_dbg(dev, "waiting for panel %s\n",
-				remote->full_name);
-			of_node_put(remote);
-			return -EPROBE_DEFER;
-		}
-		of_node_put(remote);
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &tc->panel, NULL);
+	if (ret)
+		return ret;

 	/* Shut down GPIO is optional */
 	tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 1ef0be338b85..a269f439e742 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -23,6 +23,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>

 #include <drm/bridge/analogix_dp.h>
@@ -212,8 +213,11 @@ static const struct component_ops exynos_dp_ops = {
 static int exynos_dp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *np = NULL, *endpoint = NULL;
+	struct device_node *np;
 	struct exynos_dp_device *dp;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
+	int ret;

 	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
 			  GFP_KERNEL);
@@ -237,28 +241,13 @@ static int exynos_dp_probe(struct platform_device *pdev)
 		goto out;
 	}

-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		np = of_graph_get_remote_port_parent(endpoint);
-		if (np) {
-			/* The remote port can be either a panel or a bridge */
-			dp->plat_data.panel = of_drm_find_panel(np);
-			if (!dp->plat_data.panel) {
-				dp->ptn_bridge = of_drm_find_bridge(np);
-				if (!dp->ptn_bridge) {
-					of_node_put(np);
-					return -EPROBE_DEFER;
-				}
-			}
-			of_node_put(np);
-		} else {
-			DRM_ERROR("no remote endpoint device node found.\n");
-			return -EINVAL;
-		}
-	} else {
-		DRM_ERROR("no port endpoint subnode found.\n");
-		return -EINVAL;
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, &bridge);
+	if (ret)
+		return ret;
+
+	/* The remote port can be either a panel or a bridge */
+	dp->plat_data.panel = panel;
+	dp->ptn_bridge = bridge;

 out:
 	return component_add(&pdev->dev, &exynos_dp_ops);
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index c3651456c963..511d68e22452 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -15,6 +15,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>

 #include "fsl_dcu_drm_drv.h"
@@ -141,28 +142,6 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
 	return ret;
 }

-static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
-				   const struct of_endpoint *ep)
-{
-	struct drm_bridge *bridge;
-	struct device_node *np;
-
-	np = of_graph_get_remote_port_parent(ep->local_node);
-
-	fsl_dev->connector.panel = of_drm_find_panel(np);
-	if (fsl_dev->connector.panel) {
-		of_node_put(np);
-		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
-	}
-
-	bridge = of_drm_find_bridge(np);
-	of_node_put(np);
-	if (!bridge)
-		return -ENODEV;
-
-	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
-}
-
 int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
 {
 	struct of_endpoint ep;
@@ -179,14 +158,14 @@ int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
 		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
 	}

-	ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL);
-	if (!ep_node)
-		return -ENODEV;
-
-	ret = of_graph_parse_endpoint(ep_node, &ep);
-	of_node_put(ep_node);
+	ret = drm_of_find_panel_or_bridge(fsl_dev->np, 0, 0, &panel, &bridge);
 	if (ret)
-		return -ENODEV;
+		return ret;

-	return fsl_dcu_attach_endpoint(fsl_dev, &ep);
+	if (panel) {
+		fsl_dev->connector.panel = panel;
+		return fsl_dcu_attach_panel(fsl_dev, panel);
+	}
+
+	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
 }
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 1737e98bc10a..5abc69c9630f 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -17,7 +17,6 @@

 #include <linux/clk.h>
 #include <linux/component.h>
-#include <linux/of_graph.h>

 #include <drm/drm_of.h>
 #include <drm/drm_crtc_helper.h>
@@ -754,34 +753,16 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
 {
 	struct dsi_hw_ctx *ctx = dsi->ctx;
 	struct device_node *np = pdev->dev.of_node;
-	struct device_node *endpoint, *bridge_node;
-	struct drm_bridge *bridge;
 	struct resource *res;
+	int ret;

 	/*
 	 * Get the endpoint node. In our case, dsi has one output port1
 	 * to which the external HDMI bridge is connected.
 	 */
-	endpoint = of_graph_get_endpoint_by_regs(np, 1, -1);
-	if (!endpoint) {
-		DRM_ERROR("no valid endpoint node\n");
-		return -ENODEV;
-	}
-	of_node_put(endpoint);
-
-	bridge_node = of_graph_get_remote_port_parent(endpoint);
-	if (!bridge_node) {
-		DRM_ERROR("no valid bridge node\n");
-		return -ENODEV;
-	}
-	of_node_put(bridge_node);
-
-	bridge = of_drm_find_bridge(bridge_node);
-	if (!bridge) {
-		DRM_INFO("wait for external HDMI bridge driver.\n");
-		return -EPROBE_DEFER;
-	}
-	dsi->bridge = bridge;
+	ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
+	if (ret)
+		return ret;

 	ctx->pclk = devm_clk_get(&pdev->dev, "pclk");
 	if (IS_ERR(ctx->pclk)) {
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 88cd11d30134..8fb801fab039 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -647,7 +647,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)

 	for_each_child_of_node(np, child) {
 		struct imx_ldb_channel *channel;
-		struct device_node *ep;
 		int bus_format;

 		ret = of_property_read_u32(child, "reg", &i);
@@ -671,27 +670,11 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 		 * The output port is port@4 with an external 4-port mux or
 		 * port@2 with the internal 2-port mux.
 		 */
-		ep = of_graph_get_endpoint_by_regs(child,
-						   imx_ldb->lvds_mux ? 4 : 2,
-						   -1);
-		if (ep) {
-			struct device_node *remote;
-
-			remote = of_graph_get_remote_port_parent(ep);
-			of_node_put(ep);
-			if (remote) {
-				channel->panel = of_drm_find_panel(remote);
-				channel->bridge = of_drm_find_bridge(remote);
-			} else
-				return -EPROBE_DEFER;
-			of_node_put(remote);
-
-			if (!channel->panel && !channel->bridge) {
-				dev_err(dev, "panel/bridge not found: %s\n",
-					remote->full_name);
-				return -EPROBE_DEFER;
-			}
-		}
+		ret = drm_of_find_panel_or_bridge(child,
+						  imx_ldb->lvds_mux ? 4 : 2, 0,
+						  &channel->panel, &channel->bridge);
+		if (ret)
+			return ret;

 		/* panel ddc only if there is no bridge */
 		if (!channel->bridge) {
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index d5c06fd89f90..636031a30e17 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -19,10 +19,10 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <linux/videodev2.h>
 #include <video/of_display_timing.h>
-#include <linux/of_graph.h>

 #include "imx-drm.h"

@@ -208,7 +208,6 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 {
 	struct drm_device *drm = data;
 	struct device_node *np = dev->of_node;
-	struct device_node *ep;
 	const u8 *edidp;
 	struct imx_parallel_display *imxpd;
 	int ret;
@@ -237,36 +236,9 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 	imxpd->bus_format = bus_format;

 	/* port@1 is the output port */
-	ep = of_graph_get_endpoint_by_regs(np, 1, -1);
-	if (ep) {
-		struct device_node *remote;
-
-		remote = of_graph_get_remote_port_parent(ep);
-		if (!remote) {
-			dev_warn(dev, "endpoint %s not connected\n",
-				 ep->full_name);
-			of_node_put(ep);
-			return -ENODEV;
-		}
-		of_node_put(ep);
-
-		imxpd->panel = of_drm_find_panel(remote);
-		if (imxpd->panel) {
-			dev_dbg(dev, "found panel %s\n", remote->full_name);
-		} else {
-			imxpd->bridge = of_drm_find_bridge(remote);
-			if (imxpd->bridge)
-				dev_dbg(dev, "found bridge %s\n",
-					remote->full_name);
-		}
-		if (!imxpd->panel && !imxpd->bridge) {
-			dev_dbg(dev, "waiting for panel or bridge %s\n",
-				remote->full_name);
-			of_node_put(remote);
-			return -EPROBE_DEFER;
-		}
-		of_node_put(remote);
-	}
+	ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel, &imxpd->bridge);
+	if (ret)
+		return ret;

 	imxpd->dev = dev;

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index dd71cbb1a622..4d837b29ee9e 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -16,11 +16,11 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_of.h>
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#include <linux/of_graph.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <video/videomode.h>
@@ -801,7 +801,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 {
 	struct mtk_dsi *dsi;
 	struct device *dev = &pdev->dev;
-	struct device_node *remote_node, *endpoint;
 	struct resource *regs;
 	int comp_id;
 	int ret;
@@ -813,22 +812,10 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 	dsi->host.ops = &mtk_dsi_ops;
 	dsi->host.dev = dev;

-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		remote_node = of_graph_get_remote_port_parent(endpoint);
-		if (!remote_node) {
-			dev_err(dev, "No panel connected\n");
-			return -ENODEV;
-		}
-
-		dsi->bridge = of_drm_find_bridge(remote_node);
-		dsi->panel = of_drm_find_panel(remote_node);
-		of_node_put(remote_node);
-		if (!dsi->bridge && !dsi->panel) {
-			dev_info(dev, "Waiting for bridge or panel driver\n");
-			return -EPROBE_DEFER;
-		}
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
+					  &dsi->panel, &dsi->bridge);
+	if (ret)
+		return ret;

 	dsi->engine_clk = devm_clk_get(dev, "engine");
 	if (IS_ERR(dsi->engine_clk)) {
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
index b8e81422d4e2..f7d729aa09bd 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_out.c
@@ -19,6 +19,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_simple_kms_helper.h>
@@ -82,20 +83,15 @@ static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
 };

-static int mxsfb_attach_endpoint(struct drm_device *drm,
-				 const struct of_endpoint *ep)
+int mxsfb_create_output(struct drm_device *drm)
 {
 	struct mxsfb_drm_private *mxsfb = drm->dev_private;
-	struct device_node *np;
 	struct drm_panel *panel;
-	int ret = -EPROBE_DEFER;
-
-	np = of_graph_get_remote_port_parent(ep->local_node);
-	panel = of_drm_find_panel(np);
-	of_node_put(np);
+	int ret;

-	if (!panel)
-		return -EPROBE_DEFER;
+	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, NULL);
+	if (ret)
+		return ret;

 	mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
 	mxsfb->connector.polled = 0;
@@ -109,27 +105,3 @@ static int mxsfb_attach_endpoint(struct drm_device *drm,

 	return ret;
 }
-
-int mxsfb_create_output(struct drm_device *drm)
-{
-	struct mxsfb_drm_private *mxsfb = drm->dev_private;
-	struct device_node *ep_np = NULL;
-	struct of_endpoint ep;
-	int ret;
-
-	for_each_endpoint_of_node(drm->dev->of_node, ep_np) {
-		ret = of_graph_parse_endpoint(ep_np, &ep);
-		if (!ret)
-			ret = mxsfb_attach_endpoint(drm, &ep);
-
-		if (ret) {
-			of_node_put(ep_np);
-			return ret;
-		}
-	}
-
-	if (!mxsfb->panel)
-		return -EPROBE_DEFER;
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 8548e8271639..615afad280a8 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -428,31 +428,13 @@ static const struct component_ops rockchip_dp_component_ops = {
 static int rockchip_dp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *panel_node, *port, *endpoint;
 	struct drm_panel *panel = NULL;
 	struct rockchip_dp_device *dp;
+	int ret;

-	port = of_graph_get_port_by_id(dev->of_node, 1);
-	if (port) {
-		endpoint = of_get_child_by_name(port, "endpoint");
-		of_node_put(port);
-		if (!endpoint) {
-			dev_err(dev, "no output endpoint found\n");
-			return -EINVAL;
-		}
-
-		panel_node = of_graph_get_remote_port_parent(endpoint);
-		of_node_put(endpoint);
-		if (!panel_node) {
-			dev_err(dev, "no output node found\n");
-			return -EINVAL;
-		}
-
-		panel = of_drm_find_panel(panel_node);
-		of_node_put(panel_node);
-		if (!panel)
-			return -EPROBE_DEFER;
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
+	if (ret)
+		return ret;

 	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
 	if (!dp)
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 757208f51731..46280dd70c9e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -15,6 +15,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>

 #include "sun4i_drv.h"
@@ -218,9 +219,9 @@ int sun4i_rgb_init(struct drm_device *drm)
 	rgb->drv = drv;
 	encoder = &rgb->encoder;

-	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
-	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
-	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
+	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
+					  &tcon->panel, &bridge);
+	if (ret) {
 		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
 		return 0;
 	}
@@ -240,7 +241,7 @@ int sun4i_rgb_init(struct drm_device *drm)
 	/* The RGB encoder can only work with the TCON channel 0 */
 	rgb->encoder.possible_crtcs = BIT(0);

-	if (!IS_ERR(tcon->panel)) {
+	if (tcon->panel) {
 		drm_connector_helper_add(&rgb->connector,
 					 &sun4i_rgb_con_helper_funcs);
 		ret = drm_connector_init(drm, &rgb->connector,
@@ -261,7 +262,7 @@ int sun4i_rgb_init(struct drm_device *drm)
 		}
 	}

-	if (!IS_ERR(bridge)) {
+	if (bridge) {
 		ret = drm_bridge_attach(encoder, bridge, NULL);
 		if (ret) {
 			dev_err(drm->dev, "Couldn't attach our bridge\n");
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index ea2906f87cb9..2e4e365cecf9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -15,13 +15,12 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_modes.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_of.h>

 #include <linux/component.h>
 #include <linux/ioport.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
-#include <linux/of_graph.h>
 #include <linux/of_irq.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
@@ -405,74 +404,6 @@ static int sun4i_tcon_init_regmap(struct device *dev,
 	return 0;
 }

-struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
-{
-	struct device_node *port, *remote, *child;
-	struct device_node *end_node = NULL;
-
-	/* Inputs are listed first, then outputs */
-	port = of_graph_get_port_by_id(node, 1);
-
-	/*
-	 * Our first output is the RGB interface where the panel will
-	 * be connected.
-	 */
-	for_each_child_of_node(port, child) {
-		u32 reg;
-
-		of_property_read_u32(child, "reg", &reg);
-		if (reg == 0)
-			end_node = child;
-	}
-
-	if (!end_node) {
-		DRM_DEBUG_DRIVER("Missing panel endpoint\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	remote = of_graph_get_remote_port_parent(end_node);
-	if (!remote) {
-		DRM_DEBUG_DRIVER("Unable to parse remote node\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
-}
-
-struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node)
-{
-	struct device_node *port, *remote, *child;
-	struct device_node *end_node = NULL;
-
-	/* Inputs are listed first, then outputs */
-	port = of_graph_get_port_by_id(node, 1);
-
-	/*
-	 * Our first output is the RGB interface where the panel will
-	 * be connected.
-	 */
-	for_each_child_of_node(port, child) {
-		u32 reg;
-
-		of_property_read_u32(child, "reg", &reg);
-		if (reg == 0)
-			end_node = child;
-	}
-
-	if (!end_node) {
-		DRM_DEBUG_DRIVER("Missing bridge endpoint\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	remote = of_graph_get_remote_port_parent(end_node);
-	if (!remote) {
-		DRM_DEBUG_DRIVER("Enable to parse remote node\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	return of_drm_find_bridge(remote) ?: ERR_PTR(-EPROBE_DEFER);
-}
-
 static int sun4i_tcon_bind(struct device *dev, struct device *master,
 			   void *data)
 {
@@ -555,22 +486,11 @@ static int sun4i_tcon_probe(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 	struct drm_bridge *bridge;
 	struct drm_panel *panel;
+	int ret;

-	/*
-	 * Neither the bridge or the panel is ready.
-	 * Defer the probe.
-	 */
-	panel = sun4i_tcon_find_panel(node);
-	bridge = sun4i_tcon_find_bridge(node);
-
-	/*
-	 * If we don't have a panel endpoint, just go on
-	 */
-	if ((PTR_ERR(panel) == -EPROBE_DEFER) &&
-	    (PTR_ERR(bridge) == -EPROBE_DEFER)) {
-		DRM_DEBUG_DRIVER("Still waiting for our panel/bridge. Deferring...\n");
-		return -EPROBE_DEFER;
-	}
+	ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
+	if (ret == -EPROBE_DEFER)
+		return ret;

 	return component_add(&pdev->dev, &sun4i_tcon_ops);
 }
--
2.10.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 5/5] drm: omap: use common OF graph helpers
  2017-03-22 13:26 [PATCH v3 0/5] DRM OF graph clean-up Rob Herring
                   ` (3 preceding siblings ...)
  2017-03-22 13:26 ` [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge Rob Herring
@ 2017-03-22 13:26 ` Rob Herring
  2017-04-06 21:03 ` [PATCH v3 0/5] DRM OF graph clean-up Sean Paul
  5 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2017-03-22 13:26 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, linux-kernel, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner, Alison Wang,
	Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Maxime Ripard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

The OMAP driver has its own OF graph helpers that are similar to the
common helpers. This commit replaces most of the calls with the common
helpers. There's still a couple of custom helpers left, but the driver
needs more extensive changes to get rid of them.

In dss_init_ports, we invert the loop, looping through the known ports
and matching them to DT nodes rather than looping thru DT nodes and
matching them to the ports.

Signed-off-by: Rob Herring <robh@kernel.org>
---
v3:
- rebase to v4.11-rc2

 drivers/gpu/drm/omapdrm/dss/dpi.c     |   2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c     |   3 +-
 drivers/gpu/drm/omapdrm/dss/dss-of.c  | 102 +---------------------------------
 drivers/gpu/drm/omapdrm/dss/dss.c     |  61 +++++---------------
 drivers/gpu/drm/omapdrm/dss/hdmi4.c   |   3 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c   |   3 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  11 ----
 drivers/gpu/drm/omapdrm/dss/sdi.c     |   2 +-
 drivers/gpu/drm/omapdrm/dss/venc.c    |   3 +-
 9 files changed, 26 insertions(+), 164 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index e75162d26ac0..e5bb494d4689 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -855,7 +855,7 @@ int dpi_init_port(struct platform_device *pdev, struct device_node *port)
 	if (!dpi)
 		return -ENOMEM;

-	ep = omapdss_of_get_next_endpoint(port, NULL);
+	ep = of_get_next_child(port, NULL);
 	if (!ep)
 		return 0;

diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index f74615d005a8..0aebd5d709ea 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -39,6 +39,7 @@
 #include <linux/debugfs.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <linux/of_platform.h>
 #include <linux/component.h>

@@ -5091,7 +5092,7 @@ static int dsi_probe_of(struct platform_device *pdev)
 	struct device_node *ep;
 	struct omap_dsi_pin_config pin_cfg;

-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return 0;

diff --git a/drivers/gpu/drm/omapdrm/dss/dss-of.c b/drivers/gpu/drm/omapdrm/dss/dss-of.c
index dfd4e9621e3b..eb520ab45ddd 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss-of.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss-of.c
@@ -16,77 +16,12 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <linux/seq_file.h>

 #include "omapdss.h"
 #include "dss.h"

-struct device_node *
-omapdss_of_get_next_port(const struct device_node *parent,
-			 struct device_node *prev)
-{
-	struct device_node *port = NULL;
-
-	if (!parent)
-		return NULL;
-
-	if (!prev) {
-		struct device_node *ports;
-		/*
-		 * It's the first call, we have to find a port subnode
-		 * within this node or within an optional 'ports' node.
-		 */
-		ports = of_get_child_by_name(parent, "ports");
-		if (ports)
-			parent = ports;
-
-		port = of_get_child_by_name(parent, "port");
-
-		/* release the 'ports' node */
-		of_node_put(ports);
-	} else {
-		struct device_node *ports;
-
-		ports = of_get_parent(prev);
-		if (!ports)
-			return NULL;
-
-		do {
-			port = of_get_next_child(ports, prev);
-			if (!port) {
-				of_node_put(ports);
-				return NULL;
-			}
-			prev = port;
-		} while (of_node_cmp(port->name, "port") != 0);
-
-		of_node_put(ports);
-	}
-
-	return port;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_get_next_port);
-
-struct device_node *
-omapdss_of_get_next_endpoint(const struct device_node *parent,
-			     struct device_node *prev)
-{
-	struct device_node *ep = NULL;
-
-	if (!parent)
-		return NULL;
-
-	do {
-		ep = of_get_next_child(parent, prev);
-		if (!ep)
-			return NULL;
-		prev = ep;
-	} while (of_node_cmp(ep->name, "endpoint") != 0);
-
-	return ep;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint);
-
 struct device_node *dss_of_port_get_parent_device(struct device_node *port)
 {
 	struct device_node *np;
@@ -123,37 +58,6 @@ u32 dss_of_port_get_port_number(struct device_node *port)
 	return reg;
 }

-static struct device_node *omapdss_of_get_remote_port(const struct device_node *node)
-{
-	struct device_node *np;
-
-	np = of_parse_phandle(node, "remote-endpoint", 0);
-	if (!np)
-		return NULL;
-
-	np = of_get_next_parent(np);
-
-	return np;
-}
-
-struct device_node *
-omapdss_of_get_first_endpoint(const struct device_node *parent)
-{
-	struct device_node *port, *ep;
-
-	port = omapdss_of_get_next_port(parent, NULL);
-
-	if (!port)
-		return NULL;
-
-	ep = omapdss_of_get_next_endpoint(port, NULL);
-
-	of_node_put(port);
-
-	return ep;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint);
-
 struct omap_dss_device *
 omapdss_of_find_source_for_first_ep(struct device_node *node)
 {
@@ -161,11 +65,11 @@ omapdss_of_find_source_for_first_ep(struct device_node *node)
 	struct device_node *src_port;
 	struct omap_dss_device *src;

-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return ERR_PTR(-EINVAL);

-	src_port = omapdss_of_get_remote_port(ep);
+	src_port = of_graph_get_remote_port(ep);
 	if (!src_port) {
 		of_node_put(ep);
 		return ERR_PTR(-EINVAL);
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 14887d5b02e5..2734c401d9fa 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -38,6 +38,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <linux/regulator/consumer.h>
 #include <linux/suspend.h>
 #include <linux/component.h>
@@ -1043,32 +1044,14 @@ static int dss_init_ports(struct platform_device *pdev)
 {
 	struct device_node *parent = pdev->dev.of_node;
 	struct device_node *port;
-	int r;
-
-	if (parent == NULL)
-		return 0;
+	int i;

-	port = omapdss_of_get_next_port(parent, NULL);
-	if (!port)
-		return 0;
-
-	if (dss.feat->num_ports == 0)
-		return 0;
-
-	do {
-		enum omap_display_type port_type;
-		u32 reg;
-
-		r = of_property_read_u32(port, "reg", &reg);
-		if (r)
-			reg = 0;
-
-		if (reg >= dss.feat->num_ports)
+	for (i = 0; i < dss.feat->num_ports; i++) {
+		port = of_graph_get_port_by_id(parent, i);
+		if (!port)
 			continue;

-		port_type = dss.feat->ports[reg];
-
-		switch (port_type) {
+		switch (dss.feat->ports[i]) {
 		case OMAP_DISPLAY_TYPE_DPI:
 			dpi_init_port(pdev, port);
 			break;
@@ -1078,7 +1061,7 @@ static int dss_init_ports(struct platform_device *pdev)
 		default:
 			break;
 		}
-	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+	}

 	return 0;
 }
@@ -1087,32 +1070,14 @@ static void dss_uninit_ports(struct platform_device *pdev)
 {
 	struct device_node *parent = pdev->dev.of_node;
 	struct device_node *port;
+	int i;

-	if (parent == NULL)
-		return;
-
-	port = omapdss_of_get_next_port(parent, NULL);
-	if (!port)
-		return;
-
-	if (dss.feat->num_ports == 0)
-		return;
-
-	do {
-		enum omap_display_type port_type;
-		u32 reg;
-		int r;
-
-		r = of_property_read_u32(port, "reg", &reg);
-		if (r)
-			reg = 0;
-
-		if (reg >= dss.feat->num_ports)
+	for (i = 0; i < dss.feat->num_ports; i++) {
+		port = of_graph_get_port_by_id(parent, i);
+		if (!port)
 			continue;

-		port_type = dss.feat->ports[reg];
-
-		switch (port_type) {
+		switch (dss.feat->ports[i]) {
 		case OMAP_DISPLAY_TYPE_DPI:
 			dpi_uninit_port(port);
 			break;
@@ -1122,7 +1087,7 @@ static void dss_uninit_ports(struct platform_device *pdev)
 		default:
 			break;
 		}
-	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+	}
 }

 static int dss_video_pll_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index e7162c16de2e..87c53034c634 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -34,6 +34,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/component.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <sound/omap-hdmi-audio.h>

 #include "omapdss.h"
@@ -546,7 +547,7 @@ static int hdmi_probe_of(struct platform_device *pdev)
 	struct device_node *ep;
 	int r;

-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return 0;

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 678dfb02764a..d13dce7e8079 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -39,6 +39,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/component.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <sound/omap-hdmi-audio.h>

 #include "omapdss.h"
@@ -572,7 +573,7 @@ static int hdmi_probe_of(struct platform_device *pdev)
 	struct device_node *ep;
 	int r;

-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return 0;

diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 5b3b961127bd..175d36851467 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -830,17 +830,6 @@ static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev)
 	return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
 }

-struct device_node *
-omapdss_of_get_next_port(const struct device_node *parent,
-			 struct device_node *prev);
-
-struct device_node *
-omapdss_of_get_next_endpoint(const struct device_node *parent,
-			     struct device_node *prev);
-
-struct device_node *
-omapdss_of_get_first_endpoint(const struct device_node *parent);
-
 struct omap_dss_device *
 omapdss_of_find_source_for_first_ep(struct device_node *node);

diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index b3bda2d3c08d..0620b9f8c231 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -414,7 +414,7 @@ int sdi_init_port(struct platform_device *pdev, struct device_node *port)
 	u32 datapairs;
 	int r;

-	ep = omapdss_of_get_next_endpoint(port, NULL);
+	ep = of_get_next_child(port, NULL);
 	if (!ep)
 		return 0;

diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index d74f7fcc2e46..19d14957f566 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -35,6 +35,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <linux/component.h>

 #include "omapdss.h"
@@ -818,7 +819,7 @@ static int venc_probe_of(struct platform_device *pdev)
 	u32 channels;
 	int r;

-	ep = omapdss_of_get_first_endpoint(node);
+	ep = of_graph_get_endpoint_by_regs(node, 0, 0);
 	if (!ep)
 		return 0;

--
2.10.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 2/5] drm: of: introduce drm_of_find_panel_or_bridge
  2017-03-22 13:26 ` [PATCH v3 2/5] drm: of: introduce drm_of_find_panel_or_bridge Rob Herring
@ 2017-03-22 15:00   ` Philipp Zabel
  0 siblings, 0 replies; 14+ messages in thread
From: Philipp Zabel @ 2017-03-22 15:00 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, linux-kernel,
	Boris Brezillon, Archit Taneja, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Stefan Agner,
	Alison Wang, Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	CK Hu, Matthias Brugger, Marek Vasut, Mark Yao, Heiko Stuebner,
	Maxime Ripard, Chen-Yu Tsai, Liviu Dudau, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Wed, 2017-03-22 at 08:26 -0500, Rob Herring wrote:
> Many drivers have a common pattern of searching the OF graph for either an
> attached panel or bridge and then finding the DRM struct for the panel
> or bridge. Also, most drivers need to handle deferred probing when the
> DRM device is not yet instantiated. Create a common function,
> drm_of_find_panel_or_bridge, to find the connected node and the
> associated DRM panel or bridge device.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>
> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>

Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
(imx-ldb on i.MX6)

regards
Philipp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-03-22 13:26 ` [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge Rob Herring
@ 2017-03-22 15:01   ` Philipp Zabel
  2017-05-09 14:28     ` Leonard Crestez
  2017-03-23  8:03   ` Maxime Ripard
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: Philipp Zabel @ 2017-03-22 15:01 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, linux-kernel,
	Boris Brezillon, Archit Taneja, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Stefan Agner,
	Alison Wang, Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	CK Hu, Matthias Brugger, Marek Vasut, Mark Yao, Heiko Stuebner,
	Maxime Ripard, Chen-Yu Tsai, Liviu Dudau, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Wed, 2017-03-22 at 08:26 -0500, Rob Herring wrote:
> Similar to the previous commit, convert drivers open coding OF graph
> parsing to use drm_of_find_panel_or_bridge instead.
> 
> This changes some error messages to debug messages (in the graph core).
> Graph connections are often "no connects" depending on the particular
> board, so we want to avoid spurious messages. Plus the kernel is not a
> DT validator.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>
> Reviewed-by: Archit Taneja <architt@codeaurora.org>

Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
(imx-ldb on i.MX6)

regards
Philipp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-03-22 13:26 ` [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge Rob Herring
  2017-03-22 15:01   ` Philipp Zabel
@ 2017-03-23  8:03   ` Maxime Ripard
  2017-03-24 14:22   ` Sean Paul
  2017-03-29 18:55   ` [PATCH v4 " Rob Herring
  3 siblings, 0 replies; 14+ messages in thread
From: Maxime Ripard @ 2017-03-23  8:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, linux-kernel,
	Boris Brezillon, Archit Taneja, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Stefan Agner,
	Alison Wang, Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Chen-Yu Tsai, Liviu Dudau, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

[-- Attachment #1: Type: text/plain, Size: 1774 bytes --]

On Wed, Mar 22, 2017 at 08:26:07AM -0500, Rob Herring wrote:
> Similar to the previous commit, convert drivers open coding OF graph
> parsing to use drm_of_find_panel_or_bridge instead.
> 
> This changes some error messages to debug messages (in the graph core).
> Graph connections are often "no connects" depending on the particular
> board, so we want to avoid spurious messages. Plus the kernel is not a
> DT validator.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>
> Reviewed-by: Archit Taneja <architt@codeaurora.org>
> ---
> v3:
> - rebase to v4.11-rc2
> - rework atmel to support 1 to N connections
> 
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 73 ++++++-------------
>  drivers/gpu/drm/bridge/nxp-ptn3460.c             | 16 ++---
>  drivers/gpu/drm/bridge/parade-ps8622.c           | 16 ++---
>  drivers/gpu/drm/bridge/tc358767.c                | 27 +------
>  drivers/gpu/drm/exynos/exynos_dp.c               | 35 ++++-----
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c        | 39 +++-------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     | 27 ++-----
>  drivers/gpu/drm/imx/imx-ldb.c                    | 27 ++-----
>  drivers/gpu/drm/imx/parallel-display.c           | 36 ++--------
>  drivers/gpu/drm/mediatek/mtk_dsi.c               | 23 ++----
>  drivers/gpu/drm/mxsfb/mxsfb_out.c                | 40 ++---------
>  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  | 26 ++-----
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                | 11 +--
>  drivers/gpu/drm/sun4i/sun4i_tcon.c               | 90 ++----------------------

For sun4i,
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-03-22 13:26 ` [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge Rob Herring
  2017-03-22 15:01   ` Philipp Zabel
  2017-03-23  8:03   ` Maxime Ripard
@ 2017-03-24 14:22   ` Sean Paul
  2017-03-29 18:55   ` [PATCH v4 " Rob Herring
  3 siblings, 0 replies; 14+ messages in thread
From: Sean Paul @ 2017-03-24 14:22 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, linux-kernel,
	Boris Brezillon, Archit Taneja, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Stefan Agner,
	Alison Wang, Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Maxime Ripard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Wed, Mar 22, 2017 at 08:26:07AM -0500, Rob Herring wrote:
> Similar to the previous commit, convert drivers open coding OF graph
> parsing to use drm_of_find_panel_or_bridge instead.
> 
> This changes some error messages to debug messages (in the graph core).
> Graph connections are often "no connects" depending on the particular
> board, so we want to avoid spurious messages. Plus the kernel is not a
> DT validator.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>
> Reviewed-by: Archit Taneja <architt@codeaurora.org>
> ---
> v3:
> - rebase to v4.11-rc2
> - rework atmel to support 1 to N connections
> 
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 73 ++++++-------------
>  drivers/gpu/drm/bridge/nxp-ptn3460.c             | 16 ++---
>  drivers/gpu/drm/bridge/parade-ps8622.c           | 16 ++---
>  drivers/gpu/drm/bridge/tc358767.c                | 27 +------
>  drivers/gpu/drm/exynos/exynos_dp.c               | 35 ++++-----
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c        | 39 +++-------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     | 27 ++-----
>  drivers/gpu/drm/imx/imx-ldb.c                    | 27 ++-----
>  drivers/gpu/drm/imx/parallel-display.c           | 36 ++--------
>  drivers/gpu/drm/mediatek/mtk_dsi.c               | 23 ++----
>  drivers/gpu/drm/mxsfb/mxsfb_out.c                | 40 ++---------
>  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  | 26 ++-----
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                | 11 +--
>  drivers/gpu/drm/sun4i/sun4i_tcon.c               | 90 ++----------------------
>  14 files changed, 92 insertions(+), 394 deletions(-)
>
<snip>

> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index c3651456c963..511d68e22452 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -15,6 +15,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
> 
>  #include "fsl_dcu_drm_drv.h"
> @@ -141,28 +142,6 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
>  	return ret;
>  }
> 
> -static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
> -				   const struct of_endpoint *ep)
> -{
> -	struct drm_bridge *bridge;
> -	struct device_node *np;
> -
> -	np = of_graph_get_remote_port_parent(ep->local_node);
> -
> -	fsl_dev->connector.panel = of_drm_find_panel(np);
> -	if (fsl_dev->connector.panel) {
> -		of_node_put(np);
> -		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
> -	}
> -
> -	bridge = of_drm_find_bridge(np);
> -	of_node_put(np);
> -	if (!bridge)
> -		return -ENODEV;
> -
> -	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
> -}
> -
>  int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
>  {
>  	struct of_endpoint ep;
> @@ -179,14 +158,14 @@ int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
>  		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
>  	}
> 
> -	ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL);
> -	if (!ep_node)
> -		return -ENODEV;
> -
> -	ret = of_graph_parse_endpoint(ep_node, &ep);
> -	of_node_put(ep_node);
> +	ret = drm_of_find_panel_or_bridge(fsl_dev->np, 0, 0, &panel, &bridge);

Hi Rob,
Apologies for the delay, I've been dealing with overhead the past few days. I ran across
this compile error when build testing your set.


../drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c: In function
‘fsl_dcu_create_outputs’:
../drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c:161:56: error: ‘panel’ undeclared
(first use in this function)
../drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c:161:56: note: each undeclared
identifier is reported only once for each function it appears in
../drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c:161:64: error: ‘bridge’ undeclared
(first use in this function)
../drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c:148:22: warning: unused variable
‘ep_node’ [-Wunused-variable]
../drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c:147:21: warning: unused variable
‘ep’ [-Wunused-variable]
../drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c:171:1: warning: control reaches end
of non-void function [-Wreturn-type]
make[5]: *** [drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.o] Error 1
make[4]: *** [drivers/gpu/drm/fsl-dcu] Error 2
make[4]: *** Waiting for unfinished jobs....


The defconfigs we use can be found here:
https://cgit.freedesktop.org/drm/drm-tip/tree/?h=rerere-cache

Sean


>  	if (ret)
> -		return -ENODEV;
> +		return ret;
> 
> -	return fsl_dcu_attach_endpoint(fsl_dev, &ep);
> +	if (panel) {
> +		fsl_dev->connector.panel = panel;
> +		return fsl_dcu_attach_panel(fsl_dev, panel);
> +	}
> +
> +	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);

<snip>

> --
> 2.10.1
> 

-- 
Sean Paul, Software Engineer, Google / Chromium OS

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v4 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-03-22 13:26 ` [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge Rob Herring
                     ` (2 preceding siblings ...)
  2017-03-24 14:22   ` Sean Paul
@ 2017-03-29 18:55   ` Rob Herring
  3 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2017-03-29 18:55 UTC (permalink / raw)
  To: Sean Paul
  Cc: David Airlie, Daniel Vetter, dri-devel, linux-kernel,
	Boris Brezillon, Archit Taneja, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Stefan Agner,
	Alison Wang, Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Maxime Ripard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

Similar to the previous commit, convert drivers open coding OF graph
parsing to use drm_of_find_panel_or_bridge instead.

This changes some error messages to debug messages (in the graph core).
Graph connections are often "no connects" depending on the particular
board, so we want to avoid spurious messages. Plus the kernel is not a
DT validator.

Signed-off-by: Rob Herring <robh@kernel.org>
Reviewed-by: Archit Taneja <architt@codeaurora.org>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
Sean,

I fixed the compile error on FSL DCU. Let me know if you want me to 
send the whole series again.

Rob

 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 73 ++++++-------------
 drivers/gpu/drm/bridge/nxp-ptn3460.c             | 16 ++---
 drivers/gpu/drm/bridge/parade-ps8622.c           | 16 ++---
 drivers/gpu/drm/bridge/tc358767.c                | 27 +------
 drivers/gpu/drm/exynos/exynos_dp.c               | 35 ++++-----
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c        | 44 ++++--------
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     | 27 ++-----
 drivers/gpu/drm/imx/imx-ldb.c                    | 27 ++-----
 drivers/gpu/drm/imx/parallel-display.c           | 36 ++--------
 drivers/gpu/drm/mediatek/mtk_dsi.c               | 23 ++----
 drivers/gpu/drm/mxsfb/mxsfb_out.c                | 40 ++---------
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  | 26 ++-----
 drivers/gpu/drm/sun4i/sun4i_rgb.c                | 11 +--
 drivers/gpu/drm/sun4i/sun4i_tcon.c               | 90 ++----------------------
 14 files changed, 95 insertions(+), 396 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index e7799b6ee829..f987b4572d4a 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -22,7 +22,7 @@
 #include <linux/of_graph.h>
 
 #include <drm/drmP.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_of.h>
 
 #include "atmel_hlcdc_dc.h"
 
@@ -152,29 +152,11 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int atmel_hlcdc_check_endpoint(struct drm_device *dev,
-				      const struct of_endpoint *ep)
-{
-	struct device_node *np;
-	void *obj;
-
-	np = of_graph_get_remote_port_parent(ep->local_node);
-
-	obj = of_drm_find_panel(np);
-	if (!obj)
-		obj = of_drm_find_bridge(np);
-
-	of_node_put(np);
-
-	return obj ? 0 : -EPROBE_DEFER;
-}
-
 static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
-				       const struct of_endpoint *ep)
+				       const struct device_node *np)
 {
 	struct atmel_hlcdc_dc *dc = dev->dev_private;
 	struct atmel_hlcdc_rgb_output *output;
-	struct device_node *np;
 	struct drm_panel *panel;
 	struct drm_bridge *bridge;
 	int ret;
@@ -195,13 +177,11 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
 
 	output->encoder.possible_crtcs = 0x1;
 
-	np = of_graph_get_remote_port_parent(ep->local_node);
-
-	ret = -EPROBE_DEFER;
+	ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge);
+	if (ret)
+		return ret;
 
-	panel = of_drm_find_panel(np);
 	if (panel) {
-		of_node_put(np);
 		output->connector.dpms = DRM_MODE_DPMS_OFF;
 		output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
 		drm_connector_helper_add(&output->connector,
@@ -226,9 +206,6 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
 		return 0;
 	}
 
-	bridge = of_drm_find_bridge(np);
-	of_node_put(np);
-
 	if (bridge) {
 		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
 		if (!ret)
@@ -243,31 +220,23 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
 
 int atmel_hlcdc_create_outputs(struct drm_device *dev)
 {
-	struct device_node *ep_np = NULL;
-	struct of_endpoint ep;
-	int ret;
-
-	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
-		ret = of_graph_parse_endpoint(ep_np, &ep);
-		if (!ret)
-			ret = atmel_hlcdc_check_endpoint(dev, &ep);
-
-		if (ret) {
-			of_node_put(ep_np);
-			return ret;
-		}
-	}
-
-	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
-		ret = of_graph_parse_endpoint(ep_np, &ep);
-		if (!ret)
-			ret = atmel_hlcdc_attach_endpoint(dev, &ep);
-
-		if (ret) {
-			of_node_put(ep_np);
+	struct device_node *remote;
+	int ret, endpoint = 0;
+
+	while (true) {
+		/* Loop thru possible multiple connections to the output */
+		remote = of_graph_get_remote_node(dev->dev->of_node, 0,
+						  endpoint++);
+		if (!remote)
+			break;
+
+		ret = atmel_hlcdc_attach_endpoint(dev, remote);
+		of_node_put(remote);
+		if (ret)
 			return ret;
-		}
 	}
 
-	return 0;
+	if (!endpoint)
+		return -ENODEV;
+	return ret;
 }
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index 27f98c518dde..351704390d02 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -20,8 +20,8 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
-#include <linux/of_graph.h>
 
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include "drm_crtc.h"
@@ -292,7 +292,6 @@ static int ptn3460_probe(struct i2c_client *client,
 {
 	struct device *dev = &client->dev;
 	struct ptn3460_bridge *ptn_bridge;
-	struct device_node *endpoint, *panel_node;
 	int ret;
 
 	ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
@@ -300,16 +299,9 @@ static int ptn3460_probe(struct i2c_client *client,
 		return -ENOMEM;
 	}
 
-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		panel_node = of_graph_get_remote_port_parent(endpoint);
-		if (panel_node) {
-			ptn_bridge->panel = of_drm_find_panel(panel_node);
-			of_node_put(panel_node);
-			if (!ptn_bridge->panel)
-				return -EPROBE_DEFER;
-		}
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ptn_bridge->panel, NULL);
+	if (ret)
+		return ret;
 
 	ptn_bridge->client = client;
 
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index ac8cc5b50d9f..1dcec3b97e67 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -22,10 +22,10 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_graph.h>
 #include <linux/pm.h>
 #include <linux/regulator/consumer.h>
 
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include "drmP.h"
@@ -536,7 +536,6 @@ static int ps8622_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
-	struct device_node *endpoint, *panel_node;
 	struct ps8622_bridge *ps8622;
 	int ret;
 
@@ -544,16 +543,9 @@ static int ps8622_probe(struct i2c_client *client,
 	if (!ps8622)
 		return -ENOMEM;
 
-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		panel_node = of_graph_get_remote_port_parent(endpoint);
-		if (panel_node) {
-			ps8622->panel = of_drm_find_panel(panel_node);
-			of_node_put(panel_node);
-			if (!ps8622->panel)
-				return -EPROBE_DEFER;
-		}
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ps8622->panel, NULL);
+	if (ret)
+		return ret;
 
 	ps8622->client = client;
 
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index de9ffb49e9f6..5c26488e7a2d 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1244,7 +1244,6 @@ static const struct regmap_config tc_regmap_config = {
 static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
-	struct device_node *ep;
 	struct tc_data *tc;
 	int ret;
 
@@ -1255,29 +1254,9 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	tc->dev = dev;
 
 	/* port@2 is the output port */
-	ep = of_graph_get_endpoint_by_regs(dev->of_node, 2, -1);
-	if (ep) {
-		struct device_node *remote;
-
-		remote = of_graph_get_remote_port_parent(ep);
-		if (!remote) {
-			dev_warn(dev, "endpoint %s not connected\n",
-				 ep->full_name);
-			of_node_put(ep);
-			return -ENODEV;
-		}
-		of_node_put(ep);
-		tc->panel = of_drm_find_panel(remote);
-		if (tc->panel) {
-			dev_dbg(dev, "found panel %s\n", remote->full_name);
-		} else {
-			dev_dbg(dev, "waiting for panel %s\n",
-				remote->full_name);
-			of_node_put(remote);
-			return -EPROBE_DEFER;
-		}
-		of_node_put(remote);
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &tc->panel, NULL);
+	if (ret)
+		return ret;
 
 	/* Shut down GPIO is optional */
 	tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 1ef0be338b85..a269f439e742 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -23,6 +23,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include <drm/bridge/analogix_dp.h>
@@ -212,8 +213,11 @@ static const struct component_ops exynos_dp_ops = {
 static int exynos_dp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *np = NULL, *endpoint = NULL;
+	struct device_node *np;
 	struct exynos_dp_device *dp;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
+	int ret;
 
 	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
 			  GFP_KERNEL);
@@ -237,28 +241,13 @@ static int exynos_dp_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		np = of_graph_get_remote_port_parent(endpoint);
-		if (np) {
-			/* The remote port can be either a panel or a bridge */
-			dp->plat_data.panel = of_drm_find_panel(np);
-			if (!dp->plat_data.panel) {
-				dp->ptn_bridge = of_drm_find_bridge(np);
-				if (!dp->ptn_bridge) {
-					of_node_put(np);
-					return -EPROBE_DEFER;
-				}
-			}
-			of_node_put(np);
-		} else {
-			DRM_ERROR("no remote endpoint device node found.\n");
-			return -EINVAL;
-		}
-	} else {
-		DRM_ERROR("no port endpoint subnode found.\n");
-		return -EINVAL;
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, &bridge);
+	if (ret)
+		return ret;
+
+	/* The remote port can be either a panel or a bridge */
+	dp->plat_data.panel = panel;
+	dp->ptn_bridge = bridge;
 
 out:
 	return component_add(&pdev->dev, &exynos_dp_ops);
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index c3651456c963..dcbf3c06e1d8 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -15,6 +15,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include "fsl_dcu_drm_drv.h"
@@ -141,32 +142,11 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
 	return ret;
 }
 
-static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
-				   const struct of_endpoint *ep)
-{
-	struct drm_bridge *bridge;
-	struct device_node *np;
-
-	np = of_graph_get_remote_port_parent(ep->local_node);
-
-	fsl_dev->connector.panel = of_drm_find_panel(np);
-	if (fsl_dev->connector.panel) {
-		of_node_put(np);
-		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
-	}
-
-	bridge = of_drm_find_bridge(np);
-	of_node_put(np);
-	if (!bridge)
-		return -ENODEV;
-
-	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
-}
-
 int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
 {
-	struct of_endpoint ep;
-	struct device_node *ep_node, *panel_node;
+	struct device_node *panel_node;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
 	int ret;
 
 	/* This is for backward compatibility */
@@ -179,14 +159,14 @@ int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
 		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
 	}
 
-	ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL);
-	if (!ep_node)
-		return -ENODEV;
-
-	ret = of_graph_parse_endpoint(ep_node, &ep);
-	of_node_put(ep_node);
+	ret = drm_of_find_panel_or_bridge(fsl_dev->np, 0, 0, &panel, &bridge);
 	if (ret)
-		return -ENODEV;
+		return ret;
+
+	if (panel) {
+		fsl_dev->connector.panel = panel;
+		return fsl_dcu_attach_panel(fsl_dev, panel);
+	}
 
-	return fsl_dcu_attach_endpoint(fsl_dev, &ep);
+	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
 }
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 1737e98bc10a..5abc69c9630f 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -17,7 +17,6 @@
 
 #include <linux/clk.h>
 #include <linux/component.h>
-#include <linux/of_graph.h>
 
 #include <drm/drm_of.h>
 #include <drm/drm_crtc_helper.h>
@@ -754,34 +753,16 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
 {
 	struct dsi_hw_ctx *ctx = dsi->ctx;
 	struct device_node *np = pdev->dev.of_node;
-	struct device_node *endpoint, *bridge_node;
-	struct drm_bridge *bridge;
 	struct resource *res;
+	int ret;
 
 	/*
 	 * Get the endpoint node. In our case, dsi has one output port1
 	 * to which the external HDMI bridge is connected.
 	 */
-	endpoint = of_graph_get_endpoint_by_regs(np, 1, -1);
-	if (!endpoint) {
-		DRM_ERROR("no valid endpoint node\n");
-		return -ENODEV;
-	}
-	of_node_put(endpoint);
-
-	bridge_node = of_graph_get_remote_port_parent(endpoint);
-	if (!bridge_node) {
-		DRM_ERROR("no valid bridge node\n");
-		return -ENODEV;
-	}
-	of_node_put(bridge_node);
-
-	bridge = of_drm_find_bridge(bridge_node);
-	if (!bridge) {
-		DRM_INFO("wait for external HDMI bridge driver.\n");
-		return -EPROBE_DEFER;
-	}
-	dsi->bridge = bridge;
+	ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
+	if (ret)
+		return ret;
 
 	ctx->pclk = devm_clk_get(&pdev->dev, "pclk");
 	if (IS_ERR(ctx->pclk)) {
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 88cd11d30134..8fb801fab039 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -647,7 +647,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 
 	for_each_child_of_node(np, child) {
 		struct imx_ldb_channel *channel;
-		struct device_node *ep;
 		int bus_format;
 
 		ret = of_property_read_u32(child, "reg", &i);
@@ -671,27 +670,11 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 		 * The output port is port@4 with an external 4-port mux or
 		 * port@2 with the internal 2-port mux.
 		 */
-		ep = of_graph_get_endpoint_by_regs(child,
-						   imx_ldb->lvds_mux ? 4 : 2,
-						   -1);
-		if (ep) {
-			struct device_node *remote;
-
-			remote = of_graph_get_remote_port_parent(ep);
-			of_node_put(ep);
-			if (remote) {
-				channel->panel = of_drm_find_panel(remote);
-				channel->bridge = of_drm_find_bridge(remote);
-			} else
-				return -EPROBE_DEFER;
-			of_node_put(remote);
-
-			if (!channel->panel && !channel->bridge) {
-				dev_err(dev, "panel/bridge not found: %s\n",
-					remote->full_name);
-				return -EPROBE_DEFER;
-			}
-		}
+		ret = drm_of_find_panel_or_bridge(child,
+						  imx_ldb->lvds_mux ? 4 : 2, 0,
+						  &channel->panel, &channel->bridge);
+		if (ret)
+			return ret;
 
 		/* panel ddc only if there is no bridge */
 		if (!channel->bridge) {
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index d5c06fd89f90..636031a30e17 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -19,10 +19,10 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <linux/videodev2.h>
 #include <video/of_display_timing.h>
-#include <linux/of_graph.h>
 
 #include "imx-drm.h"
 
@@ -208,7 +208,6 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 {
 	struct drm_device *drm = data;
 	struct device_node *np = dev->of_node;
-	struct device_node *ep;
 	const u8 *edidp;
 	struct imx_parallel_display *imxpd;
 	int ret;
@@ -237,36 +236,9 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 	imxpd->bus_format = bus_format;
 
 	/* port@1 is the output port */
-	ep = of_graph_get_endpoint_by_regs(np, 1, -1);
-	if (ep) {
-		struct device_node *remote;
-
-		remote = of_graph_get_remote_port_parent(ep);
-		if (!remote) {
-			dev_warn(dev, "endpoint %s not connected\n",
-				 ep->full_name);
-			of_node_put(ep);
-			return -ENODEV;
-		}
-		of_node_put(ep);
-
-		imxpd->panel = of_drm_find_panel(remote);
-		if (imxpd->panel) {
-			dev_dbg(dev, "found panel %s\n", remote->full_name);
-		} else {
-			imxpd->bridge = of_drm_find_bridge(remote);
-			if (imxpd->bridge)
-				dev_dbg(dev, "found bridge %s\n",
-					remote->full_name);
-		}
-		if (!imxpd->panel && !imxpd->bridge) {
-			dev_dbg(dev, "waiting for panel or bridge %s\n",
-				remote->full_name);
-			of_node_put(remote);
-			return -EPROBE_DEFER;
-		}
-		of_node_put(remote);
-	}
+	ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel, &imxpd->bridge);
+	if (ret)
+		return ret;
 
 	imxpd->dev = dev;
 
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index dd71cbb1a622..4d837b29ee9e 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -16,11 +16,11 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_of.h>
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#include <linux/of_graph.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <video/videomode.h>
@@ -801,7 +801,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 {
 	struct mtk_dsi *dsi;
 	struct device *dev = &pdev->dev;
-	struct device_node *remote_node, *endpoint;
 	struct resource *regs;
 	int comp_id;
 	int ret;
@@ -813,22 +812,10 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 	dsi->host.ops = &mtk_dsi_ops;
 	dsi->host.dev = dev;
 
-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		remote_node = of_graph_get_remote_port_parent(endpoint);
-		if (!remote_node) {
-			dev_err(dev, "No panel connected\n");
-			return -ENODEV;
-		}
-
-		dsi->bridge = of_drm_find_bridge(remote_node);
-		dsi->panel = of_drm_find_panel(remote_node);
-		of_node_put(remote_node);
-		if (!dsi->bridge && !dsi->panel) {
-			dev_info(dev, "Waiting for bridge or panel driver\n");
-			return -EPROBE_DEFER;
-		}
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
+					  &dsi->panel, &dsi->bridge);
+	if (ret)
+		return ret;
 
 	dsi->engine_clk = devm_clk_get(dev, "engine");
 	if (IS_ERR(dsi->engine_clk)) {
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
index b8e81422d4e2..f7d729aa09bd 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_out.c
@@ -19,6 +19,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_simple_kms_helper.h>
@@ -82,20 +83,15 @@ static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
 };
 
-static int mxsfb_attach_endpoint(struct drm_device *drm,
-				 const struct of_endpoint *ep)
+int mxsfb_create_output(struct drm_device *drm)
 {
 	struct mxsfb_drm_private *mxsfb = drm->dev_private;
-	struct device_node *np;
 	struct drm_panel *panel;
-	int ret = -EPROBE_DEFER;
-
-	np = of_graph_get_remote_port_parent(ep->local_node);
-	panel = of_drm_find_panel(np);
-	of_node_put(np);
+	int ret;
 
-	if (!panel)
-		return -EPROBE_DEFER;
+	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, NULL);
+	if (ret)
+		return ret;
 
 	mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
 	mxsfb->connector.polled = 0;
@@ -109,27 +105,3 @@ static int mxsfb_attach_endpoint(struct drm_device *drm,
 
 	return ret;
 }
-
-int mxsfb_create_output(struct drm_device *drm)
-{
-	struct mxsfb_drm_private *mxsfb = drm->dev_private;
-	struct device_node *ep_np = NULL;
-	struct of_endpoint ep;
-	int ret;
-
-	for_each_endpoint_of_node(drm->dev->of_node, ep_np) {
-		ret = of_graph_parse_endpoint(ep_np, &ep);
-		if (!ret)
-			ret = mxsfb_attach_endpoint(drm, &ep);
-
-		if (ret) {
-			of_node_put(ep_np);
-			return ret;
-		}
-	}
-
-	if (!mxsfb->panel)
-		return -EPROBE_DEFER;
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 8548e8271639..615afad280a8 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -428,31 +428,13 @@ static const struct component_ops rockchip_dp_component_ops = {
 static int rockchip_dp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *panel_node, *port, *endpoint;
 	struct drm_panel *panel = NULL;
 	struct rockchip_dp_device *dp;
+	int ret;
 
-	port = of_graph_get_port_by_id(dev->of_node, 1);
-	if (port) {
-		endpoint = of_get_child_by_name(port, "endpoint");
-		of_node_put(port);
-		if (!endpoint) {
-			dev_err(dev, "no output endpoint found\n");
-			return -EINVAL;
-		}
-
-		panel_node = of_graph_get_remote_port_parent(endpoint);
-		of_node_put(endpoint);
-		if (!panel_node) {
-			dev_err(dev, "no output node found\n");
-			return -EINVAL;
-		}
-
-		panel = of_drm_find_panel(panel_node);
-		of_node_put(panel_node);
-		if (!panel)
-			return -EPROBE_DEFER;
-	}
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
+	if (ret)
+		return ret;
 
 	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
 	if (!dp)
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 757208f51731..46280dd70c9e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -15,6 +15,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include "sun4i_drv.h"
@@ -218,9 +219,9 @@ int sun4i_rgb_init(struct drm_device *drm)
 	rgb->drv = drv;
 	encoder = &rgb->encoder;
 
-	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
-	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
-	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
+	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
+					  &tcon->panel, &bridge);
+	if (ret) {
 		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
 		return 0;
 	}
@@ -240,7 +241,7 @@ int sun4i_rgb_init(struct drm_device *drm)
 	/* The RGB encoder can only work with the TCON channel 0 */
 	rgb->encoder.possible_crtcs = BIT(0);
 
-	if (!IS_ERR(tcon->panel)) {
+	if (tcon->panel) {
 		drm_connector_helper_add(&rgb->connector,
 					 &sun4i_rgb_con_helper_funcs);
 		ret = drm_connector_init(drm, &rgb->connector,
@@ -261,7 +262,7 @@ int sun4i_rgb_init(struct drm_device *drm)
 		}
 	}
 
-	if (!IS_ERR(bridge)) {
+	if (bridge) {
 		ret = drm_bridge_attach(encoder, bridge, NULL);
 		if (ret) {
 			dev_err(drm->dev, "Couldn't attach our bridge\n");
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index ea2906f87cb9..2e4e365cecf9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -15,13 +15,12 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_modes.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_of.h>
 
 #include <linux/component.h>
 #include <linux/ioport.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
-#include <linux/of_graph.h>
 #include <linux/of_irq.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
@@ -405,74 +404,6 @@ static int sun4i_tcon_init_regmap(struct device *dev,
 	return 0;
 }
 
-struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
-{
-	struct device_node *port, *remote, *child;
-	struct device_node *end_node = NULL;
-
-	/* Inputs are listed first, then outputs */
-	port = of_graph_get_port_by_id(node, 1);
-
-	/*
-	 * Our first output is the RGB interface where the panel will
-	 * be connected.
-	 */
-	for_each_child_of_node(port, child) {
-		u32 reg;
-
-		of_property_read_u32(child, "reg", &reg);
-		if (reg == 0)
-			end_node = child;
-	}
-
-	if (!end_node) {
-		DRM_DEBUG_DRIVER("Missing panel endpoint\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	remote = of_graph_get_remote_port_parent(end_node);
-	if (!remote) {
-		DRM_DEBUG_DRIVER("Unable to parse remote node\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
-}
-
-struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node)
-{
-	struct device_node *port, *remote, *child;
-	struct device_node *end_node = NULL;
-
-	/* Inputs are listed first, then outputs */
-	port = of_graph_get_port_by_id(node, 1);
-
-	/*
-	 * Our first output is the RGB interface where the panel will
-	 * be connected.
-	 */
-	for_each_child_of_node(port, child) {
-		u32 reg;
-
-		of_property_read_u32(child, "reg", &reg);
-		if (reg == 0)
-			end_node = child;
-	}
-
-	if (!end_node) {
-		DRM_DEBUG_DRIVER("Missing bridge endpoint\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	remote = of_graph_get_remote_port_parent(end_node);
-	if (!remote) {
-		DRM_DEBUG_DRIVER("Enable to parse remote node\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	return of_drm_find_bridge(remote) ?: ERR_PTR(-EPROBE_DEFER);
-}
-
 static int sun4i_tcon_bind(struct device *dev, struct device *master,
 			   void *data)
 {
@@ -555,22 +486,11 @@ static int sun4i_tcon_probe(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 	struct drm_bridge *bridge;
 	struct drm_panel *panel;
+	int ret;
 
-	/*
-	 * Neither the bridge or the panel is ready.
-	 * Defer the probe.
-	 */
-	panel = sun4i_tcon_find_panel(node);
-	bridge = sun4i_tcon_find_bridge(node);
-
-	/*
-	 * If we don't have a panel endpoint, just go on
-	 */
-	if ((PTR_ERR(panel) == -EPROBE_DEFER) &&
-	    (PTR_ERR(bridge) == -EPROBE_DEFER)) {
-		DRM_DEBUG_DRIVER("Still waiting for our panel/bridge. Deferring...\n");
-		return -EPROBE_DEFER;
-	}
+	ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
+	if (ret == -EPROBE_DEFER)
+		return ret;
 
 	return component_add(&pdev->dev, &sun4i_tcon_ops);
 }
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 0/5] DRM OF graph clean-up
  2017-03-22 13:26 [PATCH v3 0/5] DRM OF graph clean-up Rob Herring
                   ` (4 preceding siblings ...)
  2017-03-22 13:26 ` [PATCH v3 5/5] drm: omap: use common OF graph helpers Rob Herring
@ 2017-04-06 21:03 ` Sean Paul
  5 siblings, 0 replies; 14+ messages in thread
From: Sean Paul @ 2017-04-06 21:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, dri-devel,
	Linux Kernel Mailing List, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner, Alison Wang,
	Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Matthias Brugger, Marek Vasut, Mark Yao,
	Heiko Stuebner, Maxime Ripard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Wed, Mar 22, 2017 at 9:26 AM, Rob Herring <robh@kernel.org> wrote:
> I've been unhappy with the OF graph API for some time and decided to
> do something about it. The problem is drivers have to do too much of the
> graph parsing and walking themselves. This has led to the same pattern
> duplicated over and over. This series adapts DRM drivers to use a new OF
> graph helper and added DRM helper.
>
> The DT dependency went into 4.11, so this series can be applied to the DRM
> tree without any cross tree dependencies.
>
> I've done some build testing only, so testing appreciated. A git branch is
> here[1].
>
> Rob
>
> [1] git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git of-graph-helpers
>
>
> Rob Herring (5):
>   drm: make of_drm_find_panel also depend on CONFIG_DRM_PANEL
>   drm: of: introduce drm_of_find_panel_or_bridge
>   drm: convert drivers to use of_graph_get_remote_node
>   drm: convert drivers to use drm_of_find_panel_or_bridge
>   drm: omap: use common OF graph helpers
>

Hi Rob,
Thank you for the series, and sorry for the delay. I've fixed the 2
conflicts and applied to -misc-next.

Sean


>  drivers/gpu/drm/arm/hdlcd_drv.c                  |  22 +----
>  drivers/gpu/drm/arm/malidp_drv.c                 |  28 +------
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c |  73 +++++-----------
>  drivers/gpu/drm/bridge/adv7511/adv7533.c         |  12 +--
>  drivers/gpu/drm/bridge/dumb-vga-dac.c            |  15 +---
>  drivers/gpu/drm/bridge/nxp-ptn3460.c             |  16 +---
>  drivers/gpu/drm/bridge/parade-ps8622.c           |  16 +---
>  drivers/gpu/drm/bridge/tc358767.c                |  27 +-----
>  drivers/gpu/drm/bridge/ti-tfp410.c               |  15 ++--
>  drivers/gpu/drm/drm_of.c                         |  52 ++++++++++++
>  drivers/gpu/drm/exynos/exynos_dp.c               |  35 +++-----
>  drivers/gpu/drm/exynos/exynos_drm_dpi.c          |  16 +---
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c          |  13 +--
>  drivers/gpu/drm/exynos/exynos_drm_mic.c          |  25 +-----
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c        |  39 ++-------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     |  27 +-----
>  drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c  |  30 +------
>  drivers/gpu/drm/imx/imx-ldb.c                    |  27 ++----
>  drivers/gpu/drm/imx/parallel-display.c           |  36 +-------
>  drivers/gpu/drm/mediatek/mtk_dpi.c               |  12 +--
>  drivers/gpu/drm/mediatek/mtk_dsi.c               |  23 ++---
>  drivers/gpu/drm/mediatek/mtk_hdmi.c              |  26 +-----
>  drivers/gpu/drm/meson/meson_venc_cvbs.c          |  19 +----
>  drivers/gpu/drm/msm/dsi/dsi_host.c               |   2 +-
>  drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c          |  28 +------
>  drivers/gpu/drm/mxsfb/mxsfb_out.c                |  40 ++-------
>  drivers/gpu/drm/omapdrm/dss/dpi.c                |   2 +-
>  drivers/gpu/drm/omapdrm/dss/dsi.c                |   3 +-
>  drivers/gpu/drm/omapdrm/dss/dss-of.c             | 102 +----------------------
>  drivers/gpu/drm/omapdrm/dss/dss.c                |  61 +++-----------
>  drivers/gpu/drm/omapdrm/dss/hdmi4.c              |   3 +-
>  drivers/gpu/drm/omapdrm/dss/hdmi5.c              |   3 +-
>  drivers/gpu/drm/omapdrm/dss/omapdss.h            |  11 ---
>  drivers/gpu/drm/omapdrm/dss/sdi.c                |   2 +-
>  drivers/gpu/drm/omapdrm/dss/venc.c               |   3 +-
>  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  |  26 +-----
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c      |  18 ++--
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                |  11 +--
>  drivers/gpu/drm/sun4i/sun4i_tcon.c               |  90 ++------------------
>  drivers/gpu/drm/tilcdc/tilcdc_crtc.c             |  12 +--
>  drivers/gpu/drm/tilcdc/tilcdc_external.c         |  68 ++-------------
>  drivers/gpu/drm/vc4/vc4_dpi.c                    |  15 +---
>  include/drm/drm_of.h                             |  13 +++
>  include/drm/drm_panel.h                          |   2 +-
>  44 files changed, 238 insertions(+), 881 deletions(-)
>
> --
> 2.10.1
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-03-22 15:01   ` Philipp Zabel
@ 2017-05-09 14:28     ` Leonard Crestez
  2017-05-09 22:43       ` Rob Herring
  0 siblings, 1 reply; 14+ messages in thread
From: Leonard Crestez @ 2017-05-09 14:28 UTC (permalink / raw)
  To: Rob Herring, Philipp Zabel
  Cc: dri-devel, linux-kernel, Cristina Ciocan, Octavian Purdila

On Wed, Mar 22, 2017 at 5:01 PM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> On Wed, 2017-03-22 at 08:26 -0500, Rob Herring wrote:
> > 
> > Similar to the previous commit, convert drivers open coding OF graph
> > parsing to use drm_of_find_panel_or_bridge instead.
> > 
> > This changes some error messages to debug messages (in the graph core).
> > Graph connections are often "no connects" depending on the particular
> > board, so we want to avoid spurious messages. Plus the kernel is not a
> > DT validator.
> > 
> > Signed-off-by: Rob Herring <robh@kernel.org>
> > Reviewed-by: Archit Taneja <architt@codeaurora.org>
> Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
> (imx-ldb on i.MX6)

It seems that this breaks on (at least) imx6qdl-sabreauto. The relevant
section of the boot log looks like this:

imx-drm display-subsystem: bound imx-ipuv3-crtc.2 (ops ipu_crtc_ops)
imx-drm display-subsystem: bound imx-ipuv3-crtc.3 (ops ipu_crtc_ops)
dwhdmi-imx 120000.hdmi: Detected HDMI TX controller v1.31a with HDCP
(DWC HDMI 3D TX PHY)
dwhdmi-imx 120000.hdmi: registered DesignWare HDMI I2C bus driver
imx-drm display-subsystem: bound 120000.hdmi (ops dw_hdmi_imx_ops)
imx-drm display-subsystem: failed to bind 2000000.aips-bus:ldb (ops
imx_ldb_ops): -19
imx-drm display-subsystem: master bind failed: -19

It seems that imx6qdl-sabreauto does not have any panel defined in dts.
This used to be ignored when of_graph_get_endpoint_by_regs returned
NULL but now drm_of_find_panel_or_bridge returns -ENODEV and this
causes imx_ldb_bind to fail altogether. Defining a panel works
(including showing stuff on a LVDS panel). Ignoring -ENODEV also fixes
this:

--- drivers/gpu/drm/imx/imx-ldb.c
+++ drivers/gpu/drm/imx/imx-ldb.c
@@ -673,7 +673,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                ret = drm_of_find_panel_or_bridge(child,
                                                  imx_ldb->lvds_mux ? 4 : 2, 0,
                                                  &channel->panel, &channel->bridge);
-               if (ret)
+               if (ret != -ENODEV)
                        return ret;
 
                /* panel ddc only if there is no bridge */

I don't know much about drm and it's not clear if failing to find a
panel should be an error here or not and the hack above is likely the
wrong way to handle it anyway.

I was bisecting the fact that suspend now breaks on upstream. The fact
that a probe error later breaks suspend is possibly an unrelated issue,
right?

-- 
Regards,
Leonard

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-05-09 14:28     ` Leonard Crestez
@ 2017-05-09 22:43       ` Rob Herring
  0 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2017-05-09 22:43 UTC (permalink / raw)
  To: Leonard Crestez
  Cc: Philipp Zabel, dri-devel, linux-kernel, Cristina Ciocan,
	Octavian Purdila

On Tue, May 9, 2017 at 9:28 AM, Leonard Crestez <leonard.crestez@nxp.com> wrote:
> On Wed, Mar 22, 2017 at 5:01 PM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
>> On Wed, 2017-03-22 at 08:26 -0500, Rob Herring wrote:
>> >
>> > Similar to the previous commit, convert drivers open coding OF graph
>> > parsing to use drm_of_find_panel_or_bridge instead.
>> >
>> > This changes some error messages to debug messages (in the graph core).
>> > Graph connections are often "no connects" depending on the particular
>> > board, so we want to avoid spurious messages. Plus the kernel is not a
>> > DT validator.
>> >
>> > Signed-off-by: Rob Herring <robh@kernel.org>
>> > Reviewed-by: Archit Taneja <architt@codeaurora.org>
>> Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
>> (imx-ldb on i.MX6)
>
> It seems that this breaks on (at least) imx6qdl-sabreauto. The relevant
> section of the boot log looks like this:
>
> imx-drm display-subsystem: bound imx-ipuv3-crtc.2 (ops ipu_crtc_ops)
> imx-drm display-subsystem: bound imx-ipuv3-crtc.3 (ops ipu_crtc_ops)
> dwhdmi-imx 120000.hdmi: Detected HDMI TX controller v1.31a with HDCP
> (DWC HDMI 3D TX PHY)
> dwhdmi-imx 120000.hdmi: registered DesignWare HDMI I2C bus driver
> imx-drm display-subsystem: bound 120000.hdmi (ops dw_hdmi_imx_ops)
> imx-drm display-subsystem: failed to bind 2000000.aips-bus:ldb (ops
> imx_ldb_ops): -19
> imx-drm display-subsystem: master bind failed: -19
>
> It seems that imx6qdl-sabreauto does not have any panel defined in dts.
> This used to be ignored when of_graph_get_endpoint_by_regs returned
> NULL but now drm_of_find_panel_or_bridge returns -ENODEV and this
> causes imx_ldb_bind to fail altogether. Defining a panel works
> (including showing stuff on a LVDS panel). Ignoring -ENODEV also fixes
> this:
>
> --- drivers/gpu/drm/imx/imx-ldb.c
> +++ drivers/gpu/drm/imx/imx-ldb.c
> @@ -673,7 +673,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
>                 ret = drm_of_find_panel_or_bridge(child,
>                                                   imx_ldb->lvds_mux ? 4 : 2, 0,
>                                                   &channel->panel, &channel->bridge);
> -               if (ret)
> +               if (ret != -ENODEV)
>                         return ret;
>
>                 /* panel ddc only if there is no bridge */
>
> I don't know much about drm and it's not clear if failing to find a
> panel should be an error here or not and the hack above is likely the
> wrong way to handle it anyway.

That looks like the right fix to me. Ideally, the DT should probably
define an LVDS connector node (if not a panel) in this case like we do
for other cases with DDC, but more importantly we shouldn't require a
DT update to fix things. If you needed power or gpio controls of the
panel you would also need some node in DT.

Do you mind sending a proper patch?

Rob

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2017-05-09 22:44 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-22 13:26 [PATCH v3 0/5] DRM OF graph clean-up Rob Herring
2017-03-22 13:26 ` [PATCH v3 1/5] drm: make of_drm_find_panel also depend on CONFIG_DRM_PANEL Rob Herring
2017-03-22 13:26 ` [PATCH v3 2/5] drm: of: introduce drm_of_find_panel_or_bridge Rob Herring
2017-03-22 15:00   ` Philipp Zabel
2017-03-22 13:26 ` [PATCH v3 3/5] drm: convert drivers to use of_graph_get_remote_node Rob Herring
2017-03-22 13:26 ` [PATCH v3 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge Rob Herring
2017-03-22 15:01   ` Philipp Zabel
2017-05-09 14:28     ` Leonard Crestez
2017-05-09 22:43       ` Rob Herring
2017-03-23  8:03   ` Maxime Ripard
2017-03-24 14:22   ` Sean Paul
2017-03-29 18:55   ` [PATCH v4 " Rob Herring
2017-03-22 13:26 ` [PATCH v3 5/5] drm: omap: use common OF graph helpers Rob Herring
2017-04-06 21:03 ` [PATCH v3 0/5] DRM OF graph clean-up Sean Paul

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).