#include <linux/of_graph.h>
#include <drm/drmP.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_of.h>
#include "atmel_hlcdc_dc.h"
.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;
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,
return 0;
}
- bridge = of_drm_find_bridge(np);
- of_node_put(np);
-
if (bridge) {
ret = drm_bridge_attach(&output->encoder, bridge, NULL);
if (!ret)
int atmel_hlcdc_create_outputs(struct drm_device *dev)
{
- struct device_node *ep_np = NULL;
- struct of_endpoint ep;
- int ret;
-
- for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
- ret = of_graph_parse_endpoint(ep_np, &ep);
- if (!ret)
- ret = atmel_hlcdc_check_endpoint(dev, &ep);
-
- if (ret) {
- of_node_put(ep_np);
- return ret;
- }
- }
-
- for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
- ret = of_graph_parse_endpoint(ep_np, &ep);
- if (!ret)
- ret = atmel_hlcdc_attach_endpoint(dev, &ep);
-
- if (ret) {
- of_node_put(ep_np);
+ struct device_node *remote;
+ int ret, endpoint = 0;
+
+ while (true) {
+ /* Loop thru possible multiple connections to the output */
+ remote = of_graph_get_remote_node(dev->dev->of_node, 0,
+ endpoint++);
+ if (!remote)
+ break;
+
+ ret = atmel_hlcdc_attach_endpoint(dev, remote);
+ of_node_put(remote);
+ if (ret)
return ret;
- }
}
- return 0;
+ if (!endpoint)
+ return -ENODEV;
+ return ret;
}
#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"
{
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);
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;
#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"
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
- struct device_node *endpoint, *panel_node;
struct ps8622_bridge *ps8622;
int ret;
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;
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;
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);
#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>
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);
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);
#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"
return ret;
}
-static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
- const struct of_endpoint *ep)
-{
- struct drm_bridge *bridge;
- struct device_node *np;
-
- np = of_graph_get_remote_port_parent(ep->local_node);
-
- fsl_dev->connector.panel = of_drm_find_panel(np);
- if (fsl_dev->connector.panel) {
- of_node_put(np);
- return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
- }
-
- bridge = of_drm_find_bridge(np);
- of_node_put(np);
- if (!bridge)
- return -ENODEV;
-
- return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
-}
-
int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
{
- struct of_endpoint ep;
- struct device_node *ep_node, *panel_node;
+ struct device_node *panel_node;
+ struct drm_panel *panel;
+ struct drm_bridge *bridge;
int ret;
/* This is for backward compatibility */
return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
}
- ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL);
- if (!ep_node)
- return -ENODEV;
-
- ret = of_graph_parse_endpoint(ep_node, &ep);
- of_node_put(ep_node);
+ ret = drm_of_find_panel_or_bridge(fsl_dev->np, 0, 0, &panel, &bridge);
if (ret)
- return -ENODEV;
+ return ret;
+
+ if (panel) {
+ fsl_dev->connector.panel = panel;
+ return fsl_dcu_attach_panel(fsl_dev, panel);
+ }
- return fsl_dcu_attach_endpoint(fsl_dev, &ep);
+ return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
}
#include <linux/clk.h>
#include <linux/component.h>
-#include <linux/of_graph.h>
#include <drm/drm_of.h>
#include <drm/drm_crtc_helper.h>
{
struct dsi_hw_ctx *ctx = dsi->ctx;
struct device_node *np = pdev->dev.of_node;
- struct device_node *endpoint, *bridge_node;
- struct drm_bridge *bridge;
struct resource *res;
+ int ret;
/*
* Get the endpoint node. In our case, dsi has one output port1
* to which the external HDMI bridge is connected.
*/
- endpoint = of_graph_get_endpoint_by_regs(np, 1, -1);
- if (!endpoint) {
- DRM_ERROR("no valid endpoint node\n");
- return -ENODEV;
- }
- of_node_put(endpoint);
-
- bridge_node = of_graph_get_remote_port_parent(endpoint);
- if (!bridge_node) {
- DRM_ERROR("no valid bridge node\n");
- return -ENODEV;
- }
- of_node_put(bridge_node);
-
- bridge = of_drm_find_bridge(bridge_node);
- if (!bridge) {
- DRM_INFO("wait for external HDMI bridge driver.\n");
- return -EPROBE_DEFER;
- }
- dsi->bridge = bridge;
+ ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
+ if (ret)
+ return ret;
ctx->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(ctx->pclk)) {
for_each_child_of_node(np, child) {
struct imx_ldb_channel *channel;
- struct device_node *ep;
int bus_format;
ret = of_property_read_u32(child, "reg", &i);
* The output port is port@4 with an external 4-port mux or
* port@2 with the internal 2-port mux.
*/
- ep = of_graph_get_endpoint_by_regs(child,
- imx_ldb->lvds_mux ? 4 : 2,
- -1);
- if (ep) {
- struct device_node *remote;
-
- remote = of_graph_get_remote_port_parent(ep);
- of_node_put(ep);
- if (remote) {
- channel->panel = of_drm_find_panel(remote);
- channel->bridge = of_drm_find_bridge(remote);
- } else
- return -EPROBE_DEFER;
- of_node_put(remote);
-
- if (!channel->panel && !channel->bridge) {
- dev_err(dev, "panel/bridge not found: %s\n",
- remote->full_name);
- return -EPROBE_DEFER;
- }
- }
+ ret = drm_of_find_panel_or_bridge(child,
+ imx_ldb->lvds_mux ? 4 : 2, 0,
+ &channel->panel, &channel->bridge);
+ if (ret)
+ return ret;
/* panel ddc only if there is no bridge */
if (!channel->bridge) {
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include <linux/videodev2.h>
#include <video/of_display_timing.h>
-#include <linux/of_graph.h>
#include "imx-drm.h"
{
struct drm_device *drm = data;
struct device_node *np = dev->of_node;
- struct device_node *ep;
const u8 *edidp;
struct imx_parallel_display *imxpd;
int ret;
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;
#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>
{
struct mtk_dsi *dsi;
struct device *dev = &pdev->dev;
- struct device_node *remote_node, *endpoint;
struct resource *regs;
int comp_id;
int ret;
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)) {
#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>
.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;
return ret;
}
-
-int mxsfb_create_output(struct drm_device *drm)
-{
- struct mxsfb_drm_private *mxsfb = drm->dev_private;
- struct device_node *ep_np = NULL;
- struct of_endpoint ep;
- int ret;
-
- for_each_endpoint_of_node(drm->dev->of_node, ep_np) {
- ret = of_graph_parse_endpoint(ep_np, &ep);
- if (!ret)
- ret = mxsfb_attach_endpoint(drm, &ep);
-
- if (ret) {
- of_node_put(ep_np);
- return ret;
- }
- }
-
- if (!mxsfb->panel)
- return -EPROBE_DEFER;
-
- return 0;
-}
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)
#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"
rgb->drv = drv;
encoder = &rgb->encoder;
- tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
- bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
- if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
+ ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
+ &tcon->panel, &bridge);
+ if (ret) {
dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
return 0;
}
/* 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,
}
}
- if (!IS_ERR(bridge)) {
+ if (bridge) {
ret = drm_bridge_attach(encoder, bridge, NULL);
if (ret) {
dev_err(drm->dev, "Couldn't attach our bridge\n");
#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>
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", ®);
- 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", ®);
- 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)
{
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);
}