All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] DRM OF graph clean-up
@ 2017-02-04  3:36 ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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 adds 2 new helpers and adapts DRM 
drivers to use them. It only adds one new graph helper, but reduces the 
use of the others which I hope to remove at some point. But we're not 
there yet.

There's a few other things I'd like to clean-up.

The Armada and Rockchip drivers remain oddballs with their own graph 
parsing. I can't see how the armada driver even can work. There's 
nothing to instantiate the armada-drm device either in DT or the kernel.

The omapdrm driver still has some custom helpers similar to the common 
ones, but still slightly different. It got to be more changes than I 
wanted to make to address.

Build tested only (and probably not every last driver).

Rob

Rob Herring (5):
  of: introduce of_graph_get_remote_node
  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                 |  29 +------
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c |  64 +++-----------
 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                         |  50 +++++++++++
 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          |  27 +-----
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c        |  49 ++++-------
 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                    |  28 ++-----
 drivers/gpu/drm/imx/parallel-display.c           |  35 +-------
 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_drv.c                |  12 +--
 drivers/gpu/drm/meson/meson_venc_cvbs.c          |  19 +----
 drivers/gpu/drm/msm/dsi/dsi_host.c               |   3 +-
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c          |  28 +------
 drivers/gpu/drm/mxsfb/mxsfb_out.c                |  36 ++------
 drivers/gpu/drm/omapdrm/dss/dpi.c                |   2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c                |   2 +-
 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              |   2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h            |  11 ---
 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                |  17 ++--
 drivers/gpu/drm/sun4i/sun4i_tcon.c               |  90 ++------------------
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c             |  11 +--
 drivers/gpu/drm/tilcdc/tilcdc_external.c         |  66 ++-------------
 drivers/gpu/drm/vc4/vc4_dpi.c                    |  15 +---
 drivers/of/base.c                                |  28 +++++++
 include/drm/drm_of.h                             |  13 +++
 include/linux/of_graph.h                         |   8 ++
 45 files changed, 272 insertions(+), 891 deletions(-)

-- 
2.10.1

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

* [PATCH 0/5] DRM OF graph clean-up
@ 2017-02-04  3:36 ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

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 adds 2 new helpers and adapts DRM 
drivers to use them. It only adds one new graph helper, but reduces the 
use of the others which I hope to remove at some point. But we're not 
there yet.

There's a few other things I'd like to clean-up.

The Armada and Rockchip drivers remain oddballs with their own graph 
parsing. I can't see how the armada driver even can work. There's 
nothing to instantiate the armada-drm device either in DT or the kernel.

The omapdrm driver still has some custom helpers similar to the common 
ones, but still slightly different. It got to be more changes than I 
wanted to make to address.

Build tested only (and probably not every last driver).

Rob

Rob Herring (5):
  of: introduce of_graph_get_remote_node
  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                 |  29 +------
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c |  64 +++-----------
 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                         |  50 +++++++++++
 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          |  27 +-----
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c        |  49 ++++-------
 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                    |  28 ++-----
 drivers/gpu/drm/imx/parallel-display.c           |  35 +-------
 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_drv.c                |  12 +--
 drivers/gpu/drm/meson/meson_venc_cvbs.c          |  19 +----
 drivers/gpu/drm/msm/dsi/dsi_host.c               |   3 +-
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c          |  28 +------
 drivers/gpu/drm/mxsfb/mxsfb_out.c                |  36 ++------
 drivers/gpu/drm/omapdrm/dss/dpi.c                |   2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c                |   2 +-
 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              |   2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h            |  11 ---
 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                |  17 ++--
 drivers/gpu/drm/sun4i/sun4i_tcon.c               |  90 ++------------------
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c             |  11 +--
 drivers/gpu/drm/tilcdc/tilcdc_external.c         |  66 ++-------------
 drivers/gpu/drm/vc4/vc4_dpi.c                    |  15 +---
 drivers/of/base.c                                |  28 +++++++
 include/drm/drm_of.h                             |  13 +++
 include/linux/of_graph.h                         |   8 ++
 45 files changed, 272 insertions(+), 891 deletions(-)

-- 
2.10.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 1/5] of: introduce of_graph_get_remote_node
  2017-02-04  3:36 ` Rob Herring
@ 2017-02-04  3:36   ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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 OF graph API leaves too much of the graph walking to clients when
in many cases the driver doesn't care about accessing the port or
endpoint nodes. The drivers typically just want the device connected via
a particular graph connection. of_graph_get_remote_node provides this
functionality.

Signed-off-by: Rob Herring <robh@kernel.org>
---
 drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
 include/linux/of_graph.h |  8 ++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index d4bea3c797d6..ea18ab16b92c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
 	return of_get_next_parent(np);
 }
 EXPORT_SYMBOL(of_graph_get_remote_port);
+
+struct device_node *of_graph_get_remote_node(const struct device_node *node,
+					     int port, int endpoint)
+{
+	struct device_node *endpoint_node, *remote;
+
+	endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
+	if (!endpoint_node) {
+		pr_debug("no valid endpoint (%d, %d) for node %s\n",
+			 port, endpoint, node->full_name);
+		return NULL;
+	}
+
+	remote = of_graph_get_remote_port_parent(endpoint_node);
+	of_node_put(endpoint);
+	if (!remote) {
+		pr_debug("no valid remote node\n");
+		return NULL;
+	}
+
+	if (!of_device_is_available(remote)) {
+		pr_debug("not available for remote node\n");
+		return NULL;
+	}
+
+	return remote;
+}
+EXPORT_SYMBOL(of_graph_get_remote_node);
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index bb3a5a2cd570..7b71d3e09209 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -51,6 +51,8 @@ struct device_node *of_graph_get_endpoint_by_regs(
 struct device_node *of_graph_get_remote_port_parent(
 					const struct device_node *node);
 struct device_node *of_graph_get_remote_port(const struct device_node *node);
+struct device_node *of_graph_get_remote_node(const struct device_node *node,
+					     int port, int endpoint);
 #else
 
 static inline int of_graph_parse_endpoint(const struct device_node *node,
@@ -89,6 +91,12 @@ static inline struct device_node *of_graph_get_remote_port(
 {
 	return NULL;
 }
+static inline struct device_node *of_graph_get_remote_node(
+					const struct device_node *node,
+					int port, int endpoint)
+{
+	return NULL;
+}
 
 #endif /* CONFIG_OF */
 
-- 
2.10.1

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

* [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-04  3:36   ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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

The OF graph API leaves too much of the graph walking to clients when
in many cases the driver doesn't care about accessing the port or
endpoint nodes. The drivers typically just want the device connected via
a particular graph connection. of_graph_get_remote_node provides this
functionality.

Signed-off-by: Rob Herring <robh@kernel.org>
---
 drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
 include/linux/of_graph.h |  8 ++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index d4bea3c797d6..ea18ab16b92c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
 	return of_get_next_parent(np);
 }
 EXPORT_SYMBOL(of_graph_get_remote_port);
+
+struct device_node *of_graph_get_remote_node(const struct device_node *node,
+					     int port, int endpoint)
+{
+	struct device_node *endpoint_node, *remote;
+
+	endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
+	if (!endpoint_node) {
+		pr_debug("no valid endpoint (%d, %d) for node %s\n",
+			 port, endpoint, node->full_name);
+		return NULL;
+	}
+
+	remote = of_graph_get_remote_port_parent(endpoint_node);
+	of_node_put(endpoint);
+	if (!remote) {
+		pr_debug("no valid remote node\n");
+		return NULL;
+	}
+
+	if (!of_device_is_available(remote)) {
+		pr_debug("not available for remote node\n");
+		return NULL;
+	}
+
+	return remote;
+}
+EXPORT_SYMBOL(of_graph_get_remote_node);
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index bb3a5a2cd570..7b71d3e09209 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -51,6 +51,8 @@ struct device_node *of_graph_get_endpoint_by_regs(
 struct device_node *of_graph_get_remote_port_parent(
 					const struct device_node *node);
 struct device_node *of_graph_get_remote_port(const struct device_node *node);
+struct device_node *of_graph_get_remote_node(const struct device_node *node,
+					     int port, int endpoint);
 #else
 
 static inline int of_graph_parse_endpoint(const struct device_node *node,
@@ -89,6 +91,12 @@ static inline struct device_node *of_graph_get_remote_port(
 {
 	return NULL;
 }
+static inline struct device_node *of_graph_get_remote_node(
+					const struct device_node *node,
+					int port, int endpoint)
+{
+	return NULL;
+}
 
 #endif /* CONFIG_OF */
 
-- 
2.10.1

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

* [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
  2017-02-04  3:36 ` Rob Herring
@ 2017-02-04  3:36   ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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>
---
 drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_of.h     | 13 +++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 47848ed8ca48..b29ce2f52113 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -3,7 +3,9 @@
 #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_panel.h>
 #include <drm/drm_of.h>
 
 static void drm_release_of(struct device *dev, void *data)
@@ -207,3 +209,51 @@ 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 input 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.
+ *
+ * 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 = -ENODEV;
+	struct device_node *remote;
+
+	remote = of_graph_get_remote_node(np, port, endpoint);
+	if (!remote)
+		return -ENODEV;
+
+	if (bridge)
+		*bridge = NULL;
+
+	if (panel) {
+		*panel = of_drm_find_panel(remote);
+		if (*panel) {
+			ret = 0;
+			goto out_put;
+		}
+		ret = -EPROBE_DEFER;
+	}
+
+	if (bridge) {
+		*bridge = of_drm_find_bridge(remote);
+		if (*bridge)
+			ret = 0;
+		else
+			ret = -EPROBE_DEFER;
+	}
+out_put:
+	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] 80+ messages in thread

* [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-04  3:36   ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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

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>
---
 drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_of.h     | 13 +++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 47848ed8ca48..b29ce2f52113 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -3,7 +3,9 @@
 #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_panel.h>
 #include <drm/drm_of.h>
 
 static void drm_release_of(struct device *dev, void *data)
@@ -207,3 +209,51 @@ 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 input 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.
+ *
+ * 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 = -ENODEV;
+	struct device_node *remote;
+
+	remote = of_graph_get_remote_node(np, port, endpoint);
+	if (!remote)
+		return -ENODEV;
+
+	if (bridge)
+		*bridge = NULL;
+
+	if (panel) {
+		*panel = of_drm_find_panel(remote);
+		if (*panel) {
+			ret = 0;
+			goto out_put;
+		}
+		ret = -EPROBE_DEFER;
+	}
+
+	if (bridge) {
+		*bridge = of_drm_find_bridge(remote);
+		if (*bridge)
+			ret = 0;
+		else
+			ret = -EPROBE_DEFER;
+	}
+out_put:
+	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] 80+ messages in thread

* [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
  2017-02-04  3:36 ` Rob Herring
@ 2017-02-04  3:36   ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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>
---
 drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
 drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
 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         | 27 +---------
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
 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_drv.c               | 12 ++---
 drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
 drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
 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            | 11 +----
 drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
 drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
 20 files changed, 64 insertions(+), 351 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index e5f4f4a6546d..0f70f5fe9970 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -430,29 +430,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 32f746e31379..bfa04be7f5de 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -262,7 +262,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);
@@ -360,12 +359,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) {
@@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
 irq_init_fail:
 	component_unbind_all(dev, drm);
 bind_fail:
-	of_node_put(malidp->crtc.port);
 	malidp->crtc.port = NULL;
-port_fail:
 	malidp_fini(drm);
 init_fail:
 	drm->dev_private = NULL;
@@ -478,29 +470,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 e5706981c934..47b4c99162ad 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 e07cb1fe4860..04528f512c91 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 a0def0be6d65..93ebb12133e1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -228,29 +228,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;
@@ -262,7 +239,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;
@@ -279,7 +256,7 @@ static int parse_dt(struct exynos_mic *mic)
 			break;
 		case ENDPOINT_DSI_NODE:
 			/* panel node */
-			remote_node = get_remote_node(remote_node, 1);
+			remote_node = of_graph_get_remote_node(remote_node, 1, 0);
 			if (!remote_node) {
 				ret = -EPIPE;
 				goto exit;
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 998452ad0fcb..4ed6b5fef3b7 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -757,34 +757,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 device_node *bridge_node;
 	struct resource *res;
 
 	/*
 	 * 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, 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/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index ebd5f4fe4c23..18d6570e057d 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -247,34 +247,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;
@@ -288,7 +260,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 90fb831ef031..dbd554c09a39 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 0e8c4d9af340..f14e472812ce 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1433,7 +1433,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;
@@ -1485,29 +1485,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->bridge.next = of_drm_find_bridge(remote);
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index ff1f6019b97b..37cb9c755ed7 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -163,14 +163,14 @@ static struct drm_driver meson_driver = {
 
 static bool meson_vpu_has_available_connectors(struct device *dev)
 {
-	struct device_node *ep, *remote;
+	struct device_node *remote;
+	int i;
 
-	/* Parses each endpoint and check if remote exists */
-	for_each_endpoint_of_node(dev->of_node, ep) {
-		/* If the endpoint node exists, consider it enabled */
-		remote = of_graph_get_remote_port(ep);
-		if (remote)
+	for_each_of_graph_remote_node(dev->of_node, remote, i, 2) {
+		if (remote) {
+			of_node_put(remote);
 			return true;
+		}
 	}
 
 	return false;
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 3819fdefcae2..da8619f9eb2e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1637,9 +1637,8 @@ 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_err(dev, "%s: no valid device\n", __func__);
 		ret = -ENODEV;
 		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 b782efd4b95f..9f36fad1915e 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)
@@ -270,7 +244,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 2390c8577617..5e7ccd04ada6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -373,19 +373,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);
@@ -464,7 +458,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 6dfdb145f3bb..e74cc236a79b 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -1013,16 +1013,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, 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 c67d7cd7d57e..b7523dce4e8a 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -187,39 +187,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;
@@ -227,7 +194,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;
 
@@ -266,35 +233,18 @@ 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))
+	if (!match)
 		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;
+	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] 80+ messages in thread

* [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-04  3:36   ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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

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>
---
 drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
 drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
 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         | 27 +---------
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
 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_drv.c               | 12 ++---
 drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
 drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
 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            | 11 +----
 drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
 drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
 20 files changed, 64 insertions(+), 351 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index e5f4f4a6546d..0f70f5fe9970 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -430,29 +430,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 32f746e31379..bfa04be7f5de 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -262,7 +262,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);
@@ -360,12 +359,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) {
@@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
 irq_init_fail:
 	component_unbind_all(dev, drm);
 bind_fail:
-	of_node_put(malidp->crtc.port);
 	malidp->crtc.port = NULL;
-port_fail:
 	malidp_fini(drm);
 init_fail:
 	drm->dev_private = NULL;
@@ -478,29 +470,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 e5706981c934..47b4c99162ad 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 e07cb1fe4860..04528f512c91 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 a0def0be6d65..93ebb12133e1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -228,29 +228,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;
@@ -262,7 +239,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;
@@ -279,7 +256,7 @@ static int parse_dt(struct exynos_mic *mic)
 			break;
 		case ENDPOINT_DSI_NODE:
 			/* panel node */
-			remote_node = get_remote_node(remote_node, 1);
+			remote_node = of_graph_get_remote_node(remote_node, 1, 0);
 			if (!remote_node) {
 				ret = -EPIPE;
 				goto exit;
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 998452ad0fcb..4ed6b5fef3b7 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -757,34 +757,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 device_node *bridge_node;
 	struct resource *res;
 
 	/*
 	 * 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, 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/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index ebd5f4fe4c23..18d6570e057d 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -247,34 +247,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;
@@ -288,7 +260,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 90fb831ef031..dbd554c09a39 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 0e8c4d9af340..f14e472812ce 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1433,7 +1433,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;
@@ -1485,29 +1485,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->bridge.next = of_drm_find_bridge(remote);
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index ff1f6019b97b..37cb9c755ed7 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -163,14 +163,14 @@ static struct drm_driver meson_driver = {
 
 static bool meson_vpu_has_available_connectors(struct device *dev)
 {
-	struct device_node *ep, *remote;
+	struct device_node *remote;
+	int i;
 
-	/* Parses each endpoint and check if remote exists */
-	for_each_endpoint_of_node(dev->of_node, ep) {
-		/* If the endpoint node exists, consider it enabled */
-		remote = of_graph_get_remote_port(ep);
-		if (remote)
+	for_each_of_graph_remote_node(dev->of_node, remote, i, 2) {
+		if (remote) {
+			of_node_put(remote);
 			return true;
+		}
 	}
 
 	return false;
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 3819fdefcae2..da8619f9eb2e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1637,9 +1637,8 @@ 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_err(dev, "%s: no valid device\n", __func__);
 		ret = -ENODEV;
 		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 b782efd4b95f..9f36fad1915e 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)
@@ -270,7 +244,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 2390c8577617..5e7ccd04ada6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -373,19 +373,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);
@@ -464,7 +458,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 6dfdb145f3bb..e74cc236a79b 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -1013,16 +1013,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, 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 c67d7cd7d57e..b7523dce4e8a 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -187,39 +187,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;
@@ -227,7 +194,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;
 
@@ -266,35 +233,18 @@ 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))
+	if (!match)
 		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;
+	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] 80+ messages in thread

* [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-02-04  3:36 ` Rob Herring
@ 2017-02-04  3:36   ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 64 ++++-------------
 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        | 49 ++++---------
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     |  5 +-
 drivers/gpu/drm/imx/imx-ldb.c                    | 28 ++------
 drivers/gpu/drm/imx/parallel-display.c           | 35 ++-------
 drivers/gpu/drm/mediatek/mtk_dsi.c               | 23 ++----
 drivers/gpu/drm/mxsfb/mxsfb_out.c                | 36 ++--------
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  | 26 ++-----
 drivers/gpu/drm/sun4i/sun4i_rgb.c                | 17 ++---
 drivers/gpu/drm/sun4i/sun4i_tcon.c               | 90 ++----------------------
 14 files changed, 88 insertions(+), 379 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 6119b5085501..4614048a4935 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) {
 		output->encoder.bridge = bridge;
 		bridge->encoder = &output->encoder;
@@ -245,31 +222,14 @@ 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;
+	struct device_node *remote;
 	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);
-			return ret;
-		}
-	}
+	remote = of_graph_get_remote_node(dev->dev->of_node, 0, 0);
+	if (!remote)
+		return -ENODEV;
 
-	return 0;
+	ret = atmel_hlcdc_attach_endpoint(dev, remote);
+	of_node_put(remote);
+	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 528229faffe4..376c941c5189 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>
@@ -215,8 +216,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);
@@ -240,28 +244,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 05a8ee106879..3cae7dd75834 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,35 +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;
-
-	fsl_dev->encoder.bridge = bridge;
-	bridge->encoder = &fsl_dev->encoder;
-
-	return drm_bridge_attach(fsl_dev->drm, bridge);
-}
-
 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_bridge *bridge;
+	struct drm_panel *panel;
 	int ret;
 
 	/* This is for backward compatibility */
@@ -182,14 +159,16 @@ 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);
+	}
+
+	fsl_dev->encoder.bridge = bridge;
+	bridge->encoder = &fsl_dev->encoder;
+	return drm_bridge_attach(fsl_dev->drm, bridge);
 }
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 4ed6b5fef3b7..0f23e2c55862 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>
@@ -757,14 +756,14 @@ 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 *bridge_node;
 	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.
 	 */
-	ret = drm_of_find_panel_or_bridge(np, NULL, &dsi->bridge);
+	ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 516d06490465..e670993906b8 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -649,7 +649,7 @@ 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;
+		struct device_node *remote;
 		int bus_format;
 
 		ret = of_property_read_u32(child, "reg", &i);
@@ -673,27 +673,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(fsl_dev->np,
+						  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 8582a83c0d9b..eb3a0201853a 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -210,7 +210,7 @@ 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;
+	struct device_node *remote;
 	const u8 *edidp;
 	struct imx_parallel_display *imxpd;
 	int ret;
@@ -239,36 +239,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 2c42f90809d8..14140579f8d4 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>
@@ -819,7 +819,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;
@@ -831,22 +830,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 fa8d17399407..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,23 +105,3 @@ static int mxsfb_attach_endpoint(struct drm_device *drm,
 
 	return ret;
 }
-
-int mxsfb_create_output(struct drm_device *drm)
-{
-	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;
-		}
-	}
-
-	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 f5e86fe7750e..4720725b0fb0 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"
@@ -217,12 +218,10 @@ int sun4i_rgb_init(struct drm_device *drm)
 	rgb->drv = drv;
 	encoder = &rgb->encoder;
 
-	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
-	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
-	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
-		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
-		return 0;
-	}
+	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
+					  &tcon->panel, &encoder->bridge);
+	if (ret)
+		return ret;
 
 	drm_encoder_helper_add(&rgb->encoder,
 			       &sun4i_rgb_enc_helper_funcs);
@@ -239,7 +238,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,
@@ -260,7 +259,7 @@ int sun4i_rgb_init(struct drm_device *drm)
 		}
 	}
 
-	if (!IS_ERR(encoder->bridge)) {
+	if (encoder->bridge) {
 		encoder->bridge->encoder = &rgb->encoder;
 
 		ret = drm_bridge_attach(drm, encoder->bridge);
@@ -268,8 +267,6 @@ int sun4i_rgb_init(struct drm_device *drm)
 			dev_err(drm->dev, "Couldn't attach our bridge\n");
 			goto err_cleanup_connector;
 		}
-	} else {
-		encoder->bridge = NULL;
 	}
 
 	return 0;
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] 80+ messages in thread

* [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-04  3:36   ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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

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>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 64 ++++-------------
 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        | 49 ++++---------
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     |  5 +-
 drivers/gpu/drm/imx/imx-ldb.c                    | 28 ++------
 drivers/gpu/drm/imx/parallel-display.c           | 35 ++-------
 drivers/gpu/drm/mediatek/mtk_dsi.c               | 23 ++----
 drivers/gpu/drm/mxsfb/mxsfb_out.c                | 36 ++--------
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  | 26 ++-----
 drivers/gpu/drm/sun4i/sun4i_rgb.c                | 17 ++---
 drivers/gpu/drm/sun4i/sun4i_tcon.c               | 90 ++----------------------
 14 files changed, 88 insertions(+), 379 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 6119b5085501..4614048a4935 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) {
 		output->encoder.bridge = bridge;
 		bridge->encoder = &output->encoder;
@@ -245,31 +222,14 @@ 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;
+	struct device_node *remote;
 	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);
-			return ret;
-		}
-	}
+	remote = of_graph_get_remote_node(dev->dev->of_node, 0, 0);
+	if (!remote)
+		return -ENODEV;
 
-	return 0;
+	ret = atmel_hlcdc_attach_endpoint(dev, remote);
+	of_node_put(remote);
+	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 528229faffe4..376c941c5189 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>
@@ -215,8 +216,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);
@@ -240,28 +244,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 05a8ee106879..3cae7dd75834 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,35 +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;
-
-	fsl_dev->encoder.bridge = bridge;
-	bridge->encoder = &fsl_dev->encoder;
-
-	return drm_bridge_attach(fsl_dev->drm, bridge);
-}
-
 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_bridge *bridge;
+	struct drm_panel *panel;
 	int ret;
 
 	/* This is for backward compatibility */
@@ -182,14 +159,16 @@ 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);
+	}
+
+	fsl_dev->encoder.bridge = bridge;
+	bridge->encoder = &fsl_dev->encoder;
+	return drm_bridge_attach(fsl_dev->drm, bridge);
 }
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 4ed6b5fef3b7..0f23e2c55862 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>
@@ -757,14 +756,14 @@ 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 *bridge_node;
 	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.
 	 */
-	ret = drm_of_find_panel_or_bridge(np, NULL, &dsi->bridge);
+	ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 516d06490465..e670993906b8 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -649,7 +649,7 @@ 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;
+		struct device_node *remote;
 		int bus_format;
 
 		ret = of_property_read_u32(child, "reg", &i);
@@ -673,27 +673,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(fsl_dev->np,
+						  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 8582a83c0d9b..eb3a0201853a 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -210,7 +210,7 @@ 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;
+	struct device_node *remote;
 	const u8 *edidp;
 	struct imx_parallel_display *imxpd;
 	int ret;
@@ -239,36 +239,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 2c42f90809d8..14140579f8d4 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>
@@ -819,7 +819,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;
@@ -831,22 +830,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 fa8d17399407..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,23 +105,3 @@ static int mxsfb_attach_endpoint(struct drm_device *drm,
 
 	return ret;
 }
-
-int mxsfb_create_output(struct drm_device *drm)
-{
-	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;
-		}
-	}
-
-	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 f5e86fe7750e..4720725b0fb0 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"
@@ -217,12 +218,10 @@ int sun4i_rgb_init(struct drm_device *drm)
 	rgb->drv = drv;
 	encoder = &rgb->encoder;
 
-	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
-	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
-	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
-		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
-		return 0;
-	}
+	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
+					  &tcon->panel, &encoder->bridge);
+	if (ret)
+		return ret;
 
 	drm_encoder_helper_add(&rgb->encoder,
 			       &sun4i_rgb_enc_helper_funcs);
@@ -239,7 +238,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,
@@ -260,7 +259,7 @@ int sun4i_rgb_init(struct drm_device *drm)
 		}
 	}
 
-	if (!IS_ERR(encoder->bridge)) {
+	if (encoder->bridge) {
 		encoder->bridge->encoder = &rgb->encoder;
 
 		ret = drm_bridge_attach(drm, encoder->bridge);
@@ -268,8 +267,6 @@ int sun4i_rgb_init(struct drm_device *drm)
 			dev_err(drm->dev, "Couldn't attach our bridge\n");
 			goto err_cleanup_connector;
 		}
-	} else {
-		encoder->bridge = NULL;
 	}
 
 	return 0;
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] 80+ messages in thread

* [PATCH 5/5] drm: omap: use common OF graph helpers
  2017-02-04  3:36 ` Rob Herring
@ 2017-02-04  3:36   ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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>
---
 drivers/gpu/drm/omapdrm/dss/dpi.c     |   2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c     |   2 +-
 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   |   2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  11 ----
 drivers/gpu/drm/omapdrm/dss/venc.c    |   3 +-
 8 files changed, 23 insertions(+), 163 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 f060bda31235..a9235b9fdaaf 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -5091,7 +5091,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..1d14a4ac9902 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -572,7 +572,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 b420dde8c0fb..acf4e520baaf 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/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] 80+ messages in thread

* [PATCH 5/5] drm: omap: use common OF graph helpers
@ 2017-02-04  3:36   ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-04  3:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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

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>
---
 drivers/gpu/drm/omapdrm/dss/dpi.c     |   2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c     |   2 +-
 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   |   2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  11 ----
 drivers/gpu/drm/omapdrm/dss/venc.c    |   3 +-
 8 files changed, 23 insertions(+), 163 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 f060bda31235..a9235b9fdaaf 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -5091,7 +5091,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..1d14a4ac9902 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -572,7 +572,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 b420dde8c0fb..acf4e520baaf 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/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] 80+ messages in thread

* Re: [PATCH 0/5] DRM OF graph clean-up
  2017-02-04  3:36 ` Rob Herring
@ 2017-02-04 10:47   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 80+ messages in thread
From: Russell King - ARM Linux @ 2017-02-04 10:47 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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

On Fri, Feb 03, 2017 at 09:36:30PM -0600, Rob Herring wrote:
> The Armada and Rockchip drivers remain oddballs with their own graph 
> parsing. I can't see how the armada driver even can work. There's 
> nothing to instantiate the armada-drm device either in DT or the kernel.

Correct, that's sitting out of tree because it requires either legacy
code in arch/arm/mach-dove at the moment, or stuff for DT.  Each time
that I looked at the DT reserved memory stuff I've ended up giving up
as it always seemed to be half complete, and the documentation was
confusing (seemingly referring to things that weren't merged.)

Maybe that's changed today, but I've not had a chance to look at it
again.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH 0/5] DRM OF graph clean-up
@ 2017-02-04 10:47   ` Russell King - ARM Linux
  0 siblings, 0 replies; 80+ messages in thread
From: Russell King - ARM Linux @ 2017-02-04 10:47 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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

On Fri, Feb 03, 2017 at 09:36:30PM -0600, Rob Herring wrote:
> The Armada and Rockchip drivers remain oddballs with their own graph 
> parsing. I can't see how the armada driver even can work. There's 
> nothing to instantiate the armada-drm device either in DT or the kernel.

Correct, that's sitting out of tree because it requires either legacy
code in arch/arm/mach-dove at the moment, or stuff for DT.  Each time
that I looked at the DT reserved memory stuff I've ended up giving up
as it always seemed to be half complete, and the documentation was
confusing (seemingly referring to things that weren't merged.)

Maybe that's changed today, but I've not had a chance to look at it
again.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-04 16:10     ` Vladimir Zapolskiy
  0 siblings, 0 replies; 80+ messages in thread
From: Vladimir Zapolskiy @ 2017-02-04 16:10 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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

Hi Rob,

On 02/04/2017 05:36 AM, Rob Herring wrote:
> The OF graph API leaves too much of the graph walking to clients when
> in many cases the driver doesn't care about accessing the port or
> endpoint nodes. The drivers typically just want the device connected via
> a particular graph connection. of_graph_get_remote_node provides this
> functionality.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
>  include/linux/of_graph.h |  8 ++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d4bea3c797d6..ea18ab16b92c 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>  	return of_get_next_parent(np);
>  }
>  EXPORT_SYMBOL(of_graph_get_remote_port);
> +
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint)

it would be nice to add a short comment that a returned device
node is expected to be dereferenced with of_node_put().

> +{
> +	struct device_node *endpoint_node, *remote;
> +
> +	endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
> +	if (!endpoint_node) {
> +		pr_debug("no valid endpoint (%d, %d) for node %s\n",
> +			 port, endpoint, node->full_name);
> +		return NULL;
> +	}
> +
> +	remote = of_graph_get_remote_port_parent(endpoint_node);
> +	of_node_put(endpoint);

Typo, here it should be of_node_put(endpoint_node);

> +	if (!remote) {
> +		pr_debug("no valid remote node\n");
> +		return NULL;
> +	}
> +
> +	if (!of_device_is_available(remote)) {
> +		pr_debug("not available for remote node\n");
> +		return NULL;
> +	}
> +
> +	return remote;
> +}
> +EXPORT_SYMBOL(of_graph_get_remote_node);

--
With best wishes,
Vladimir

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-04 16:10     ` Vladimir Zapolskiy
  0 siblings, 0 replies; 80+ messages in thread
From: Vladimir Zapolskiy @ 2017-02-04 16:10 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

Hi Rob,

On 02/04/2017 05:36 AM, Rob Herring wrote:
> The OF graph API leaves too much of the graph walking to clients when
> in many cases the driver doesn't care about accessing the port or
> endpoint nodes. The drivers typically just want the device connected via
> a particular graph connection. of_graph_get_remote_node provides this
> functionality.
> 
> Signed-off-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
>  include/linux/of_graph.h |  8 ++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d4bea3c797d6..ea18ab16b92c 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>  	return of_get_next_parent(np);
>  }
>  EXPORT_SYMBOL(of_graph_get_remote_port);
> +
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint)

it would be nice to add a short comment that a returned device
node is expected to be dereferenced with of_node_put().

> +{
> +	struct device_node *endpoint_node, *remote;
> +
> +	endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
> +	if (!endpoint_node) {
> +		pr_debug("no valid endpoint (%d, %d) for node %s\n",
> +			 port, endpoint, node->full_name);
> +		return NULL;
> +	}
> +
> +	remote = of_graph_get_remote_port_parent(endpoint_node);
> +	of_node_put(endpoint);

Typo, here it should be of_node_put(endpoint_node);

> +	if (!remote) {
> +		pr_debug("no valid remote node\n");
> +		return NULL;
> +	}
> +
> +	if (!of_device_is_available(remote)) {
> +		pr_debug("not available for remote node\n");
> +		return NULL;
> +	}
> +
> +	return remote;
> +}
> +EXPORT_SYMBOL(of_graph_get_remote_node);

--
With best wishes,
Vladimir
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-04 20:26     ` Fabio Estevam
  0 siblings, 0 replies; 80+ messages in thread
From: Fabio Estevam @ 2017-02-04 20:26 UTC (permalink / raw)
  To: Rob Herring, Marek Vasut
  Cc: David Airlie, Daniel Vetter, Sean Paul, DRI mailing list,
	devicetree, linux-kernel, Frank Rowand, 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, 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

Hi Rob,

On Sat, Feb 4, 2017 at 1:36 AM, Rob Herring <robh@kernel.org> wrote:

> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> index fa8d17399407..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;

I fixed some build issues of this series and I am trying to use it
with the mxsfb drm driver.

I would like to add bridge support for this driver, so that I can use
the TDA19988 HDMI bridge on a imx6sx-udoo-neo-full board.

My dts looks like this:

--- a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
+++ b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
@@ -185,6 +185,41 @@
        };
 };

+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       clock-frequency = <100000>;
+       status = "okay";
+
+       hdmi-transmitter@70 {
+               compatible = "nxp,tda998x";
+               reg = <0x70>;
+               pinctrl-0 = <&pinctrl_hdmi>;
+               pinctrl-names = "default";
+               interrupt-parent = <&gpio3>;
+               interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
+               clocks = <&clks IMX6SX_CLK_CKO2>;
+
+               port {
+                       tda998x_input: endpoint {
+                               remote-endpoint = <&lcdif1_output>;
+                       };
+               };
+       };
+};
+
+&lcdif1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_lcd>;
+       status = "okay";
+
+       port {
+               lcdif1_output: endpoint {
+                       remote-endpoint = <&tda998x_input>;
+               };
+       };
+};

and I changed it to:

ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, &bridge);

,but drm_of_find_panel_or_bridge() always returns -EPROBE_DEFER.

Shouldn't it be able to find the bridge chip in this case? Any ideas
of what it is missing?

Thanks

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-04 20:26     ` Fabio Estevam
  0 siblings, 0 replies; 80+ messages in thread
From: Fabio Estevam @ 2017-02-04 20:26 UTC (permalink / raw)
  To: Rob Herring, Marek Vasut
  Cc: David Airlie, Daniel Vetter, Sean Paul, DRI mailing list,
	devicetree-u79uwXL29TY76Z2rM5mHXA, linux-kernel, Frank Rowand,
	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

Hi Rob,

On Sat, Feb 4, 2017 at 1:36 AM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:

> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
> index fa8d17399407..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;

I fixed some build issues of this series and I am trying to use it
with the mxsfb drm driver.

I would like to add bridge support for this driver, so that I can use
the TDA19988 HDMI bridge on a imx6sx-udoo-neo-full board.

My dts looks like this:

--- a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
+++ b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
@@ -185,6 +185,41 @@
        };
 };

+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       clock-frequency = <100000>;
+       status = "okay";
+
+       hdmi-transmitter@70 {
+               compatible = "nxp,tda998x";
+               reg = <0x70>;
+               pinctrl-0 = <&pinctrl_hdmi>;
+               pinctrl-names = "default";
+               interrupt-parent = <&gpio3>;
+               interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
+               clocks = <&clks IMX6SX_CLK_CKO2>;
+
+               port {
+                       tda998x_input: endpoint {
+                               remote-endpoint = <&lcdif1_output>;
+                       };
+               };
+       };
+};
+
+&lcdif1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_lcd>;
+       status = "okay";
+
+       port {
+               lcdif1_output: endpoint {
+                       remote-endpoint = <&tda998x_input>;
+               };
+       };
+};

and I changed it to:

ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, &bridge);

,but drm_of_find_panel_or_bridge() always returns -EPROBE_DEFER.

Shouldn't it be able to find the bridge chip in this case? Any ideas
of what it is missing?

Thanks
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-02-04 20:26     ` Fabio Estevam
@ 2017-02-05 22:25       ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-05 22:25 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: Marek Vasut, David Airlie, Daniel Vetter, Sean Paul,
	DRI mailing list, devicetree, linux-kernel, Frank Rowand,
	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, 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 Sat, Feb 4, 2017 at 2:26 PM, Fabio Estevam <festevam@gmail.com> wrote:
> Hi Rob,
>
> On Sat, Feb 4, 2017 at 1:36 AM, Rob Herring <robh@kernel.org> wrote:
>
>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
>> index fa8d17399407..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;
>
> I fixed some build issues of this series and I am trying to use it
> with the mxsfb drm driver.
>
> I would like to add bridge support for this driver, so that I can use
> the TDA19988 HDMI bridge on a imx6sx-udoo-neo-full board.
>
> My dts looks like this:
>
> --- a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
> +++ b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
> @@ -185,6 +185,41 @@
>         };
>  };
>
> +&i2c3 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_i2c3>;
> +       clock-frequency = <100000>;
> +       status = "okay";
> +
> +       hdmi-transmitter@70 {
> +               compatible = "nxp,tda998x";
> +               reg = <0x70>;
> +               pinctrl-0 = <&pinctrl_hdmi>;
> +               pinctrl-names = "default";
> +               interrupt-parent = <&gpio3>;
> +               interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
> +               clocks = <&clks IMX6SX_CLK_CKO2>;
> +
> +               port {
> +                       tda998x_input: endpoint {
> +                               remote-endpoint = <&lcdif1_output>;
> +                       };
> +               };
> +       };
> +};
> +
> +&lcdif1 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_lcd>;
> +       status = "okay";
> +
> +       port {
> +               lcdif1_output: endpoint {
> +                       remote-endpoint = <&tda998x_input>;
> +               };
> +       };
> +};
>
> and I changed it to:
>
> ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, &bridge);
>
> ,but drm_of_find_panel_or_bridge() always returns -EPROBE_DEFER.
>
> Shouldn't it be able to find the bridge chip in this case? Any ideas
> of what it is missing?

Did the bridge driver probe? This function just checks lists of
registered panels and bridges.

Rob

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-05 22:25       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-05 22:25 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: Marek Vasut, David Airlie, Daniel Vetter, Sean Paul,
	DRI mailing list, devicetree, linux-kernel, Frank Rowand,
	Boris Brezillon, Archit Taneja, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Stefan Agner

On Sat, Feb 4, 2017 at 2:26 PM, Fabio Estevam <festevam@gmail.com> wrote:
> Hi Rob,
>
> On Sat, Feb 4, 2017 at 1:36 AM, Rob Herring <robh@kernel.org> wrote:
>
>> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
>> index fa8d17399407..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;
>
> I fixed some build issues of this series and I am trying to use it
> with the mxsfb drm driver.
>
> I would like to add bridge support for this driver, so that I can use
> the TDA19988 HDMI bridge on a imx6sx-udoo-neo-full board.
>
> My dts looks like this:
>
> --- a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
> +++ b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
> @@ -185,6 +185,41 @@
>         };
>  };
>
> +&i2c3 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_i2c3>;
> +       clock-frequency = <100000>;
> +       status = "okay";
> +
> +       hdmi-transmitter@70 {
> +               compatible = "nxp,tda998x";
> +               reg = <0x70>;
> +               pinctrl-0 = <&pinctrl_hdmi>;
> +               pinctrl-names = "default";
> +               interrupt-parent = <&gpio3>;
> +               interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
> +               clocks = <&clks IMX6SX_CLK_CKO2>;
> +
> +               port {
> +                       tda998x_input: endpoint {
> +                               remote-endpoint = <&lcdif1_output>;
> +                       };
> +               };
> +       };
> +};
> +
> +&lcdif1 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_lcd>;
> +       status = "okay";
> +
> +       port {
> +               lcdif1_output: endpoint {
> +                       remote-endpoint = <&tda998x_input>;
> +               };
> +       };
> +};
>
> and I changed it to:
>
> ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, &bridge);
>
> ,but drm_of_find_panel_or_bridge() always returns -EPROBE_DEFER.
>
> Shouldn't it be able to find the bridge chip in this case? Any ideas
> of what it is missing?

Did the bridge driver probe? This function just checks lists of
registered panels and bridges.

Rob

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-06  0:01         ` Fabio Estevam
  0 siblings, 0 replies; 80+ messages in thread
From: Fabio Estevam @ 2017-02-06  0:01 UTC (permalink / raw)
  To: Rob Herring
  Cc: Marek Vasut, David Airlie, Daniel Vetter, Sean Paul,
	DRI mailing list, devicetree, linux-kernel, Frank Rowand,
	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, 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 Sun, Feb 5, 2017 at 8:25 PM, Rob Herring <robh@kernel.org> wrote:

> Did the bridge driver probe? This function just checks lists of
> registered panels and bridges.

The tda998x_probe() returns success, but tda998x_bind() is never called.

I am trying to understand what needs to be done in
drivers/gpu/drm/mxsfb/ so that it can bind the tda998x driver.

Thanks

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-06  0:01         ` Fabio Estevam
  0 siblings, 0 replies; 80+ messages in thread
From: Fabio Estevam @ 2017-02-06  0:01 UTC (permalink / raw)
  To: Rob Herring
  Cc: Marek Vasut, David Airlie, Daniel Vetter, Sean Paul,
	DRI mailing list, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel, Frank Rowand, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner

On Sun, Feb 5, 2017 at 8:25 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:

> Did the bridge driver probe? This function just checks lists of
> registered panels and bridges.

The tda998x_probe() returns success, but tda998x_bind() is never called.

I am trying to understand what needs to be done in
drivers/gpu/drm/mxsfb/ so that it can bind the tda998x driver.

Thanks
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-06  1:22           ` Fabio Estevam
  0 siblings, 0 replies; 80+ messages in thread
From: Fabio Estevam @ 2017-02-06  1:22 UTC (permalink / raw)
  To: Rob Herring
  Cc: Marek Vasut, David Airlie, Daniel Vetter, Sean Paul,
	DRI mailing list, devicetree, linux-kernel, Frank Rowand,
	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, 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 Sun, Feb 5, 2017 at 10:01 PM, Fabio Estevam <festevam@gmail.com> wrote:
>
> The tda998x_probe() returns success, but tda998x_bind() is never called.
>
> I am trying to understand what needs to be done in
> drivers/gpu/drm/mxsfb/ so that it can bind the tda998x driver.

Looks like that converting to component style and adding
component_bind_all() does the trick:

[    1.323772] tda998x 2-0070: found TDA19988
[    1.342381] mxsfb 2220000.lcdif: bound 2-0070 (ops tda998x_ops)

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-06  1:22           ` Fabio Estevam
  0 siblings, 0 replies; 80+ messages in thread
From: Fabio Estevam @ 2017-02-06  1:22 UTC (permalink / raw)
  To: Rob Herring
  Cc: Marek Vasut, David Airlie, Daniel Vetter, Sean Paul,
	DRI mailing list, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel, Frank Rowand, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner

On Sun, Feb 5, 2017 at 10:01 PM, Fabio Estevam <festevam-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
> The tda998x_probe() returns success, but tda998x_bind() is never called.
>
> I am trying to understand what needs to be done in
> drivers/gpu/drm/mxsfb/ so that it can bind the tda998x driver.

Looks like that converting to component style and adding
component_bind_all() does the trick:

[    1.323772] tda998x 2-0070: found TDA19988
[    1.342381] mxsfb 2220000.lcdif: bound 2-0070 (ops tda998x_ops)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06  8:31     ` Jyri Sarha
  0 siblings, 0 replies; 80+ messages in thread
From: Jyri Sarha @ 2017-02-06  8:31 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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, Tomi Valkeinen, Eric Anholt, Russell King

Thanks Rob, for nice cleanup, but ...

On 02/04/17 05:36, Rob Herring wrote:
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> index 6dfdb145f3bb..e74cc236a79b 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> @@ -1013,16 +1013,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, 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 c67d7cd7d57e..b7523dce4e8a 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> @@ -187,39 +187,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;
> @@ -227,7 +194,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;
>  
> @@ -266,35 +233,18 @@ 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))


> +	if (!match)
>  		return 0;

This will break tilcdc on setups that use the old tilcdc internal panel-
or tfp410- support. The driver uses tilcdc_get_external_components()
with match == NULL to check if the setup uses graph binding or legacy
internal panel/tfp410 support.

My intention is to get rid off the legacy internal encoder and connector
support (I even did that once already, but DRM had lot of infrastructure
changes in that area and my changes became obsolete), but we still need it.

>  
> -	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;

Simply remove the above mentioned if statement add and this here:
if (match)
> +	drm_of_component_match_add(dev, match, dev_match_of, node);
> +	of_node_put(node);
> +	return 1;
>  }

Best regards,
Jyri

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06  8:31     ` Jyri Sarha
  0 siblings, 0 replies; 80+ messages in thread
From: Jyri Sarha @ 2017-02-06  8:31 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

Thanks Rob, for nice cleanup, but ...

On 02/04/17 05:36, Rob Herring wrote:
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> index 6dfdb145f3bb..e74cc236a79b 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> @@ -1013,16 +1013,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, 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 c67d7cd7d57e..b7523dce4e8a 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> @@ -187,39 +187,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;
> @@ -227,7 +194,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;
>  
> @@ -266,35 +233,18 @@ 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))


> +	if (!match)
>  		return 0;

This will break tilcdc on setups that use the old tilcdc internal panel-
or tfp410- support. The driver uses tilcdc_get_external_components()
with match == NULL to check if the setup uses graph binding or legacy
internal panel/tfp410 support.

My intention is to get rid off the legacy internal encoder and connector
support (I even did that once already, but DRM had lot of infrastructure
changes in that area and my changes became obsolete), but we still need it.

>  
> -	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;

Simply remove the above mentioned if statement add and this here:
if (match)
> +	drm_of_component_match_add(dev, match, dev_match_of, node);
> +	of_node_put(node);
> +	return 1;
>  }

Best regards,
Jyri

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
  2017-02-04  3:36   ` Rob Herring
@ 2017-02-06  8:50     ` Daniel Vetter
  -1 siblings, 0 replies; 80+ messages in thread
From: Daniel Vetter @ 2017-02-06  8:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, Neil Armstrong,
	Liviu Dudau, dri-devel, Tomi Valkeinen, Frank Rowand,
	Marek Vasut, Kevin Hilman, Chen-Yu Tsai, Krzysztof Kozlowski,
	Xinliang Liu, Javier Martinez Canillas, Xinwei Kong, Kukjin Kim,
	Mali DP Maintainers, devicetree, Chen Feng, Jyri Sarha,
	Carlo Caione, Russell King, Matthias Brugger, Alison Wang,
	Jingoo Han, Seung-Woo Kim, linux-kernel, Kyungmin Park,
	Rongrong Zou, Maxime Ripard

On Fri, Feb 03, 2017 at 09:36:31PM -0600, Rob Herring wrote:
> The OF graph API leaves too much of the graph walking to clients when
> in many cases the driver doesn't care about accessing the port or
> endpoint nodes. The drivers typically just want the device connected via
> a particular graph connection. of_graph_get_remote_node provides this
> functionality.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>

Just a quick procedural comment: drm-misc for 4.11 is closed already, but
if we can get this core patch into 4.11 still then that would avoid
cross-tree sync pains in 4.12 ...
-Daniel

> ---
>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
>  include/linux/of_graph.h |  8 ++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d4bea3c797d6..ea18ab16b92c 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>  	return of_get_next_parent(np);
>  }
>  EXPORT_SYMBOL(of_graph_get_remote_port);
> +
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint)
> +{
> +	struct device_node *endpoint_node, *remote;
> +
> +	endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
> +	if (!endpoint_node) {
> +		pr_debug("no valid endpoint (%d, %d) for node %s\n",
> +			 port, endpoint, node->full_name);
> +		return NULL;
> +	}
> +
> +	remote = of_graph_get_remote_port_parent(endpoint_node);
> +	of_node_put(endpoint);
> +	if (!remote) {
> +		pr_debug("no valid remote node\n");
> +		return NULL;
> +	}
> +
> +	if (!of_device_is_available(remote)) {
> +		pr_debug("not available for remote node\n");
> +		return NULL;
> +	}
> +
> +	return remote;
> +}
> +EXPORT_SYMBOL(of_graph_get_remote_node);
> diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
> index bb3a5a2cd570..7b71d3e09209 100644
> --- a/include/linux/of_graph.h
> +++ b/include/linux/of_graph.h
> @@ -51,6 +51,8 @@ struct device_node *of_graph_get_endpoint_by_regs(
>  struct device_node *of_graph_get_remote_port_parent(
>  					const struct device_node *node);
>  struct device_node *of_graph_get_remote_port(const struct device_node *node);
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint);
>  #else
>  
>  static inline int of_graph_parse_endpoint(const struct device_node *node,
> @@ -89,6 +91,12 @@ static inline struct device_node *of_graph_get_remote_port(
>  {
>  	return NULL;
>  }
> +static inline struct device_node *of_graph_get_remote_node(
> +					const struct device_node *node,
> +					int port, int endpoint)
> +{
> +	return NULL;
> +}
>  
>  #endif /* CONFIG_OF */
>  
> -- 
> 2.10.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-06  8:50     ` Daniel Vetter
  0 siblings, 0 replies; 80+ messages in thread
From: Daniel Vetter @ 2017-02-06  8:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, Neil Armstrong,
	Liviu Dudau, dri-devel, Tomi Valkeinen, Frank Rowand,
	Marek Vasut, Kevin Hilman, Chen-Yu Tsai, Krzysztof Kozlowski,
	Xinliang Liu, Javier Martinez Canillas, Xinwei Kong, Kukjin Kim,
	Mali DP Maintainers, devicetree, Chen Feng, Jyri Sarha, Carlo

On Fri, Feb 03, 2017 at 09:36:31PM -0600, Rob Herring wrote:
> The OF graph API leaves too much of the graph walking to clients when
> in many cases the driver doesn't care about accessing the port or
> endpoint nodes. The drivers typically just want the device connected via
> a particular graph connection. of_graph_get_remote_node provides this
> functionality.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>

Just a quick procedural comment: drm-misc for 4.11 is closed already, but
if we can get this core patch into 4.11 still then that would avoid
cross-tree sync pains in 4.12 ...
-Daniel

> ---
>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
>  include/linux/of_graph.h |  8 ++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d4bea3c797d6..ea18ab16b92c 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>  	return of_get_next_parent(np);
>  }
>  EXPORT_SYMBOL(of_graph_get_remote_port);
> +
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint)
> +{
> +	struct device_node *endpoint_node, *remote;
> +
> +	endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
> +	if (!endpoint_node) {
> +		pr_debug("no valid endpoint (%d, %d) for node %s\n",
> +			 port, endpoint, node->full_name);
> +		return NULL;
> +	}
> +
> +	remote = of_graph_get_remote_port_parent(endpoint_node);
> +	of_node_put(endpoint);
> +	if (!remote) {
> +		pr_debug("no valid remote node\n");
> +		return NULL;
> +	}
> +
> +	if (!of_device_is_available(remote)) {
> +		pr_debug("not available for remote node\n");
> +		return NULL;
> +	}
> +
> +	return remote;
> +}
> +EXPORT_SYMBOL(of_graph_get_remote_node);
> diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
> index bb3a5a2cd570..7b71d3e09209 100644
> --- a/include/linux/of_graph.h
> +++ b/include/linux/of_graph.h
> @@ -51,6 +51,8 @@ struct device_node *of_graph_get_endpoint_by_regs(
>  struct device_node *of_graph_get_remote_port_parent(
>  					const struct device_node *node);
>  struct device_node *of_graph_get_remote_port(const struct device_node *node);
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint);
>  #else
>  
>  static inline int of_graph_parse_endpoint(const struct device_node *node,
> @@ -89,6 +91,12 @@ static inline struct device_node *of_graph_get_remote_port(
>  {
>  	return NULL;
>  }
> +static inline struct device_node *of_graph_get_remote_node(
> +					const struct device_node *node,
> +					int port, int endpoint)
> +{
> +	return NULL;
> +}
>  
>  #endif /* CONFIG_OF */
>  
> -- 
> 2.10.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-06 10:03     ` Maxime Ripard
  0 siblings, 0 replies; 80+ messages in thread
From: Maxime Ripard @ 2017-02-06 10:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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: 4871 bytes --]

Hi Rob,

On Fri, Feb 03, 2017 at 09:36:34PM -0600, 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>
> ---

[..]

> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index f5e86fe7750e..4720725b0fb0 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"
> @@ -217,12 +218,10 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	rgb->drv = drv;
>  	encoder = &rgb->encoder;
>  
> -	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> -		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
> -		return 0;
> -	}
> +	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> +					  &tcon->panel, &encoder->bridge);
> +	if (ret)
> +		return ret;

It used to ignore the error if it couldn't find the bridge. This will
break the probe.

>  
>  	drm_encoder_helper_add(&rgb->encoder,
>  			       &sun4i_rgb_enc_helper_funcs);
> @@ -239,7 +238,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,
> @@ -260,7 +259,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>  		}
>  	}
>  
> -	if (!IS_ERR(encoder->bridge)) {
> +	if (encoder->bridge) {
>  		encoder->bridge->encoder = &rgb->encoder;
>  
>  		ret = drm_bridge_attach(drm, encoder->bridge);
> @@ -268,8 +267,6 @@ int sun4i_rgb_init(struct drm_device *drm)
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
>  		}
> -	} else {
> -		encoder->bridge = NULL;
>  	}
>  
>  	return 0;
> 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);

And the panel is only one of our endpoints, which is optional, while
other endpoints are mandatory. This means that we might very well have
an endpoint that is not a panel or a bridge. In this case, I think
your function will return an error and will be treated as such, while
it's really the expected behaviour.

I think it's better to leave this driver alone for now, it's not as
trivial as it looks, and will require some testing to get things
right. I'll try to get my head around how to use your new (very
welcome) helpers.

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] 80+ messages in thread

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-06 10:03     ` Maxime Ripard
  0 siblings, 0 replies; 80+ messages in thread
From: Maxime Ripard @ 2017-02-06 10:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

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

Hi Rob,

On Fri, Feb 03, 2017 at 09:36:34PM -0600, 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---

[..]

> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index f5e86fe7750e..4720725b0fb0 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"
> @@ -217,12 +218,10 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	rgb->drv = drv;
>  	encoder = &rgb->encoder;
>  
> -	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> -		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
> -		return 0;
> -	}
> +	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> +					  &tcon->panel, &encoder->bridge);
> +	if (ret)
> +		return ret;

It used to ignore the error if it couldn't find the bridge. This will
break the probe.

>  
>  	drm_encoder_helper_add(&rgb->encoder,
>  			       &sun4i_rgb_enc_helper_funcs);
> @@ -239,7 +238,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,
> @@ -260,7 +259,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>  		}
>  	}
>  
> -	if (!IS_ERR(encoder->bridge)) {
> +	if (encoder->bridge) {
>  		encoder->bridge->encoder = &rgb->encoder;
>  
>  		ret = drm_bridge_attach(drm, encoder->bridge);
> @@ -268,8 +267,6 @@ int sun4i_rgb_init(struct drm_device *drm)
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
>  		}
> -	} else {
> -		encoder->bridge = NULL;
>  	}
>  
>  	return 0;
> 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);

And the panel is only one of our endpoints, which is optional, while
other endpoints are mandatory. This means that we might very well have
an endpoint that is not a panel or a bridge. In this case, I think
your function will return an error and will be treated as such, while
it's really the expected behaviour.

I think it's better to leave this driver alone for now, it's not as
trivial as it looks, and will require some testing to get things
right. I'll try to get my head around how to use your new (very
welcome) helpers.

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] 80+ messages in thread

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 10:17     ` Neil Armstrong
  0 siblings, 0 replies; 80+ messages in thread
From: Neil Armstrong @ 2017-02-06 10:17 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On 02/04/2017 04:36 AM, Rob Herring wrote:
> 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>
> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
>  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         | 27 +---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>  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_drv.c               | 12 ++---
>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>  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            | 11 +----
>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>  20 files changed, 64 insertions(+), 351 deletions(-)
> 
[...]
> diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
> index ff1f6019b97b..37cb9c755ed7 100644
> --- a/drivers/gpu/drm/meson/meson_drv.c
> +++ b/drivers/gpu/drm/meson/meson_drv.c
> @@ -163,14 +163,14 @@ static struct drm_driver meson_driver = {
>  
>  static bool meson_vpu_has_available_connectors(struct device *dev)
>  {
> -	struct device_node *ep, *remote;
> +	struct device_node *remote;
> +	int i;
>  
> -	/* Parses each endpoint and check if remote exists */
> -	for_each_endpoint_of_node(dev->of_node, ep) {
> -		/* If the endpoint node exists, consider it enabled */
> -		remote = of_graph_get_remote_port(ep);
> -		if (remote)
> +	for_each_of_graph_remote_node(dev->of_node, remote, i, 2) {
> +		if (remote) {
> +			of_node_put(remote);
>  			return true;
> +		}
>  	}
>  
>  	return false;
> 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)
[...]

Hi Rob,

For the meson changes :
Acked-by: Neil Armstrong <narmstrong@baylibre.com>

Thanks !
Neil

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 10:17     ` Neil Armstrong
  0 siblings, 0 replies; 80+ messages in thread
From: Neil Armstrong @ 2017-02-06 10:17 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On 02/04/2017 04:36 AM, Rob Herring wrote:
> 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
>  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         | 27 +---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>  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_drv.c               | 12 ++---
>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>  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            | 11 +----
>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>  20 files changed, 64 insertions(+), 351 deletions(-)
> 
[...]
> diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
> index ff1f6019b97b..37cb9c755ed7 100644
> --- a/drivers/gpu/drm/meson/meson_drv.c
> +++ b/drivers/gpu/drm/meson/meson_drv.c
> @@ -163,14 +163,14 @@ static struct drm_driver meson_driver = {
>  
>  static bool meson_vpu_has_available_connectors(struct device *dev)
>  {
> -	struct device_node *ep, *remote;
> +	struct device_node *remote;
> +	int i;
>  
> -	/* Parses each endpoint and check if remote exists */
> -	for_each_endpoint_of_node(dev->of_node, ep) {
> -		/* If the endpoint node exists, consider it enabled */
> -		remote = of_graph_get_remote_port(ep);
> -		if (remote)
> +	for_each_of_graph_remote_node(dev->of_node, remote, i, 2) {
> +		if (remote) {
> +			of_node_put(remote);
>  			return true;
> +		}
>  	}
>  
>  	return false;
> 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)
[...]

Hi Rob,

For the meson changes :
Acked-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>

Thanks !
Neil
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-06 10:18     ` Liviu Dudau
  0 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-06 10:18 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Fri, Feb 03, 2017 at 09:36:32PM -0600, 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>
> ---
>  drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_of.h     | 13 +++++++++++++
>  2 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b29ce2f52113 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -3,7 +3,9 @@
>  #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_panel.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> @@ -207,3 +209,51 @@ 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 input 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.
> + *
> + * 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 = -ENODEV;

Given that you never return 'ret' with -ENODEV can I suggest that you initialise 'ret'
with -EPROBE_DEFER and then you can get rid of the two assignments further down?

Otherwise, looks good to me.

Best regards,
Liviu

> +	struct device_node *remote;
> +
> +	remote = of_graph_get_remote_node(np, port, endpoint);
> +	if (!remote)
> +		return -ENODEV;
> +
> +	if (bridge)
> +		*bridge = NULL;
> +
> +	if (panel) {
> +		*panel = of_drm_find_panel(remote);
> +		if (*panel) {
> +			ret = 0;
> +			goto out_put;
> +		}
> +		ret = -EPROBE_DEFER;
> +	}
> +
> +	if (bridge) {
> +		*bridge = of_drm_find_bridge(remote);
> +		if (*bridge)
> +			ret = 0;
> +		else
> +			ret = -EPROBE_DEFER;
> +	}
> +out_put:
> +	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
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-06 10:18     ` Liviu Dudau
  0 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-06 10:18 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Fri, Feb 03, 2017 at 09:36:32PM -0600, 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_of.h     | 13 +++++++++++++
>  2 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b29ce2f52113 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -3,7 +3,9 @@
>  #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_panel.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> @@ -207,3 +209,51 @@ 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 input 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.
> + *
> + * 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 = -ENODEV;

Given that you never return 'ret' with -ENODEV can I suggest that you initialise 'ret'
with -EPROBE_DEFER and then you can get rid of the two assignments further down?

Otherwise, looks good to me.

Best regards,
Liviu

> +	struct device_node *remote;
> +
> +	remote = of_graph_get_remote_node(np, port, endpoint);
> +	if (!remote)
> +		return -ENODEV;
> +
> +	if (bridge)
> +		*bridge = NULL;
> +
> +	if (panel) {
> +		*panel = of_drm_find_panel(remote);
> +		if (*panel) {
> +			ret = 0;
> +			goto out_put;
> +		}
> +		ret = -EPROBE_DEFER;
> +	}
> +
> +	if (bridge) {
> +		*bridge = of_drm_find_bridge(remote);
> +		if (*bridge)
> +			ret = 0;
> +		else
> +			ret = -EPROBE_DEFER;
> +	}
> +out_put:
> +	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
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 10:29     ` Liviu Dudau
  0 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-06 10:29 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> 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>
> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
>  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         | 27 +---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>  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_drv.c               | 12 ++---
>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>  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            | 11 +----
>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>  20 files changed, 64 insertions(+), 351 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> index e5f4f4a6546d..0f70f5fe9970 100644
> --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> @@ -430,29 +430,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;

The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
test your changes on my setup to see how this affects having the encoder as a module.

> -	}
>  
>  	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 32f746e31379..bfa04be7f5de 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -262,7 +262,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);
> @@ -360,12 +359,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) {
> @@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
>  irq_init_fail:
>  	component_unbind_all(dev, drm);
>  bind_fail:
> -	of_node_put(malidp->crtc.port);

Why removing this line? AFAICT this is still needed, according to of_graph_get_port_by_id()
documentation.

>  	malidp->crtc.port = NULL;
> -port_fail:
>  	malidp_fini(drm);
>  init_fail:
>  	drm->dev_private = NULL;
> @@ -478,29 +470,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;
> -	}

This looks good for mali-dp as well (except above comment), I will give it a run through my setup.

Best regards,
Liviu

>  
>  	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 e5706981c934..47b4c99162ad 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 e07cb1fe4860..04528f512c91 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 a0def0be6d65..93ebb12133e1 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> @@ -228,29 +228,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;
> @@ -262,7 +239,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;
> @@ -279,7 +256,7 @@ static int parse_dt(struct exynos_mic *mic)
>  			break;
>  		case ENDPOINT_DSI_NODE:
>  			/* panel node */
> -			remote_node = get_remote_node(remote_node, 1);
> +			remote_node = of_graph_get_remote_node(remote_node, 1, 0);
>  			if (!remote_node) {
>  				ret = -EPIPE;
>  				goto exit;
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..4ed6b5fef3b7 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -757,34 +757,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 device_node *bridge_node;
>  	struct resource *res;
>  
>  	/*
>  	 * 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, 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/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> index ebd5f4fe4c23..18d6570e057d 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> @@ -247,34 +247,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;
> @@ -288,7 +260,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 90fb831ef031..dbd554c09a39 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 0e8c4d9af340..f14e472812ce 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1433,7 +1433,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;
> @@ -1485,29 +1485,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->bridge.next = of_drm_find_bridge(remote);
> diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
> index ff1f6019b97b..37cb9c755ed7 100644
> --- a/drivers/gpu/drm/meson/meson_drv.c
> +++ b/drivers/gpu/drm/meson/meson_drv.c
> @@ -163,14 +163,14 @@ static struct drm_driver meson_driver = {
>  
>  static bool meson_vpu_has_available_connectors(struct device *dev)
>  {
> -	struct device_node *ep, *remote;
> +	struct device_node *remote;
> +	int i;
>  
> -	/* Parses each endpoint and check if remote exists */
> -	for_each_endpoint_of_node(dev->of_node, ep) {
> -		/* If the endpoint node exists, consider it enabled */
> -		remote = of_graph_get_remote_port(ep);
> -		if (remote)
> +	for_each_of_graph_remote_node(dev->of_node, remote, i, 2) {
> +		if (remote) {
> +			of_node_put(remote);
>  			return true;
> +		}
>  	}
>  
>  	return false;
> 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 3819fdefcae2..da8619f9eb2e 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -1637,9 +1637,8 @@ 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_err(dev, "%s: no valid device\n", __func__);
>  		ret = -ENODEV;
>  		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 b782efd4b95f..9f36fad1915e 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)
> @@ -270,7 +244,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 2390c8577617..5e7ccd04ada6 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -373,19 +373,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);
> @@ -464,7 +458,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 6dfdb145f3bb..e74cc236a79b 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> @@ -1013,16 +1013,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, 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 c67d7cd7d57e..b7523dce4e8a 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> @@ -187,39 +187,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;
> @@ -227,7 +194,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;
>  
> @@ -266,35 +233,18 @@ 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))
> +	if (!match)
>  		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;
> +	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
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 10:29     ` Liviu Dudau
  0 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-06 10:29 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
>  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         | 27 +---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>  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_drv.c               | 12 ++---
>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>  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            | 11 +----
>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>  20 files changed, 64 insertions(+), 351 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> index e5f4f4a6546d..0f70f5fe9970 100644
> --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> @@ -430,29 +430,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;

The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
test your changes on my setup to see how this affects having the encoder as a module.

> -	}
>  
>  	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 32f746e31379..bfa04be7f5de 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -262,7 +262,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);
> @@ -360,12 +359,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) {
> @@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
>  irq_init_fail:
>  	component_unbind_all(dev, drm);
>  bind_fail:
> -	of_node_put(malidp->crtc.port);

Why removing this line? AFAICT this is still needed, according to of_graph_get_port_by_id()
documentation.

>  	malidp->crtc.port = NULL;
> -port_fail:
>  	malidp_fini(drm);
>  init_fail:
>  	drm->dev_private = NULL;
> @@ -478,29 +470,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;
> -	}

This looks good for mali-dp as well (except above comment), I will give it a run through my setup.

Best regards,
Liviu

>  
>  	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 e5706981c934..47b4c99162ad 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 e07cb1fe4860..04528f512c91 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 a0def0be6d65..93ebb12133e1 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> @@ -228,29 +228,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;
> @@ -262,7 +239,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;
> @@ -279,7 +256,7 @@ static int parse_dt(struct exynos_mic *mic)
>  			break;
>  		case ENDPOINT_DSI_NODE:
>  			/* panel node */
> -			remote_node = get_remote_node(remote_node, 1);
> +			remote_node = of_graph_get_remote_node(remote_node, 1, 0);
>  			if (!remote_node) {
>  				ret = -EPIPE;
>  				goto exit;
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..4ed6b5fef3b7 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -757,34 +757,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 device_node *bridge_node;
>  	struct resource *res;
>  
>  	/*
>  	 * 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, 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/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> index ebd5f4fe4c23..18d6570e057d 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> @@ -247,34 +247,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;
> @@ -288,7 +260,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 90fb831ef031..dbd554c09a39 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 0e8c4d9af340..f14e472812ce 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1433,7 +1433,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;
> @@ -1485,29 +1485,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->bridge.next = of_drm_find_bridge(remote);
> diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
> index ff1f6019b97b..37cb9c755ed7 100644
> --- a/drivers/gpu/drm/meson/meson_drv.c
> +++ b/drivers/gpu/drm/meson/meson_drv.c
> @@ -163,14 +163,14 @@ static struct drm_driver meson_driver = {
>  
>  static bool meson_vpu_has_available_connectors(struct device *dev)
>  {
> -	struct device_node *ep, *remote;
> +	struct device_node *remote;
> +	int i;
>  
> -	/* Parses each endpoint and check if remote exists */
> -	for_each_endpoint_of_node(dev->of_node, ep) {
> -		/* If the endpoint node exists, consider it enabled */
> -		remote = of_graph_get_remote_port(ep);
> -		if (remote)
> +	for_each_of_graph_remote_node(dev->of_node, remote, i, 2) {
> +		if (remote) {
> +			of_node_put(remote);
>  			return true;
> +		}
>  	}
>  
>  	return false;
> 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 3819fdefcae2..da8619f9eb2e 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -1637,9 +1637,8 @@ 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_err(dev, "%s: no valid device\n", __func__);
>  		ret = -ENODEV;
>  		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 b782efd4b95f..9f36fad1915e 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)
> @@ -270,7 +244,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 2390c8577617..5e7ccd04ada6 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -373,19 +373,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);
> @@ -464,7 +458,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 6dfdb145f3bb..e74cc236a79b 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> @@ -1013,16 +1013,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, 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 c67d7cd7d57e..b7523dce4e8a 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> @@ -187,39 +187,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;
> @@ -227,7 +194,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;
>  
> @@ -266,35 +233,18 @@ 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))
> +	if (!match)
>  		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;
> +	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
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-06 10:32     ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 10:32 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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

Hi Rob,

thanks for this clean-up series! I was not aware how far the duplication
has spread over time.

On Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
> The OF graph API leaves too much of the graph walking to clients when
> in many cases the driver doesn't care about accessing the port or
> endpoint nodes. The drivers typically just want the device connected via
> a particular graph connection. of_graph_get_remote_node provides this
> functionality.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
>  include/linux/of_graph.h |  8 ++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d4bea3c797d6..ea18ab16b92c 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>  	return of_get_next_parent(np);
>  }
>  EXPORT_SYMBOL(of_graph_get_remote_port);
> +
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint)

I think this should have a documentation comment, similar to the
of_graph_get_endpoint_by_regs one, as it is not really clear from the
function name that the returned device node is the parent (or
grandparent) device node containing the remote port to the specified
node & port & endpoint.
Also it might be interesting to the user that -1 is a wildcard value for
port / endpoint.

> +{
> +	struct device_node *endpoint_node, *remote;
> +
> +	endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
> +	if (!endpoint_node) {
> +		pr_debug("no valid endpoint (%d, %d) for node %s\n",
> +			 port, endpoint, node->full_name);
> +		return NULL;
> +	}
> +
> +	remote = of_graph_get_remote_port_parent(endpoint_node);
> +	of_node_put(endpoint);

Vladimir pointed this out already. With that fixed and the missing doc
comment added,
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>

> +	if (!remote) {
> +		pr_debug("no valid remote node\n");
> +		return NULL;
> +	}
> +
> +	if (!of_device_is_available(remote)) {
> +		pr_debug("not available for remote node\n");
> +		return NULL;
> +	}
> +
> +	return remote;
> +}
> +EXPORT_SYMBOL(of_graph_get_remote_node);
> diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
> index bb3a5a2cd570..7b71d3e09209 100644
> --- a/include/linux/of_graph.h
> +++ b/include/linux/of_graph.h
> @@ -51,6 +51,8 @@ struct device_node *of_graph_get_endpoint_by_regs(
>  struct device_node *of_graph_get_remote_port_parent(
>  					const struct device_node *node);
>  struct device_node *of_graph_get_remote_port(const struct device_node *node);
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint);
>  #else
>  
>  static inline int of_graph_parse_endpoint(const struct device_node *node,
> @@ -89,6 +91,12 @@ static inline struct device_node *of_graph_get_remote_port(
>  {
>  	return NULL;
>  }
> +static inline struct device_node *of_graph_get_remote_node(
> +					const struct device_node *node,
> +					int port, int endpoint)
> +{
> +	return NULL;
> +}
>  
>  #endif /* CONFIG_OF */

regards
Philipp

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-06 10:32     ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 10:32 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

Hi Rob,

thanks for this clean-up series! I was not aware how far the duplication
has spread over time.

On Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
> The OF graph API leaves too much of the graph walking to clients when
> in many cases the driver doesn't care about accessing the port or
> endpoint nodes. The drivers typically just want the device connected via
> a particular graph connection. of_graph_get_remote_node provides this
> functionality.
> 
> Signed-off-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
>  include/linux/of_graph.h |  8 ++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d4bea3c797d6..ea18ab16b92c 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>  	return of_get_next_parent(np);
>  }
>  EXPORT_SYMBOL(of_graph_get_remote_port);
> +
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint)

I think this should have a documentation comment, similar to the
of_graph_get_endpoint_by_regs one, as it is not really clear from the
function name that the returned device node is the parent (or
grandparent) device node containing the remote port to the specified
node & port & endpoint.
Also it might be interesting to the user that -1 is a wildcard value for
port / endpoint.

> +{
> +	struct device_node *endpoint_node, *remote;
> +
> +	endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
> +	if (!endpoint_node) {
> +		pr_debug("no valid endpoint (%d, %d) for node %s\n",
> +			 port, endpoint, node->full_name);
> +		return NULL;
> +	}
> +
> +	remote = of_graph_get_remote_port_parent(endpoint_node);
> +	of_node_put(endpoint);

Vladimir pointed this out already. With that fixed and the missing doc
comment added,
Acked-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

> +	if (!remote) {
> +		pr_debug("no valid remote node\n");
> +		return NULL;
> +	}
> +
> +	if (!of_device_is_available(remote)) {
> +		pr_debug("not available for remote node\n");
> +		return NULL;
> +	}
> +
> +	return remote;
> +}
> +EXPORT_SYMBOL(of_graph_get_remote_node);
> diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
> index bb3a5a2cd570..7b71d3e09209 100644
> --- a/include/linux/of_graph.h
> +++ b/include/linux/of_graph.h
> @@ -51,6 +51,8 @@ struct device_node *of_graph_get_endpoint_by_regs(
>  struct device_node *of_graph_get_remote_port_parent(
>  					const struct device_node *node);
>  struct device_node *of_graph_get_remote_port(const struct device_node *node);
> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> +					     int port, int endpoint);
>  #else
>  
>  static inline int of_graph_parse_endpoint(const struct device_node *node,
> @@ -89,6 +91,12 @@ static inline struct device_node *of_graph_get_remote_port(
>  {
>  	return NULL;
>  }
> +static inline struct device_node *of_graph_get_remote_node(
> +					const struct device_node *node,
> +					int port, int endpoint)
> +{
> +	return NULL;
> +}
>  
>  #endif /* CONFIG_OF */

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-06 10:42     ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 10:42 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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 Fri, 2017-02-03 at 21:36 -0600, 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>
> ---
>  drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_of.h     | 13 +++++++++++++
>  2 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b29ce2f52113 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -3,7 +3,9 @@
>  #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_panel.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> @@ -207,3 +209,51 @@ 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 input 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.

Add a commend that at least one of panel, bridge must be set?

> + * 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 = -ENODEV;

This is only returned if !panel && !bridge. I'd consider this invalid
usage of this function, so maybe use -EINVAL?

> +	struct device_node *remote;
> +
> +	remote = of_graph_get_remote_node(np, port, endpoint);
> +	if (!remote)
> +		return -ENODEV;
> +
> +	if (bridge)
> +		*bridge = NULL;

I would move this ^ ...

> +	if (panel) {
> +		*panel = of_drm_find_panel(remote);
> +		if (*panel) {

... here.

> +			ret = 0;
> +			goto out_put;
> +		}
> +		ret = -EPROBE_DEFER;
> +	}
> +
> +	if (bridge) {
> +		*bridge = of_drm_find_bridge(remote);
> +		if (*bridge)
> +			ret = 0;
> +		else
> +			ret = -EPROBE_DEFER;
> +	}
> +out_put:
> +	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,

regards
Philipp

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-06 10:42     ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 10:42 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Fri, 2017-02-03 at 21:36 -0600, 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_of.h     | 13 +++++++++++++
>  2 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b29ce2f52113 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -3,7 +3,9 @@
>  #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_panel.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> @@ -207,3 +209,51 @@ 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 input 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.

Add a commend that at least one of panel, bridge must be set?

> + * 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 = -ENODEV;

This is only returned if !panel && !bridge. I'd consider this invalid
usage of this function, so maybe use -EINVAL?

> +	struct device_node *remote;
> +
> +	remote = of_graph_get_remote_node(np, port, endpoint);
> +	if (!remote)
> +		return -ENODEV;
> +
> +	if (bridge)
> +		*bridge = NULL;

I would move this ^ ...

> +	if (panel) {
> +		*panel = of_drm_find_panel(remote);
> +		if (*panel) {

... here.

> +			ret = 0;
> +			goto out_put;
> +		}
> +		ret = -EPROBE_DEFER;
> +	}
> +
> +	if (bridge) {
> +		*bridge = of_drm_find_bridge(remote);
> +		if (*bridge)
> +			ret = 0;
> +		else
> +			ret = -EPROBE_DEFER;
> +	}
> +out_put:
> +	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,

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 10:52     ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 10:52 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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 Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
> 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>
> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
>  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         | 27 +---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>  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_drv.c               | 12 ++---
>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>  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            | 11 +----
>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>  20 files changed, 64 insertions(+), 351 deletions(-)
> 
[...] 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 90fb831ef031..dbd554c09a39 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);

Note that before this change, of_graph_get_next_endpoint would just
choose the first port/endpoint without restrictions to their reg
properties, whereas the new code requires reg to be either not set or
set to zero.
As the former is the case for the mt8173 dpi->hdmi link, which is the
only use of this driver, this should be fine.

[...]
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 0e8c4d9af340..f14e472812ce 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1433,7 +1433,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;
> @@ -1485,29 +1485,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);

Same as above. TMDS links reasonably have only one endpoint in the
source port, and the mt8173-evb DT has no reg property set.

Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
for the mediatek changes.

regards
Philipp

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 10:52     ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 10:52 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
> 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
>  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         | 27 +---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>  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_drv.c               | 12 ++---
>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>  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            | 11 +----
>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>  20 files changed, 64 insertions(+), 351 deletions(-)
> 
[...] 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 90fb831ef031..dbd554c09a39 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);

Note that before this change, of_graph_get_next_endpoint would just
choose the first port/endpoint without restrictions to their reg
properties, whereas the new code requires reg to be either not set or
set to zero.
As the former is the case for the mt8173 dpi->hdmi link, which is the
only use of this driver, this should be fine.

[...]
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 0e8c4d9af340..f14e472812ce 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1433,7 +1433,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;
> @@ -1485,29 +1485,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);

Same as above. TMDS links reasonably have only one endpoint in the
source port, and the mt8173-evb DT has no reg property set.

Acked-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
for the mediatek changes.

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-06 11:07     ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 11:07 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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 Fri, 2017-02-03 at 21:36 -0600, 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>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 64 ++++-------------
>  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        | 49 ++++---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     |  5 +-
>  drivers/gpu/drm/imx/imx-ldb.c                    | 28 ++------
>  drivers/gpu/drm/imx/parallel-display.c           | 35 ++-------
>  drivers/gpu/drm/mediatek/mtk_dsi.c               | 23 ++----
>  drivers/gpu/drm/mxsfb/mxsfb_out.c                | 36 ++--------
>  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  | 26 ++-----
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                | 17 ++---
>  drivers/gpu/drm/sun4i/sun4i_tcon.c               | 90 ++----------------------
>  14 files changed, 88 insertions(+), 379 deletions(-)
> 
[...]
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index 516d06490465..e670993906b8 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -649,7 +649,7 @@ 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;
> +		struct device_node *remote;
>  		int bus_format;
>  
>  		ret = of_property_read_u32(child, "reg", &i);
> @@ -673,27 +673,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(fsl_dev->np,

s/fsl_dev->np/child/

> +						  imx_ldb->lvds_mux ? 4 : 2, 0,

Same comment as for the mediatek changes, this now requires that the
endpoints have no reg property set or reg = <0>. This is fine for LVDS
links, and I am not aware of any device trees that set the reg propertiy
in their LVDS output endpoints, so that should be fine.

> +						  &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 8582a83c0d9b..eb3a0201853a 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -210,7 +210,7 @@ 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;
> +	struct device_node *remote;
>  	const u8 *edidp;
>  	struct imx_parallel_display *imxpd;
>  	int ret;
> @@ -239,36 +239,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;

The parallel-display change looks good to me.

> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 2c42f90809d8..14140579f8d4 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>
> @@ -819,7 +819,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;
> @@ -831,22 +830,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;

Looks fine and also fixes a missing of_node_put on the endpoint node.

regards
Philipp

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-06 11:07     ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 11:07 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Fri, 2017-02-03 at 21:36 -0600, 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 64 ++++-------------
>  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        | 49 ++++---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c     |  5 +-
>  drivers/gpu/drm/imx/imx-ldb.c                    | 28 ++------
>  drivers/gpu/drm/imx/parallel-display.c           | 35 ++-------
>  drivers/gpu/drm/mediatek/mtk_dsi.c               | 23 ++----
>  drivers/gpu/drm/mxsfb/mxsfb_out.c                | 36 ++--------
>  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c  | 26 ++-----
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                | 17 ++---
>  drivers/gpu/drm/sun4i/sun4i_tcon.c               | 90 ++----------------------
>  14 files changed, 88 insertions(+), 379 deletions(-)
> 
[...]
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index 516d06490465..e670993906b8 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -649,7 +649,7 @@ 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;
> +		struct device_node *remote;
>  		int bus_format;
>  
>  		ret = of_property_read_u32(child, "reg", &i);
> @@ -673,27 +673,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(fsl_dev->np,

s/fsl_dev->np/child/

> +						  imx_ldb->lvds_mux ? 4 : 2, 0,

Same comment as for the mediatek changes, this now requires that the
endpoints have no reg property set or reg = <0>. This is fine for LVDS
links, and I am not aware of any device trees that set the reg propertiy
in their LVDS output endpoints, so that should be fine.

> +						  &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 8582a83c0d9b..eb3a0201853a 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -210,7 +210,7 @@ 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;
> +	struct device_node *remote;
>  	const u8 *edidp;
>  	struct imx_parallel_display *imxpd;
>  	int ret;
> @@ -239,36 +239,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;

The parallel-display change looks good to me.

> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 2c42f90809d8..14140579f8d4 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>
> @@ -819,7 +819,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;
> @@ -831,22 +830,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;

Looks fine and also fixes a missing of_node_put on the endpoint node.

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
  2017-02-06 10:52     ` Philipp Zabel
@ 2017-02-06 13:40       ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 13:40 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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 Mon, Feb 6, 2017 at 4:52 AM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> On Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
>> 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>
>> ---
>>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
>>  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         | 27 +---------
>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>>  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_drv.c               | 12 ++---
>>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>>  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            | 11 +----
>>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>>  20 files changed, 64 insertions(+), 351 deletions(-)
>>
> [...]
>> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
>> index 90fb831ef031..dbd554c09a39 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);
>
> Note that before this change, of_graph_get_next_endpoint would just
> choose the first port/endpoint without restrictions to their reg
> properties, whereas the new code requires reg to be either not set or
> set to zero.
> As the former is the case for the mt8173 dpi->hdmi link, which is the
> only use of this driver, this should be fine.

Yes, that is on purpose. A given node should have known port numbering
and know what type of port each port is. The binding doc should
outline the ports and endpoints.

>
> [...]
>> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> index 0e8c4d9af340..f14e472812ce 100644
>> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> @@ -1433,7 +1433,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;
>> @@ -1485,29 +1485,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);
>
> Same as above. TMDS links reasonably have only one endpoint in the
> source port, and the mt8173-evb DT has no reg property set.
>
> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> for the mediatek changes.

Thanks.

Rob

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 13:40       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 13:40 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner

On Mon, Feb 6, 2017 at 4:52 AM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> On Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
>> 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>
>> ---
>>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
>>  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         | 27 +---------
>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>>  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_drv.c               | 12 ++---
>>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>>  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            | 11 +----
>>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>>  20 files changed, 64 insertions(+), 351 deletions(-)
>>
> [...]
>> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
>> index 90fb831ef031..dbd554c09a39 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);
>
> Note that before this change, of_graph_get_next_endpoint would just
> choose the first port/endpoint without restrictions to their reg
> properties, whereas the new code requires reg to be either not set or
> set to zero.
> As the former is the case for the mt8173 dpi->hdmi link, which is the
> only use of this driver, this should be fine.

Yes, that is on purpose. A given node should have known port numbering
and know what type of port each port is. The binding doc should
outline the ports and endpoints.

>
> [...]
>> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> index 0e8c4d9af340..f14e472812ce 100644
>> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> @@ -1433,7 +1433,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;
>> @@ -1485,29 +1485,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);
>
> Same as above. TMDS links reasonably have only one endpoint in the
> source port, and the mt8173-evb DT has no reg property set.
>
> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> for the mediatek changes.

Thanks.

Rob

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
  2017-02-06  8:50     ` Daniel Vetter
@ 2017-02-06 13:41       ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 13:41 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul,
	Neil Armstrong, Liviu Dudau, dri-devel, Tomi Valkeinen,
	Frank Rowand, Marek Vasut, Kevin Hilman, Chen-Yu Tsai,
	Krzysztof Kozlowski, Xinliang Liu, Javier Martinez Canillas,
	Xinwei Kong, Kukjin Kim, Mali DP Maintainers, devicetree,
	Chen Feng, Jyri Sarha, Carlo Caione, Russell King,
	Matthias Brugger, Alison Wang, Jingoo Han, Seung-Woo Kim,
	linux-kernel, Kyungmin Park, Rongrong Zou, Maxime Ripard

On Mon, Feb 6, 2017 at 2:50 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Fri, Feb 03, 2017 at 09:36:31PM -0600, Rob Herring wrote:
>> The OF graph API leaves too much of the graph walking to clients when
>> in many cases the driver doesn't care about accessing the port or
>> endpoint nodes. The drivers typically just want the device connected via
>> a particular graph connection. of_graph_get_remote_node provides this
>> functionality.
>>
>> Signed-off-by: Rob Herring <robh@kernel.org>
>
> Just a quick procedural comment: drm-misc for 4.11 is closed already, but
> if we can get this core patch into 4.11 still then that would avoid
> cross-tree sync pains in 4.12 ...

Right, I was thinking the same thing.

Rob

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-06 13:41       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 13:41 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul,
	Neil Armstrong, Liviu Dudau, dri-devel, Tomi Valkeinen,
	Frank Rowand, Marek Vasut, Kevin Hilman, Chen-Yu Tsai,
	Krzysztof Kozlowski, Xinliang Liu, Javier Martinez Canillas,
	Xinwei Kong, Kukjin Kim, Mali DP Maintainers, devicetree

On Mon, Feb 6, 2017 at 2:50 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Fri, Feb 03, 2017 at 09:36:31PM -0600, Rob Herring wrote:
>> The OF graph API leaves too much of the graph walking to clients when
>> in many cases the driver doesn't care about accessing the port or
>> endpoint nodes. The drivers typically just want the device connected via
>> a particular graph connection. of_graph_get_remote_node provides this
>> functionality.
>>
>> Signed-off-by: Rob Herring <robh@kernel.org>
>
> Just a quick procedural comment: drm-misc for 4.11 is closed already, but
> if we can get this core patch into 4.11 still then that would avoid
> cross-tree sync pains in 4.12 ...

Right, I was thinking the same thing.

Rob

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
  2017-02-06 10:32     ` Philipp Zabel
@ 2017-02-06 13:54       ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 13:54 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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 Mon, Feb 6, 2017 at 4:32 AM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> Hi Rob,
>
> thanks for this clean-up series! I was not aware how far the duplication
> has spread over time.
>
> On Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
>> The OF graph API leaves too much of the graph walking to clients when
>> in many cases the driver doesn't care about accessing the port or
>> endpoint nodes. The drivers typically just want the device connected via
>> a particular graph connection. of_graph_get_remote_node provides this
>> functionality.
>>
>> Signed-off-by: Rob Herring <robh@kernel.org>
>> ---
>>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
>>  include/linux/of_graph.h |  8 ++++++++
>>  2 files changed, 36 insertions(+)
>>
>> diff --git a/drivers/of/base.c b/drivers/of/base.c
>> index d4bea3c797d6..ea18ab16b92c 100644
>> --- a/drivers/of/base.c
>> +++ b/drivers/of/base.c
>> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>>       return of_get_next_parent(np);
>>  }
>>  EXPORT_SYMBOL(of_graph_get_remote_port);
>> +
>> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
>> +                                          int port, int endpoint)
>
> I think this should have a documentation comment, similar to the
> of_graph_get_endpoint_by_regs one, as it is not really clear from the
> function name that the returned device node is the parent (or
> grandparent) device node containing the remote port to the specified
> node & port & endpoint.
> Also it might be interesting to the user that -1 is a wildcard value for
> port / endpoint.

I really want to not allow using a wildcard here. Drivers should know
what port they want (or iterate over all of them). It didn't look like
any drivers were depending on the wildcard, but were just using -1 for
"no reg property" when really that should 0. Of course, I may have
missed something.

I guess I could enforce port/endpoint > 0 here as there's no existing users.

Rob

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-06 13:54       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 13:54 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, Boris Brezillon, Archit Taneja,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Kukjin Kim, Krzysztof Kozlowski,
	Javier Martinez Canillas, Stefan Agner

On Mon, Feb 6, 2017 at 4:32 AM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> Hi Rob,
>
> thanks for this clean-up series! I was not aware how far the duplication
> has spread over time.
>
> On Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
>> The OF graph API leaves too much of the graph walking to clients when
>> in many cases the driver doesn't care about accessing the port or
>> endpoint nodes. The drivers typically just want the device connected via
>> a particular graph connection. of_graph_get_remote_node provides this
>> functionality.
>>
>> Signed-off-by: Rob Herring <robh@kernel.org>
>> ---
>>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
>>  include/linux/of_graph.h |  8 ++++++++
>>  2 files changed, 36 insertions(+)
>>
>> diff --git a/drivers/of/base.c b/drivers/of/base.c
>> index d4bea3c797d6..ea18ab16b92c 100644
>> --- a/drivers/of/base.c
>> +++ b/drivers/of/base.c
>> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>>       return of_get_next_parent(np);
>>  }
>>  EXPORT_SYMBOL(of_graph_get_remote_port);
>> +
>> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
>> +                                          int port, int endpoint)
>
> I think this should have a documentation comment, similar to the
> of_graph_get_endpoint_by_regs one, as it is not really clear from the
> function name that the returned device node is the parent (or
> grandparent) device node containing the remote port to the specified
> node & port & endpoint.
> Also it might be interesting to the user that -1 is a wildcard value for
> port / endpoint.

I really want to not allow using a wildcard here. Drivers should know
what port they want (or iterate over all of them). It didn't look like
any drivers were depending on the wildcard, but were just using -1 for
"no reg property" when really that should 0. Of course, I may have
missed something.

I guess I could enforce port/endpoint > 0 here as there's no existing users.

Rob

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-06 14:03         ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 14:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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 Mon, 2017-02-06 at 07:54 -0600, Rob Herring wrote:
> On Mon, Feb 6, 2017 at 4:32 AM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> > Hi Rob,
> >
> > thanks for this clean-up series! I was not aware how far the duplication
> > has spread over time.
> >
> > On Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
> >> The OF graph API leaves too much of the graph walking to clients when
> >> in many cases the driver doesn't care about accessing the port or
> >> endpoint nodes. The drivers typically just want the device connected via
> >> a particular graph connection. of_graph_get_remote_node provides this
> >> functionality.
> >>
> >> Signed-off-by: Rob Herring <robh@kernel.org>
> >> ---
> >>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
> >>  include/linux/of_graph.h |  8 ++++++++
> >>  2 files changed, 36 insertions(+)
> >>
> >> diff --git a/drivers/of/base.c b/drivers/of/base.c
> >> index d4bea3c797d6..ea18ab16b92c 100644
> >> --- a/drivers/of/base.c
> >> +++ b/drivers/of/base.c
> >> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
> >>       return of_get_next_parent(np);
> >>  }
> >>  EXPORT_SYMBOL(of_graph_get_remote_port);
> >> +
> >> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> >> +                                          int port, int endpoint)
> >
> > I think this should have a documentation comment, similar to the
> > of_graph_get_endpoint_by_regs one, as it is not really clear from the
> > function name that the returned device node is the parent (or
> > grandparent) device node containing the remote port to the specified
> > node & port & endpoint.
> > Also it might be interesting to the user that -1 is a wildcard value for
> > port / endpoint.
> 
> I really want to not allow using a wildcard here. Drivers should know
> what port they want (or iterate over all of them). It didn't look like
> any drivers were depending on the wildcard, but were just using -1 for
> "no reg property" when really that should 0. Of course, I may have
> missed something.
> 
> I guess I could enforce port/endpoint > 0 here as there's no existing users.

That sounds reasonable. If it works for all users, enforcing >= 0 should
be fine, but in that case I'd change the parameters to be unsigned.

regards
Philipp

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

* Re: [PATCH 1/5] of: introduce of_graph_get_remote_node
@ 2017-02-06 14:03         ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 14:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	Boris Brezillon, Archit Taneja, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Stefan Agner

On Mon, 2017-02-06 at 07:54 -0600, Rob Herring wrote:
> On Mon, Feb 6, 2017 at 4:32 AM, Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> wrote:
> > Hi Rob,
> >
> > thanks for this clean-up series! I was not aware how far the duplication
> > has spread over time.
> >
> > On Fri, 2017-02-03 at 21:36 -0600, Rob Herring wrote:
> >> The OF graph API leaves too much of the graph walking to clients when
> >> in many cases the driver doesn't care about accessing the port or
> >> endpoint nodes. The drivers typically just want the device connected via
> >> a particular graph connection. of_graph_get_remote_node provides this
> >> functionality.
> >>
> >> Signed-off-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> >> ---
> >>  drivers/of/base.c        | 28 ++++++++++++++++++++++++++++
> >>  include/linux/of_graph.h |  8 ++++++++
> >>  2 files changed, 36 insertions(+)
> >>
> >> diff --git a/drivers/of/base.c b/drivers/of/base.c
> >> index d4bea3c797d6..ea18ab16b92c 100644
> >> --- a/drivers/of/base.c
> >> +++ b/drivers/of/base.c
> >> @@ -2469,3 +2469,31 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
> >>       return of_get_next_parent(np);
> >>  }
> >>  EXPORT_SYMBOL(of_graph_get_remote_port);
> >> +
> >> +struct device_node *of_graph_get_remote_node(const struct device_node *node,
> >> +                                          int port, int endpoint)
> >
> > I think this should have a documentation comment, similar to the
> > of_graph_get_endpoint_by_regs one, as it is not really clear from the
> > function name that the returned device node is the parent (or
> > grandparent) device node containing the remote port to the specified
> > node & port & endpoint.
> > Also it might be interesting to the user that -1 is a wildcard value for
> > port / endpoint.
> 
> I really want to not allow using a wildcard here. Drivers should know
> what port they want (or iterate over all of them). It didn't look like
> any drivers were depending on the wildcard, but were just using -1 for
> "no reg property" when really that should 0. Of course, I may have
> missed something.
> 
> I guess I could enforce port/endpoint > 0 here as there's no existing users.

That sounds reasonable. If it works for all users, enforcing >= 0 should
be fine, but in that case I'd change the parameters to be unsigned.

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-06 16:20       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 16:20 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Mon, Feb 6, 2017 at 4:18 AM, Liviu Dudau <liviu.dudau@arm.com> wrote:
> On Fri, Feb 03, 2017 at 09:36:32PM -0600, 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>
>> ---
>>  drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/drm/drm_of.h     | 13 +++++++++++++
>>  2 files changed, 63 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
>> index 47848ed8ca48..b29ce2f52113 100644
>> --- a/drivers/gpu/drm/drm_of.c
>> +++ b/drivers/gpu/drm/drm_of.c
>> @@ -3,7 +3,9 @@
>>  #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_panel.h>
>>  #include <drm/drm_of.h>
>>
>>  static void drm_release_of(struct device *dev, void *data)
>> @@ -207,3 +209,51 @@ 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 input 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.
>> + *
>> + * 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 = -ENODEV;
>
> Given that you never return 'ret' with -ENODEV can I suggest that you initialise 'ret'
> with -EPROBE_DEFER and then you can get rid of the two assignments further down?

But I can if both panel and bridge are NULL. I'm going with Philipp's
suggestion of -EINVAL here.

Rob

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-06 16:20       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 16:20 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	Boris Brezillon, Archit Taneja, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Stefan Agner

On Mon, Feb 6, 2017 at 4:18 AM, Liviu Dudau <liviu.dudau-5wv7dgnIgG8@public.gmane.org> wrote:
> On Fri, Feb 03, 2017 at 09:36:32PM -0600, 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>> ---
>>  drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/drm/drm_of.h     | 13 +++++++++++++
>>  2 files changed, 63 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
>> index 47848ed8ca48..b29ce2f52113 100644
>> --- a/drivers/gpu/drm/drm_of.c
>> +++ b/drivers/gpu/drm/drm_of.c
>> @@ -3,7 +3,9 @@
>>  #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_panel.h>
>>  #include <drm/drm_of.h>
>>
>>  static void drm_release_of(struct device *dev, void *data)
>> @@ -207,3 +209,51 @@ 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 input 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.
>> + *
>> + * 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 = -ENODEV;
>
> Given that you never return 'ret' with -ENODEV can I suggest that you initialise 'ret'
> with -EPROBE_DEFER and then you can get rid of the two assignments further down?

But I can if both panel and bridge are NULL. I'm going with Philipp's
suggestion of -EINVAL here.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-06 16:53       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 16:53 UTC (permalink / raw)
  To: Philipp Zabel, Liviu Dudau
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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, Mali DP Maintainers, Neil Armstrong,
	Carlo Caione, Kevin Hilman, Rob Clark, Jyri Sarha,
	Tomi Valkeinen, Eric Anholt, Russell King

On Mon, Feb 06, 2017 at 11:42:48AM +0100, Philipp Zabel wrote:
> On Fri, 2017-02-03 at 21:36 -0600, 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.

[...]

> > +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 = -ENODEV;
> 
> This is only returned if !panel && !bridge. I'd consider this invalid
> usage of this function, so maybe use -EINVAL?

Yes.

> > +	struct device_node *remote;
> > +
> > +	remote = of_graph_get_remote_node(np, port, endpoint);
> > +	if (!remote)
> > +		return -ENODEV;
> > +
> > +	if (bridge)
> > +		*bridge = NULL;
> 
> I would move this ^ ...
> 
> > +	if (panel) {
> > +		*panel = of_drm_find_panel(remote);
> > +		if (*panel) {
> 
> ... here.

Okay.

> > +			ret = 0;
> > +			goto out_put;
> > +		}
> > +		ret = -EPROBE_DEFER;
> > +	}
> > +
> > +	if (bridge) {
> > +		*bridge = of_drm_find_bridge(remote);
> > +		if (*bridge)
> > +			ret = 0;
> > +		else
> > +			ret = -EPROBE_DEFER;
> > +	}
> > +out_put:
> > +	of_node_put(remote);
> > +	return ret;
> > +}

I've ended up re-writing things a bit getting rid of the goto and the 
result looks like this:

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) {
			if (bridge)
				*bridge = NULL;
			ret = 0;
		}
	}

	/* No panel found yet, check for a bridge next. */
	if (ret && bridge) {
		*bridge = of_drm_find_bridge(remote);
		if (*bridge)
			ret = 0;
	}

	of_node_put(remote);
	return ret;
}

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-06 16:53       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 16:53 UTC (permalink / raw)
  To: Philipp Zabel, Liviu Dudau
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Mon, Feb 06, 2017 at 11:42:48AM +0100, Philipp Zabel wrote:
> On Fri, 2017-02-03 at 21:36 -0600, 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.

[...]

> > +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 = -ENODEV;
> 
> This is only returned if !panel && !bridge. I'd consider this invalid
> usage of this function, so maybe use -EINVAL?

Yes.

> > +	struct device_node *remote;
> > +
> > +	remote = of_graph_get_remote_node(np, port, endpoint);
> > +	if (!remote)
> > +		return -ENODEV;
> > +
> > +	if (bridge)
> > +		*bridge = NULL;
> 
> I would move this ^ ...
> 
> > +	if (panel) {
> > +		*panel = of_drm_find_panel(remote);
> > +		if (*panel) {
> 
> ... here.

Okay.

> > +			ret = 0;
> > +			goto out_put;
> > +		}
> > +		ret = -EPROBE_DEFER;
> > +	}
> > +
> > +	if (bridge) {
> > +		*bridge = of_drm_find_bridge(remote);
> > +		if (*bridge)
> > +			ret = 0;
> > +		else
> > +			ret = -EPROBE_DEFER;
> > +	}
> > +out_put:
> > +	of_node_put(remote);
> > +	return ret;
> > +}

I've ended up re-writing things a bit getting rid of the goto and the 
result looks like this:

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) {
			if (bridge)
				*bridge = NULL;
			ret = 0;
		}
	}

	/* No panel found yet, check for a bridge next. */
	if (ret && bridge) {
		*bridge = of_drm_find_bridge(remote);
		if (*bridge)
			ret = 0;
	}

	of_node_put(remote);
	return ret;
}

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 17:09       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 17:09 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
> On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> > 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>
> > ---
> >  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
> >  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
> >  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         | 27 +---------
> >  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
> >  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_drv.c               | 12 ++---
> >  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
> >  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
> >  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            | 11 +----
> >  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
> >  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
> >  20 files changed, 64 insertions(+), 351 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> > index e5f4f4a6546d..0f70f5fe9970 100644
> > --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> > +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> > @@ -430,29 +430,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;
> 
> The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
> test your changes on my setup to see how this affects having the encoder as a module.

What are you expecting to happen with -EAGAIN? This one was a bit of an 
oddball. 

This condition would only change if you had an overlay. That's a use 
case that needs to be handled in a common way ('cause I don't want to 
clean-up every driver doing overlays in their own way latter). Just 
having "status" changing at runtime would have all sorts of implications 
in the kernel.

> 
> > -	}
> >  
> >  	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 32f746e31379..bfa04be7f5de 100644
> > --- a/drivers/gpu/drm/arm/malidp_drv.c
> > +++ b/drivers/gpu/drm/arm/malidp_drv.c
> > @@ -262,7 +262,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);
> > @@ -360,12 +359,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) {
> > @@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
> >  irq_init_fail:
> >  	component_unbind_all(dev, drm);
> >  bind_fail:
> > -	of_node_put(malidp->crtc.port);
> 
> Why removing this line? AFAICT this is still needed, according to of_graph_get_port_by_id()
> documentation.

Yes, you are right.

Rob

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 17:09       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 17:09 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
> On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> > 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> > ---
> >  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
> >  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
> >  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         | 27 +---------
> >  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
> >  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_drv.c               | 12 ++---
> >  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
> >  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
> >  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            | 11 +----
> >  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
> >  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
> >  20 files changed, 64 insertions(+), 351 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> > index e5f4f4a6546d..0f70f5fe9970 100644
> > --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> > +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> > @@ -430,29 +430,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;
> 
> The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
> test your changes on my setup to see how this affects having the encoder as a module.

What are you expecting to happen with -EAGAIN? This one was a bit of an 
oddball. 

This condition would only change if you had an overlay. That's a use 
case that needs to be handled in a common way ('cause I don't want to 
clean-up every driver doing overlays in their own way latter). Just 
having "status" changing at runtime would have all sorts of implications 
in the kernel.

> 
> > -	}
> >  
> >  	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 32f746e31379..bfa04be7f5de 100644
> > --- a/drivers/gpu/drm/arm/malidp_drv.c
> > +++ b/drivers/gpu/drm/arm/malidp_drv.c
> > @@ -262,7 +262,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);
> > @@ -360,12 +359,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) {
> > @@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
> >  irq_init_fail:
> >  	component_unbind_all(dev, drm);
> >  bind_fail:
> > -	of_node_put(malidp->crtc.port);
> 
> Why removing this line? AFAICT this is still needed, according to of_graph_get_port_by_id()
> documentation.

Yes, you are right.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
  2017-02-06 17:09       ` Rob Herring
@ 2017-02-06 17:23         ` Liviu Dudau
  -1 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-06 17:23 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Mon, Feb 06, 2017 at 11:09:49AM -0600, Rob Herring wrote:
> On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
> > On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> > > 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>
> > > ---
> > >  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
> > >  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
> > >  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         | 27 +---------
> > >  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
> > >  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_drv.c               | 12 ++---
> > >  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
> > >  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
> > >  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            | 11 +----
> > >  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
> > >  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
> > >  20 files changed, 64 insertions(+), 351 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> > > index e5f4f4a6546d..0f70f5fe9970 100644
> > > --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> > > +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> > > @@ -430,29 +430,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;
> > 
> > The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
> > test your changes on my setup to see how this affects having the encoder as a module.
> 
> What are you expecting to happen with -EAGAIN? This one was a bit of an 
> oddball.

When both the HDLCD and the TDA998x drivers are compiled as modules, the order in which
they are inserted can be somewhat random (due to testing). It is at that time when you
want the probe of HDLCD to be retried on the insmod-ing of the tda998x.ko rather than
fail entirely.

> 
> This condition would only change if you had an overlay. That's a use 
> case that needs to be handled in a common way ('cause I don't want to 
> clean-up every driver doing overlays in their own way latter). Just 
> having "status" changing at runtime would have all sorts of implications 
> in the kernel.

Hmm, not sure what you mean here with overlays. Are you thinking that the
remote port is initially disabled and then re-enabled by an overlay? That is
not the only way of_device_is_available() can fail, see above regarding modules.

Best regards,
Liviu

> 
> > 
> > > -	}
> > >  
> > >  	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 32f746e31379..bfa04be7f5de 100644
> > > --- a/drivers/gpu/drm/arm/malidp_drv.c
> > > +++ b/drivers/gpu/drm/arm/malidp_drv.c
> > > @@ -262,7 +262,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);
> > > @@ -360,12 +359,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) {
> > > @@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
> > >  irq_init_fail:
> > >  	component_unbind_all(dev, drm);
> > >  bind_fail:
> > > -	of_node_put(malidp->crtc.port);
> > 
> > Why removing this line? AFAICT this is still needed, according to of_graph_get_port_by_id()
> > documentation.
> 
> Yes, you are right.
> 
> Rob

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 17:23         ` Liviu Dudau
  0 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-06 17:23 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Mon, Feb 06, 2017 at 11:09:49AM -0600, Rob Herring wrote:
> On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
> > On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> > > 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> > > ---
> > >  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
> > >  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------
> > >  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         | 27 +---------
> > >  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
> > >  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_drv.c               | 12 ++---
> > >  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
> > >  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
> > >  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            | 11 +----
> > >  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
> > >  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
> > >  20 files changed, 64 insertions(+), 351 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> > > index e5f4f4a6546d..0f70f5fe9970 100644
> > > --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> > > +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> > > @@ -430,29 +430,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;
> > 
> > The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
> > test your changes on my setup to see how this affects having the encoder as a module.
> 
> What are you expecting to happen with -EAGAIN? This one was a bit of an 
> oddball.

When both the HDLCD and the TDA998x drivers are compiled as modules, the order in which
they are inserted can be somewhat random (due to testing). It is at that time when you
want the probe of HDLCD to be retried on the insmod-ing of the tda998x.ko rather than
fail entirely.

> 
> This condition would only change if you had an overlay. That's a use 
> case that needs to be handled in a common way ('cause I don't want to 
> clean-up every driver doing overlays in their own way latter). Just 
> having "status" changing at runtime would have all sorts of implications 
> in the kernel.

Hmm, not sure what you mean here with overlays. Are you thinking that the
remote port is initially disabled and then re-enabled by an overlay? That is
not the only way of_device_is_available() can fail, see above regarding modules.

Best regards,
Liviu

> 
> > 
> > > -	}
> > >  
> > >  	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 32f746e31379..bfa04be7f5de 100644
> > > --- a/drivers/gpu/drm/arm/malidp_drv.c
> > > +++ b/drivers/gpu/drm/arm/malidp_drv.c
> > > @@ -262,7 +262,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);
> > > @@ -360,12 +359,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) {
> > > @@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
> > >  irq_init_fail:
> > >  	component_unbind_all(dev, drm);
> > >  bind_fail:
> > > -	of_node_put(malidp->crtc.port);
> > 
> > Why removing this line? AFAICT this is still needed, according to of_graph_get_port_by_id()
> > documentation.
> 
> Yes, you are right.
> 
> Rob

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-02-06 10:03     ` Maxime Ripard
@ 2017-02-06 17:32       ` Rob Herring
  -1 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 17:32 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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

On Mon, Feb 06, 2017 at 11:03:01AM +0100, Maxime Ripard wrote:
> Hi Rob,
> 
> On Fri, Feb 03, 2017 at 09:36:34PM -0600, 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>
> > ---
> 
> [..]
> 
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > index f5e86fe7750e..4720725b0fb0 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"
> > @@ -217,12 +218,10 @@ int sun4i_rgb_init(struct drm_device *drm)
> >  	rgb->drv = drv;
> >  	encoder = &rgb->encoder;
> >  
> > -	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> > -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> > -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> > -		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
> > -		return 0;
> > -	}
> > +	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> > +					  &tcon->panel, &encoder->bridge);
> > +	if (ret)
> > +		return ret;
> 
> It used to ignore the error if it couldn't find the bridge. This will
> break the probe.

Well, I got it half right. :) The probe does that, but this needs to 
too.

> >  
> >  	drm_encoder_helper_add(&rgb->encoder,
> >  			       &sun4i_rgb_enc_helper_funcs);
> > @@ -239,7 +238,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,
> > @@ -260,7 +259,7 @@ int sun4i_rgb_init(struct drm_device *drm)
> >  		}
> >  	}
> >  
> > -	if (!IS_ERR(encoder->bridge)) {
> > +	if (encoder->bridge) {
> >  		encoder->bridge->encoder = &rgb->encoder;
> >  
> >  		ret = drm_bridge_attach(drm, encoder->bridge);
> > @@ -268,8 +267,6 @@ int sun4i_rgb_init(struct drm_device *drm)
> >  			dev_err(drm->dev, "Couldn't attach our bridge\n");
> >  			goto err_cleanup_connector;
> >  		}
> > -	} else {
> > -		encoder->bridge = NULL;
> >  	}
> >  
> >  	return 0;
> > 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);
> 
> And the panel is only one of our endpoints, which is optional, while
> other endpoints are mandatory. This means that we might very well have
> an endpoint that is not a panel or a bridge. In this case, I think
> your function will return an error and will be treated as such, while
> it's really the expected behaviour.
> 
> I think it's better to leave this driver alone for now, it's not as
> trivial as it looks, and will require some testing to get things
> right. I'll try to get my head around how to use your new (very
> welcome) helpers.

Well, certainly it needs testing. But this is one of the easier examples 
because you are requesting a specific port/endpoint number. It's the 
drivers that just loop over all the endpoints that give me more 
problems.

Anyway, this is 4.12 material, so I'll make the fix above and want 
to leave this in for now. 

Rob

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-06 17:32       ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 17:32 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Mon, Feb 06, 2017 at 11:03:01AM +0100, Maxime Ripard wrote:
> Hi Rob,
> 
> On Fri, Feb 03, 2017 at 09:36:34PM -0600, 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> > ---
> 
> [..]
> 
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > index f5e86fe7750e..4720725b0fb0 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"
> > @@ -217,12 +218,10 @@ int sun4i_rgb_init(struct drm_device *drm)
> >  	rgb->drv = drv;
> >  	encoder = &rgb->encoder;
> >  
> > -	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> > -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> > -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> > -		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
> > -		return 0;
> > -	}
> > +	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> > +					  &tcon->panel, &encoder->bridge);
> > +	if (ret)
> > +		return ret;
> 
> It used to ignore the error if it couldn't find the bridge. This will
> break the probe.

Well, I got it half right. :) The probe does that, but this needs to 
too.

> >  
> >  	drm_encoder_helper_add(&rgb->encoder,
> >  			       &sun4i_rgb_enc_helper_funcs);
> > @@ -239,7 +238,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,
> > @@ -260,7 +259,7 @@ int sun4i_rgb_init(struct drm_device *drm)
> >  		}
> >  	}
> >  
> > -	if (!IS_ERR(encoder->bridge)) {
> > +	if (encoder->bridge) {
> >  		encoder->bridge->encoder = &rgb->encoder;
> >  
> >  		ret = drm_bridge_attach(drm, encoder->bridge);
> > @@ -268,8 +267,6 @@ int sun4i_rgb_init(struct drm_device *drm)
> >  			dev_err(drm->dev, "Couldn't attach our bridge\n");
> >  			goto err_cleanup_connector;
> >  		}
> > -	} else {
> > -		encoder->bridge = NULL;
> >  	}
> >  
> >  	return 0;
> > 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);
> 
> And the panel is only one of our endpoints, which is optional, while
> other endpoints are mandatory. This means that we might very well have
> an endpoint that is not a panel or a bridge. In this case, I think
> your function will return an error and will be treated as such, while
> it's really the expected behaviour.
> 
> I think it's better to leave this driver alone for now, it's not as
> trivial as it looks, and will require some testing to get things
> right. I'll try to get my head around how to use your new (very
> welcome) helpers.

Well, certainly it needs testing. But this is one of the easier examples 
because you are requesting a specific port/endpoint number. It's the 
drivers that just loop over all the endpoints that give me more 
problems.

Anyway, this is 4.12 material, so I'll make the fix above and want 
to leave this in for now. 

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 17:34           ` Russell King - ARM Linux
  0 siblings, 0 replies; 80+ messages in thread
From: Russell King - ARM Linux @ 2017-02-06 17:34 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Rob Herring, David Airlie, Daniel Vetter, Sean Paul, dri-devel,
	devicetree, linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt

On Mon, Feb 06, 2017 at 05:23:06PM +0000, Liviu Dudau wrote:
> On Mon, Feb 06, 2017 at 11:09:49AM -0600, Rob Herring wrote:
> > On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
> > > On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> > > > -	/* 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;
> > > 
> > > The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
> > > test your changes on my setup to see how this affects having the encoder as a module.
> > 
> > What are you expecting to happen with -EAGAIN? This one was a bit of an 
> > oddball.
> 
> When both the HDLCD and the TDA998x drivers are compiled as modules, the
> order in which they are inserted can be somewhat random (due to testing).

Not really "due to testing" but if you run a real distro, they tend to
have a multi-threaded behaviour when loading kernel modules at boot.

> It is at that time when you want the probe of HDLCD to be retried on the
> insmod-ing of the tda998x.ko rather than fail entirely.

-EAGAIN doesn't get you that, and in any case, solving that problem is
exactly why the component API exists - so that DRM only comes up once
all the necessary components are available.

-EAGAIN also doesn't get you that from inside a probe function - such
an error will be reported in the kernel log, and no further action
will be taken (the device driver probe will be failed, and not
automatically retried.

The only case that we automatically retry is if a driver returns
-EPROBE_DEFER.  Everything else causes a probe failure.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 17:34           ` Russell King - ARM Linux
  0 siblings, 0 replies; 80+ messages in thread
From: Russell King - ARM Linux @ 2017-02-06 17:34 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Rob Herring, David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Mon, Feb 06, 2017 at 05:23:06PM +0000, Liviu Dudau wrote:
> On Mon, Feb 06, 2017 at 11:09:49AM -0600, Rob Herring wrote:
> > On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
> > > On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> > > > -	/* 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;
> > > 
> > > The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
> > > test your changes on my setup to see how this affects having the encoder as a module.
> > 
> > What are you expecting to happen with -EAGAIN? This one was a bit of an 
> > oddball.
> 
> When both the HDLCD and the TDA998x drivers are compiled as modules, the
> order in which they are inserted can be somewhat random (due to testing).

Not really "due to testing" but if you run a real distro, they tend to
have a multi-threaded behaviour when loading kernel modules at boot.

> It is at that time when you want the probe of HDLCD to be retried on the
> insmod-ing of the tda998x.ko rather than fail entirely.

-EAGAIN doesn't get you that, and in any case, solving that problem is
exactly why the component API exists - so that DRM only comes up once
all the necessary components are available.

-EAGAIN also doesn't get you that from inside a probe function - such
an error will be reported in the kernel log, and no further action
will be taken (the device driver probe will be failed, and not
automatically retried.

The only case that we automatically retry is if a driver returns
-EPROBE_DEFER.  Everything else causes a probe failure.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 17:42           ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 17:42 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

On Mon, Feb 6, 2017 at 11:23 AM, Liviu Dudau <liviu.dudau@arm.com> wrote:
> On Mon, Feb 06, 2017 at 11:09:49AM -0600, Rob Herring wrote:
>> On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
>> > On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
>> > > 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.

[...]

>> > > - /* 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;
>> >
>> > The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
>> > test your changes on my setup to see how this affects having the encoder as a module.
>>
>> What are you expecting to happen with -EAGAIN? This one was a bit of an
>> oddball.
>
> When both the HDLCD and the TDA998x drivers are compiled as modules, the order in which
> they are inserted can be somewhat random (due to testing). It is at that time when you
> want the probe of HDLCD to be retried on the insmod-ing of the tda998x.ko rather than
> fail entirely.
>
>>
>> This condition would only change if you had an overlay. That's a use
>> case that needs to be handled in a common way ('cause I don't want to
>> clean-up every driver doing overlays in their own way latter). Just
>> having "status" changing at runtime would have all sorts of implications
>> in the kernel.
>
> Hmm, not sure what you mean here with overlays. Are you thinking that the
> remote port is initially disabled and then re-enabled by an overlay? That is
> not the only way of_device_is_available() can fail, see above regarding modules.

Russell pretty much answered most of this, but specifically for
of_device_is_available, the only way of_device_is_available() can
change is a DT change with "status" changing. The only way
of_graph_get_remote_port_parent changes is also from a DT change.

Rob

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 17:42           ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2017-02-06 17:42 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	Boris Brezillon, Archit Taneja, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Kukjin Kim,
	Krzysztof Kozlowski, Javier Martinez Canillas, Stefan Agner

On Mon, Feb 6, 2017 at 11:23 AM, Liviu Dudau <liviu.dudau-5wv7dgnIgG8@public.gmane.org> wrote:
> On Mon, Feb 06, 2017 at 11:09:49AM -0600, Rob Herring wrote:
>> On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
>> > On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
>> > > 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.

[...]

>> > > - /* 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;
>> >
>> > The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
>> > test your changes on my setup to see how this affects having the encoder as a module.
>>
>> What are you expecting to happen with -EAGAIN? This one was a bit of an
>> oddball.
>
> When both the HDLCD and the TDA998x drivers are compiled as modules, the order in which
> they are inserted can be somewhat random (due to testing). It is at that time when you
> want the probe of HDLCD to be retried on the insmod-ing of the tda998x.ko rather than
> fail entirely.
>
>>
>> This condition would only change if you had an overlay. That's a use
>> case that needs to be handled in a common way ('cause I don't want to
>> clean-up every driver doing overlays in their own way latter). Just
>> having "status" changing at runtime would have all sorts of implications
>> in the kernel.
>
> Hmm, not sure what you mean here with overlays. Are you thinking that the
> remote port is initially disabled and then re-enabled by an overlay? That is
> not the only way of_device_is_available() can fail, see above regarding modules.

Russell pretty much answered most of this, but specifically for
of_device_is_available, the only way of_device_is_available() can
change is a DT change with "status" changing. The only way
of_graph_get_remote_port_parent changes is also from a DT change.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
  2017-02-06 16:53       ` Rob Herring
@ 2017-02-06 17:45         ` Philipp Zabel
  -1 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 17:45 UTC (permalink / raw)
  To: Rob Herring
  Cc: Liviu Dudau, David Airlie, Daniel Vetter, Sean Paul, dri-devel,
	devicetree, linux-kernel, Frank Rowand, 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, Mali DP Maintainers, Neil Armstrong,
	Carlo Caione, Kevin Hilman, Rob Clark, Jyri Sarha,
	Tomi Valkeinen, Eric Anholt, Russell King

On Mon, 2017-02-06 at 10:53 -0600, Rob Herring wrote:
> On Mon, Feb 06, 2017 at 11:42:48AM +0100, Philipp Zabel wrote:
> > On Fri, 2017-02-03 at 21:36 -0600, 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.
> 
> [...]
> 
> > > +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 = -ENODEV;
> > 
> > This is only returned if !panel && !bridge. I'd consider this invalid
> > usage of this function, so maybe use -EINVAL?
> 
> Yes.
> 
> > > +	struct device_node *remote;
> > > +
> > > +	remote = of_graph_get_remote_node(np, port, endpoint);
> > > +	if (!remote)
> > > +		return -ENODEV;
> > > +
> > > +	if (bridge)
> > > +		*bridge = NULL;
> > 
> > I would move this ^ ...
> > 
> > > +	if (panel) {
> > > +		*panel = of_drm_find_panel(remote);
> > > +		if (*panel) {
> > 
> > ... here.
> 
> Okay.
> 
> > > +			ret = 0;
> > > +			goto out_put;
> > > +		}
> > > +		ret = -EPROBE_DEFER;
> > > +	}
> > > +
> > > +	if (bridge) {
> > > +		*bridge = of_drm_find_bridge(remote);
> > > +		if (*bridge)
> > > +			ret = 0;
> > > +		else
> > > +			ret = -EPROBE_DEFER;
> > > +	}
> > > +out_put:
> > > +	of_node_put(remote);
> > > +	return ret;
> > > +}
> 
> I've ended up re-writing things a bit getting rid of the goto and the 
> result looks like this:

Looks good to me.

> 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) {
> 			if (bridge)
> 				*bridge = NULL;

With the goto out_put gone, I'm conflicted whether I find this clearer
here, or ...

> 			ret = 0;
> 		}
> 	}
> 
> 	/* No panel found yet, check for a bridge next. */
> 	if (ret && bridge) {
> 		*bridge = of_drm_find_bridge(remote);
> 		if (*bridge)
> 			ret = 0;
> 	}

... even down here:

	if (bridge) {
		if (ret) {
			/* No panel found yet, check for a bridge next. */
			*bridge = of_drm_find_bridge(remote)
			if (*bridge)
				ret = 0;
		} else {
			*bridge = NULL;
		}
	}

That way bridge doesn't have to be checked twice and all the
modification of *bridge is in the same block.

> 
> 	of_node_put(remote);
> 	return ret;
> }

Either way,

Acked-by: Philipp Zabel <p.zabel@pengutronix.de>

regards
Philipp

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-06 17:45         ` Philipp Zabel
  0 siblings, 0 replies; 80+ messages in thread
From: Philipp Zabel @ 2017-02-06 17:45 UTC (permalink / raw)
  To: Rob Herring
  Cc: Liviu Dudau, David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Mon, 2017-02-06 at 10:53 -0600, Rob Herring wrote:
> On Mon, Feb 06, 2017 at 11:42:48AM +0100, Philipp Zabel wrote:
> > On Fri, 2017-02-03 at 21:36 -0600, 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.
> 
> [...]
> 
> > > +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 = -ENODEV;
> > 
> > This is only returned if !panel && !bridge. I'd consider this invalid
> > usage of this function, so maybe use -EINVAL?
> 
> Yes.
> 
> > > +	struct device_node *remote;
> > > +
> > > +	remote = of_graph_get_remote_node(np, port, endpoint);
> > > +	if (!remote)
> > > +		return -ENODEV;
> > > +
> > > +	if (bridge)
> > > +		*bridge = NULL;
> > 
> > I would move this ^ ...
> > 
> > > +	if (panel) {
> > > +		*panel = of_drm_find_panel(remote);
> > > +		if (*panel) {
> > 
> > ... here.
> 
> Okay.
> 
> > > +			ret = 0;
> > > +			goto out_put;
> > > +		}
> > > +		ret = -EPROBE_DEFER;
> > > +	}
> > > +
> > > +	if (bridge) {
> > > +		*bridge = of_drm_find_bridge(remote);
> > > +		if (*bridge)
> > > +			ret = 0;
> > > +		else
> > > +			ret = -EPROBE_DEFER;
> > > +	}
> > > +out_put:
> > > +	of_node_put(remote);
> > > +	return ret;
> > > +}
> 
> I've ended up re-writing things a bit getting rid of the goto and the 
> result looks like this:

Looks good to me.

> 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) {
> 			if (bridge)
> 				*bridge = NULL;

With the goto out_put gone, I'm conflicted whether I find this clearer
here, or ...

> 			ret = 0;
> 		}
> 	}
> 
> 	/* No panel found yet, check for a bridge next. */
> 	if (ret && bridge) {
> 		*bridge = of_drm_find_bridge(remote);
> 		if (*bridge)
> 			ret = 0;
> 	}

... even down here:

	if (bridge) {
		if (ret) {
			/* No panel found yet, check for a bridge next. */
			*bridge = of_drm_find_bridge(remote)
			if (*bridge)
				ret = 0;
		} else {
			*bridge = NULL;
		}
	}

That way bridge doesn't have to be checked twice and all the
modification of *bridge is in the same block.

> 
> 	of_node_put(remote);
> 	return ret;
> }

Either way,

Acked-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 17:55             ` Liviu Dudau
  0 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-06 17:55 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Rob Herring, David Airlie, Daniel Vetter, Sean Paul, dri-devel,
	devicetree, linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt

On Mon, Feb 06, 2017 at 05:34:07PM +0000, Russell King - ARM Linux wrote:
> On Mon, Feb 06, 2017 at 05:23:06PM +0000, Liviu Dudau wrote:
> > On Mon, Feb 06, 2017 at 11:09:49AM -0600, Rob Herring wrote:
> > > On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
> > > > On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> > > > > -	/* 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;
> > > > 
> > > > The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
> > > > test your changes on my setup to see how this affects having the encoder as a module.
> > > 
> > > What are you expecting to happen with -EAGAIN? This one was a bit of an 
> > > oddball.
> > 
> > When both the HDLCD and the TDA998x drivers are compiled as modules, the
> > order in which they are inserted can be somewhat random (due to testing).
> 
> Not really "due to testing" but if you run a real distro, they tend to
> have a multi-threaded behaviour when loading kernel modules at boot.

Yeah, a lot of times I'm using a toy "distribution" (buildroot) as it boots
faster under ARM models than a "real" (read systemd-based) distro would.

> 
> > It is at that time when you want the probe of HDLCD to be retried on the
> > insmod-ing of the tda998x.ko rather than fail entirely.
> 
> -EAGAIN doesn't get you that, and in any case, solving that problem is
> exactly why the component API exists - so that DRM only comes up once
> all the necessary components are available.
> 
> -EAGAIN also doesn't get you that from inside a probe function - such
> an error will be reported in the kernel log, and no further action
> will be taken (the device driver probe will be failed, and not
> automatically retried.

I stand corrected on the behaviour of the driver then. That was the original
intent, to generate a re-probe of the driver.

> 
> The only case that we automatically retry is if a driver returns
> -EPROBE_DEFER.  Everything else causes a probe failure.

OK, I will fix the driver if Rob's patch still requires it.

Best regards,
Liviu

> 
> -- 
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 17:55             ` Liviu Dudau
  0 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-06 17:55 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Rob Herring, David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Mon, Feb 06, 2017 at 05:34:07PM +0000, Russell King - ARM Linux wrote:
> On Mon, Feb 06, 2017 at 05:23:06PM +0000, Liviu Dudau wrote:
> > On Mon, Feb 06, 2017 at 11:09:49AM -0600, Rob Herring wrote:
> > > On Mon, Feb 06, 2017 at 10:29:33AM +0000, Liviu Dudau wrote:
> > > > On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> > > > > -	/* 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;
> > > > 
> > > > The HDLCD change looks reasonable except for this -EAGAIN business. I'll have to
> > > > test your changes on my setup to see how this affects having the encoder as a module.
> > > 
> > > What are you expecting to happen with -EAGAIN? This one was a bit of an 
> > > oddball.
> > 
> > When both the HDLCD and the TDA998x drivers are compiled as modules, the
> > order in which they are inserted can be somewhat random (due to testing).
> 
> Not really "due to testing" but if you run a real distro, they tend to
> have a multi-threaded behaviour when loading kernel modules at boot.

Yeah, a lot of times I'm using a toy "distribution" (buildroot) as it boots
faster under ARM models than a "real" (read systemd-based) distro would.

> 
> > It is at that time when you want the probe of HDLCD to be retried on the
> > insmod-ing of the tda998x.ko rather than fail entirely.
> 
> -EAGAIN doesn't get you that, and in any case, solving that problem is
> exactly why the component API exists - so that DRM only comes up once
> all the necessary components are available.
> 
> -EAGAIN also doesn't get you that from inside a probe function - such
> an error will be reported in the kernel log, and no further action
> will be taken (the device driver probe will be failed, and not
> automatically retried.

I stand corrected on the behaviour of the driver then. That was the original
intent, to generate a re-probe of the driver.

> 
> The only case that we automatically retry is if a driver returns
> -EPROBE_DEFER.  Everything else causes a probe failure.

OK, I will fix the driver if Rob's patch still requires it.

Best regards,
Liviu

> 
> -- 
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 18:09               ` Russell King - ARM Linux
  0 siblings, 0 replies; 80+ messages in thread
From: Russell King - ARM Linux @ 2017-02-06 18:09 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Rob Herring, David Airlie, Daniel Vetter, Sean Paul, dri-devel,
	devicetree, linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt

On Mon, Feb 06, 2017 at 05:55:33PM +0000, Liviu Dudau wrote:
> OK, I will fix the driver if Rob's patch still requires it.

I don't think you ever needed it.  As Rob says, what you're testing
won't ever change unless you're using overlays - it's certainly not
dependent on the tda998x module being loaded or not, or even the
tda998x driver being bound or not.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-06 18:09               ` Russell King - ARM Linux
  0 siblings, 0 replies; 80+ messages in thread
From: Russell King - ARM Linux @ 2017-02-06 18:09 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Rob Herring, David Airlie, Daniel Vetter, Sean Paul,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Frank Rowand,
	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

On Mon, Feb 06, 2017 at 05:55:33PM +0000, Liviu Dudau wrote:
> OK, I will fix the driver if Rob's patch still requires it.

I don't think you ever needed it.  As Rob says, what you're testing
won't ever change unless you're using overlays - it's certainly not
dependent on the tda998x module being loaded or not, or even the
tda998x driver being bound or not.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
  2017-02-06 17:32       ` Rob Herring
@ 2017-02-08  7:46         ` Maxime Ripard
  -1 siblings, 0 replies; 80+ messages in thread
From: Maxime Ripard @ 2017-02-08  7:46 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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: 6105 bytes --]

Hi Rob,

On Mon, Feb 06, 2017 at 11:32:01AM -0600, Rob Herring wrote:
> On Mon, Feb 06, 2017 at 11:03:01AM +0100, Maxime Ripard wrote:
> > Hi Rob,
> > 
> > On Fri, Feb 03, 2017 at 09:36:34PM -0600, 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>
> > > ---
> > 
> > [..]
> > 
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > > index f5e86fe7750e..4720725b0fb0 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"
> > > @@ -217,12 +218,10 @@ int sun4i_rgb_init(struct drm_device *drm)
> > >  	rgb->drv = drv;
> > >  	encoder = &rgb->encoder;
> > >  
> > > -	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> > > -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> > > -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> > > -		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
> > > -		return 0;
> > > -	}
> > > +	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> > > +					  &tcon->panel, &encoder->bridge);
> > > +	if (ret)
> > > +		return ret;
> > 
> > It used to ignore the error if it couldn't find the bridge. This will
> > break the probe.
> 
> Well, I got it half right. :) The probe does that, but this needs to 
> too.
> 
> > >  
> > >  	drm_encoder_helper_add(&rgb->encoder,
> > >  			       &sun4i_rgb_enc_helper_funcs);
> > > @@ -239,7 +238,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,
> > > @@ -260,7 +259,7 @@ int sun4i_rgb_init(struct drm_device *drm)
> > >  		}
> > >  	}
> > >  
> > > -	if (!IS_ERR(encoder->bridge)) {
> > > +	if (encoder->bridge) {
> > >  		encoder->bridge->encoder = &rgb->encoder;
> > >  
> > >  		ret = drm_bridge_attach(drm, encoder->bridge);
> > > @@ -268,8 +267,6 @@ int sun4i_rgb_init(struct drm_device *drm)
> > >  			dev_err(drm->dev, "Couldn't attach our bridge\n");
> > >  			goto err_cleanup_connector;
> > >  		}
> > > -	} else {
> > > -		encoder->bridge = NULL;
> > >  	}
> > >  
> > >  	return 0;
> > > 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);
> > 
> > And the panel is only one of our endpoints, which is optional, while
> > other endpoints are mandatory. This means that we might very well have
> > an endpoint that is not a panel or a bridge. In this case, I think
> > your function will return an error and will be treated as such, while
> > it's really the expected behaviour.
> > 
> > I think it's better to leave this driver alone for now, it's not as
> > trivial as it looks, and will require some testing to get things
> > right. I'll try to get my head around how to use your new (very
> > welcome) helpers.
> 
> Well, certainly it needs testing. But this is one of the easier examples 
> because you are requesting a specific port/endpoint number. It's the 
> drivers that just loop over all the endpoints that give me more 
> problems.

Oh, right... I missed that you were giving the port and endpoint
numbers..

> Anyway, this is 4.12 material, so I'll make the fix above and want 
> to leave this in for now. 

Ok, I'll test it, thanks!
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] 80+ messages in thread

* Re: [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge
@ 2017-02-08  7:46         ` Maxime Ripard
  0 siblings, 0 replies; 80+ messages in thread
From: Maxime Ripard @ 2017-02-08  7:46 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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

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

Hi Rob,

On Mon, Feb 06, 2017 at 11:32:01AM -0600, Rob Herring wrote:
> On Mon, Feb 06, 2017 at 11:03:01AM +0100, Maxime Ripard wrote:
> > Hi Rob,
> > 
> > On Fri, Feb 03, 2017 at 09:36:34PM -0600, 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>
> > > ---
> > 
> > [..]
> > 
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > > index f5e86fe7750e..4720725b0fb0 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"
> > > @@ -217,12 +218,10 @@ int sun4i_rgb_init(struct drm_device *drm)
> > >  	rgb->drv = drv;
> > >  	encoder = &rgb->encoder;
> > >  
> > > -	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> > > -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> > > -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> > > -		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
> > > -		return 0;
> > > -	}
> > > +	ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
> > > +					  &tcon->panel, &encoder->bridge);
> > > +	if (ret)
> > > +		return ret;
> > 
> > It used to ignore the error if it couldn't find the bridge. This will
> > break the probe.
> 
> Well, I got it half right. :) The probe does that, but this needs to 
> too.
> 
> > >  
> > >  	drm_encoder_helper_add(&rgb->encoder,
> > >  			       &sun4i_rgb_enc_helper_funcs);
> > > @@ -239,7 +238,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,
> > > @@ -260,7 +259,7 @@ int sun4i_rgb_init(struct drm_device *drm)
> > >  		}
> > >  	}
> > >  
> > > -	if (!IS_ERR(encoder->bridge)) {
> > > +	if (encoder->bridge) {
> > >  		encoder->bridge->encoder = &rgb->encoder;
> > >  
> > >  		ret = drm_bridge_attach(drm, encoder->bridge);
> > > @@ -268,8 +267,6 @@ int sun4i_rgb_init(struct drm_device *drm)
> > >  			dev_err(drm->dev, "Couldn't attach our bridge\n");
> > >  			goto err_cleanup_connector;
> > >  		}
> > > -	} else {
> > > -		encoder->bridge = NULL;
> > >  	}
> > >  
> > >  	return 0;
> > > 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);
> > 
> > And the panel is only one of our endpoints, which is optional, while
> > other endpoints are mandatory. This means that we might very well have
> > an endpoint that is not a panel or a bridge. In this case, I think
> > your function will return an error and will be treated as such, while
> > it's really the expected behaviour.
> > 
> > I think it's better to leave this driver alone for now, it's not as
> > trivial as it looks, and will require some testing to get things
> > right. I'll try to get my head around how to use your new (very
> > welcome) helpers.
> 
> Well, certainly it needs testing. But this is one of the easier examples 
> because you are requesting a specific port/endpoint number. It's the 
> drivers that just loop over all the endpoints that give me more 
> problems.

Oh, right... I missed that you were giving the port and endpoint
numbers..

> Anyway, this is 4.12 material, so I'll make the fix above and want 
> to leave this in for now. 

Ok, I'll test it, thanks!
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] 80+ messages in thread

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
  2017-02-04  3:36   ` Rob Herring
@ 2017-02-08 11:57     ` Liviu Dudau
  -1 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-08 11:57 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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, Mali DP Maintainers,
	Neil Armstrong, Carlo Caione, Kevin Hilman, Rob Clark,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, Russell King

Hi Rob,

On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> 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>
> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------

For the HDLCD and Mali DP part you can also add:

Tested-by: Liviu Dudau <liviu.dudau@arm.com>

Best regards,
Liviu

>  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         | 27 +---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>  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_drv.c               | 12 ++---
>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>  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            | 11 +----
>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>  20 files changed, 64 insertions(+), 351 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> index e5f4f4a6546d..0f70f5fe9970 100644
> --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> @@ -430,29 +430,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 32f746e31379..bfa04be7f5de 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -262,7 +262,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);
> @@ -360,12 +359,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) {
> @@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
>  irq_init_fail:
>  	component_unbind_all(dev, drm);
>  bind_fail:
> -	of_node_put(malidp->crtc.port);
>  	malidp->crtc.port = NULL;
> -port_fail:
>  	malidp_fini(drm);
>  init_fail:
>  	drm->dev_private = NULL;
> @@ -478,29 +470,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 e5706981c934..47b4c99162ad 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 e07cb1fe4860..04528f512c91 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 a0def0be6d65..93ebb12133e1 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> @@ -228,29 +228,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;
> @@ -262,7 +239,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;
> @@ -279,7 +256,7 @@ static int parse_dt(struct exynos_mic *mic)
>  			break;
>  		case ENDPOINT_DSI_NODE:
>  			/* panel node */
> -			remote_node = get_remote_node(remote_node, 1);
> +			remote_node = of_graph_get_remote_node(remote_node, 1, 0);
>  			if (!remote_node) {
>  				ret = -EPIPE;
>  				goto exit;
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..4ed6b5fef3b7 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -757,34 +757,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 device_node *bridge_node;
>  	struct resource *res;
>  
>  	/*
>  	 * 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, 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/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> index ebd5f4fe4c23..18d6570e057d 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> @@ -247,34 +247,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;
> @@ -288,7 +260,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 90fb831ef031..dbd554c09a39 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 0e8c4d9af340..f14e472812ce 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1433,7 +1433,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;
> @@ -1485,29 +1485,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->bridge.next = of_drm_find_bridge(remote);
> diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
> index ff1f6019b97b..37cb9c755ed7 100644
> --- a/drivers/gpu/drm/meson/meson_drv.c
> +++ b/drivers/gpu/drm/meson/meson_drv.c
> @@ -163,14 +163,14 @@ static struct drm_driver meson_driver = {
>  
>  static bool meson_vpu_has_available_connectors(struct device *dev)
>  {
> -	struct device_node *ep, *remote;
> +	struct device_node *remote;
> +	int i;
>  
> -	/* Parses each endpoint and check if remote exists */
> -	for_each_endpoint_of_node(dev->of_node, ep) {
> -		/* If the endpoint node exists, consider it enabled */
> -		remote = of_graph_get_remote_port(ep);
> -		if (remote)
> +	for_each_of_graph_remote_node(dev->of_node, remote, i, 2) {
> +		if (remote) {
> +			of_node_put(remote);
>  			return true;
> +		}
>  	}
>  
>  	return false;
> 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 3819fdefcae2..da8619f9eb2e 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -1637,9 +1637,8 @@ 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_err(dev, "%s: no valid device\n", __func__);
>  		ret = -ENODEV;
>  		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 b782efd4b95f..9f36fad1915e 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)
> @@ -270,7 +244,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 2390c8577617..5e7ccd04ada6 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -373,19 +373,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);
> @@ -464,7 +458,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 6dfdb145f3bb..e74cc236a79b 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> @@ -1013,16 +1013,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, 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 c67d7cd7d57e..b7523dce4e8a 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> @@ -187,39 +187,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;
> @@ -227,7 +194,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;
>  
> @@ -266,35 +233,18 @@ 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))
> +	if (!match)
>  		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;
> +	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
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-08 11:57     ` Liviu Dudau
  0 siblings, 0 replies; 80+ messages in thread
From: Liviu Dudau @ 2017-02-08 11:57 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Sean Paul, dri-devel, devicetree,
	linux-kernel, Frank Rowand, 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

Hi Rob,

On Fri, Feb 03, 2017 at 09:36:33PM -0600, Rob Herring wrote:
> 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>
> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c                 | 22 ++-------
>  drivers/gpu/drm/arm/malidp_drv.c                | 29 ++---------

For the HDLCD and Mali DP part you can also add:

Tested-by: Liviu Dudau <liviu.dudau@arm.com>

Best regards,
Liviu

>  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         | 27 +---------
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c    | 26 ++--------
>  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_drv.c               | 12 ++---
>  drivers/gpu/drm/meson/meson_venc_cvbs.c         | 19 ++-----
>  drivers/gpu/drm/msm/dsi/dsi_host.c              |  3 +-
>  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            | 11 +----
>  drivers/gpu/drm/tilcdc/tilcdc_external.c        | 66 +++----------------------
>  drivers/gpu/drm/vc4/vc4_dpi.c                   | 15 ++----
>  20 files changed, 64 insertions(+), 351 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> index e5f4f4a6546d..0f70f5fe9970 100644
> --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> @@ -430,29 +430,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 32f746e31379..bfa04be7f5de 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -262,7 +262,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);
> @@ -360,12 +359,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) {
> @@ -418,9 +412,7 @@ static int malidp_bind(struct device *dev)
>  irq_init_fail:
>  	component_unbind_all(dev, drm);
>  bind_fail:
> -	of_node_put(malidp->crtc.port);
>  	malidp->crtc.port = NULL;
> -port_fail:
>  	malidp_fini(drm);
>  init_fail:
>  	drm->dev_private = NULL;
> @@ -478,29 +470,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 e5706981c934..47b4c99162ad 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 e07cb1fe4860..04528f512c91 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 a0def0be6d65..93ebb12133e1 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> @@ -228,29 +228,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;
> @@ -262,7 +239,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;
> @@ -279,7 +256,7 @@ static int parse_dt(struct exynos_mic *mic)
>  			break;
>  		case ENDPOINT_DSI_NODE:
>  			/* panel node */
> -			remote_node = get_remote_node(remote_node, 1);
> +			remote_node = of_graph_get_remote_node(remote_node, 1, 0);
>  			if (!remote_node) {
>  				ret = -EPIPE;
>  				goto exit;
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..4ed6b5fef3b7 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -757,34 +757,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 device_node *bridge_node;
>  	struct resource *res;
>  
>  	/*
>  	 * 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, 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/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> index ebd5f4fe4c23..18d6570e057d 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> @@ -247,34 +247,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;
> @@ -288,7 +260,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 90fb831ef031..dbd554c09a39 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 0e8c4d9af340..f14e472812ce 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1433,7 +1433,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;
> @@ -1485,29 +1485,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->bridge.next = of_drm_find_bridge(remote);
> diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
> index ff1f6019b97b..37cb9c755ed7 100644
> --- a/drivers/gpu/drm/meson/meson_drv.c
> +++ b/drivers/gpu/drm/meson/meson_drv.c
> @@ -163,14 +163,14 @@ static struct drm_driver meson_driver = {
>  
>  static bool meson_vpu_has_available_connectors(struct device *dev)
>  {
> -	struct device_node *ep, *remote;
> +	struct device_node *remote;
> +	int i;
>  
> -	/* Parses each endpoint and check if remote exists */
> -	for_each_endpoint_of_node(dev->of_node, ep) {
> -		/* If the endpoint node exists, consider it enabled */
> -		remote = of_graph_get_remote_port(ep);
> -		if (remote)
> +	for_each_of_graph_remote_node(dev->of_node, remote, i, 2) {
> +		if (remote) {
> +			of_node_put(remote);
>  			return true;
> +		}
>  	}
>  
>  	return false;
> 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 3819fdefcae2..da8619f9eb2e 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -1637,9 +1637,8 @@ 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_err(dev, "%s: no valid device\n", __func__);
>  		ret = -ENODEV;
>  		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 b782efd4b95f..9f36fad1915e 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)
> @@ -270,7 +244,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 2390c8577617..5e7ccd04ada6 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -373,19 +373,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);
> @@ -464,7 +458,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 6dfdb145f3bb..e74cc236a79b 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> @@ -1013,16 +1013,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, 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 c67d7cd7d57e..b7523dce4e8a 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> @@ -187,39 +187,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;
> @@ -227,7 +194,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;
>  
> @@ -266,35 +233,18 @@ 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))
> +	if (!match)
>  		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;
> +	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
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
  2017-02-04  3:36   ` Rob Herring
@ 2017-02-08 20:44     ` Eric Anholt
  -1 siblings, 0 replies; 80+ messages in thread
From: Eric Anholt @ 2017-02-08 20:44 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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 Ri pard, Chen-Yu Tsai, Liviu Dudau,
	Mali DP Maintainers, Neil Armstrong, Carlo Caione, Kevin Hilman,
	Rob Clark, Jyri Sarha, Tomi Valkeinen, Russell King

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

Rob Herring <robh@kernel.org> writes:

> 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.

For vc4,

Tested-by: Eric Anholt <eric@anholt.net>

Thanks for making this easier.

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

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

* Re: [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node
@ 2017-02-08 20:44     ` Eric Anholt
  0 siblings, 0 replies; 80+ messages in thread
From: Eric Anholt @ 2017-02-08 20:44 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, linux-kernel, Frank Rowand,
	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

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

Rob Herring <robh@kernel.org> writes:

> 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.

For vc4,

Tested-by: Eric Anholt <eric@anholt.net>

Thanks for making this easier.

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

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-10 19:42     ` Frank Rowand
  0 siblings, 0 replies; 80+ messages in thread
From: Frank Rowand @ 2017-02-10 19:42 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel, devicetree, 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 02/03/17 19:36, 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>
> ---
>  drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_of.h     | 13 +++++++++++++
>  2 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b29ce2f52113 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -3,7 +3,9 @@
>  #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_panel.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> @@ -207,3 +209,51 @@ 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 input ports

      @port: ....
      @endpoint: ....


> + * @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.
> + *
> + * 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)
> +{

< snip >

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

* Re: [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge
@ 2017-02-10 19:42     ` Frank Rowand
  0 siblings, 0 replies; 80+ messages in thread
From: Frank Rowand @ 2017-02-10 19:42 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Daniel Vetter, Sean Paul
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, 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

On 02/03/17 19:36, 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-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  drivers/gpu/drm/drm_of.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_of.h     | 13 +++++++++++++
>  2 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b29ce2f52113 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -3,7 +3,9 @@
>  #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_panel.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> @@ -207,3 +209,51 @@ 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 input ports

      @port: ....
      @endpoint: ....


> + * @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.
> + *
> + * 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)
> +{

< snip >

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2017-02-10 19:50 UTC | newest]

Thread overview: 80+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-04  3:36 [PATCH 0/5] DRM OF graph clean-up Rob Herring
2017-02-04  3:36 ` Rob Herring
2017-02-04  3:36 ` [PATCH 1/5] of: introduce of_graph_get_remote_node Rob Herring
2017-02-04  3:36   ` Rob Herring
2017-02-04 16:10   ` Vladimir Zapolskiy
2017-02-04 16:10     ` Vladimir Zapolskiy
2017-02-06  8:50   ` Daniel Vetter
2017-02-06  8:50     ` Daniel Vetter
2017-02-06 13:41     ` Rob Herring
2017-02-06 13:41       ` Rob Herring
2017-02-06 10:32   ` Philipp Zabel
2017-02-06 10:32     ` Philipp Zabel
2017-02-06 13:54     ` Rob Herring
2017-02-06 13:54       ` Rob Herring
2017-02-06 14:03       ` Philipp Zabel
2017-02-06 14:03         ` Philipp Zabel
2017-02-04  3:36 ` [PATCH 2/5] drm: of: introduce drm_of_find_panel_or_bridge Rob Herring
2017-02-04  3:36   ` Rob Herring
2017-02-06 10:18   ` Liviu Dudau
2017-02-06 10:18     ` Liviu Dudau
2017-02-06 16:20     ` Rob Herring
2017-02-06 16:20       ` Rob Herring
2017-02-06 10:42   ` Philipp Zabel
2017-02-06 10:42     ` Philipp Zabel
2017-02-06 16:53     ` Rob Herring
2017-02-06 16:53       ` Rob Herring
2017-02-06 17:45       ` Philipp Zabel
2017-02-06 17:45         ` Philipp Zabel
2017-02-10 19:42   ` Frank Rowand
2017-02-10 19:42     ` Frank Rowand
2017-02-04  3:36 ` [PATCH 3/5] drm: convert drivers to use of_graph_get_remote_node Rob Herring
2017-02-04  3:36   ` Rob Herring
2017-02-06  8:31   ` Jyri Sarha
2017-02-06  8:31     ` Jyri Sarha
2017-02-06 10:17   ` Neil Armstrong
2017-02-06 10:17     ` Neil Armstrong
2017-02-06 10:29   ` Liviu Dudau
2017-02-06 10:29     ` Liviu Dudau
2017-02-06 17:09     ` Rob Herring
2017-02-06 17:09       ` Rob Herring
2017-02-06 17:23       ` Liviu Dudau
2017-02-06 17:23         ` Liviu Dudau
2017-02-06 17:34         ` Russell King - ARM Linux
2017-02-06 17:34           ` Russell King - ARM Linux
2017-02-06 17:55           ` Liviu Dudau
2017-02-06 17:55             ` Liviu Dudau
2017-02-06 18:09             ` Russell King - ARM Linux
2017-02-06 18:09               ` Russell King - ARM Linux
2017-02-06 17:42         ` Rob Herring
2017-02-06 17:42           ` Rob Herring
2017-02-06 10:52   ` Philipp Zabel
2017-02-06 10:52     ` Philipp Zabel
2017-02-06 13:40     ` Rob Herring
2017-02-06 13:40       ` Rob Herring
2017-02-08 11:57   ` Liviu Dudau
2017-02-08 11:57     ` Liviu Dudau
2017-02-08 20:44   ` Eric Anholt
2017-02-08 20:44     ` Eric Anholt
2017-02-04  3:36 ` [PATCH 4/5] drm: convert drivers to use drm_of_find_panel_or_bridge Rob Herring
2017-02-04  3:36   ` Rob Herring
2017-02-04 20:26   ` Fabio Estevam
2017-02-04 20:26     ` Fabio Estevam
2017-02-05 22:25     ` Rob Herring
2017-02-05 22:25       ` Rob Herring
2017-02-06  0:01       ` Fabio Estevam
2017-02-06  0:01         ` Fabio Estevam
2017-02-06  1:22         ` Fabio Estevam
2017-02-06  1:22           ` Fabio Estevam
2017-02-06 10:03   ` Maxime Ripard
2017-02-06 10:03     ` Maxime Ripard
2017-02-06 17:32     ` Rob Herring
2017-02-06 17:32       ` Rob Herring
2017-02-08  7:46       ` Maxime Ripard
2017-02-08  7:46         ` Maxime Ripard
2017-02-06 11:07   ` Philipp Zabel
2017-02-06 11:07     ` Philipp Zabel
2017-02-04  3:36 ` [PATCH 5/5] drm: omap: use common OF graph helpers Rob Herring
2017-02-04  3:36   ` Rob Herring
2017-02-04 10:47 ` [PATCH 0/5] DRM OF graph clean-up Russell King - ARM Linux
2017-02-04 10:47   ` Russell King - ARM Linux

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.