提交 ebc94461 编写于 作者: R Rob Herring 提交者: Sean Paul

drm: convert drivers to use drm_of_find_panel_or_bridge

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: NRob Herring <robh@kernel.org>
Reviewed-by: NArchit Taneja <architt@codeaurora.org>
Tested-by: NPhilipp Zabel <p.zabel@pengutronix.de>
Acked-by: NMaxime Ripard <maxime.ripard@free-electrons.com>
[seanpaul dropped rockchip changes since they're now obsolete]
Signed-off-by: NSean Paul <seanpaul@chromium.org>
上级 86418f90
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_panel.h> #include <drm/drm_of.h>
#include "atmel_hlcdc_dc.h" #include "atmel_hlcdc_dc.h"
...@@ -152,29 +152,11 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = { ...@@ -152,29 +152,11 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .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, 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_dc *dc = dev->dev_private;
struct atmel_hlcdc_rgb_output *output; struct atmel_hlcdc_rgb_output *output;
struct device_node *np;
struct drm_panel *panel; struct drm_panel *panel;
struct drm_bridge *bridge; struct drm_bridge *bridge;
int ret; int ret;
...@@ -195,13 +177,11 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, ...@@ -195,13 +177,11 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
output->encoder.possible_crtcs = 0x1; output->encoder.possible_crtcs = 0x1;
np = of_graph_get_remote_port_parent(ep->local_node); ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge);
if (ret)
ret = -EPROBE_DEFER; return ret;
panel = of_drm_find_panel(np);
if (panel) { if (panel) {
of_node_put(np);
output->connector.dpms = DRM_MODE_DPMS_OFF; output->connector.dpms = DRM_MODE_DPMS_OFF;
output->connector.polled = DRM_CONNECTOR_POLL_CONNECT; output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
drm_connector_helper_add(&output->connector, drm_connector_helper_add(&output->connector,
...@@ -226,9 +206,6 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, ...@@ -226,9 +206,6 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
return 0; return 0;
} }
bridge = of_drm_find_bridge(np);
of_node_put(np);
if (bridge) { if (bridge) {
ret = drm_bridge_attach(&output->encoder, bridge, NULL); ret = drm_bridge_attach(&output->encoder, bridge, NULL);
if (!ret) if (!ret)
...@@ -243,31 +220,23 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, ...@@ -243,31 +220,23 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
int atmel_hlcdc_create_outputs(struct drm_device *dev) int atmel_hlcdc_create_outputs(struct drm_device *dev)
{ {
struct device_node *ep_np = NULL; struct device_node *remote;
struct of_endpoint ep; int ret, endpoint = 0;
int ret;
while (true) {
for_each_endpoint_of_node(dev->dev->of_node, ep_np) { /* Loop thru possible multiple connections to the output */
ret = of_graph_parse_endpoint(ep_np, &ep); remote = of_graph_get_remote_node(dev->dev->of_node, 0,
if (!ret) endpoint++);
ret = atmel_hlcdc_check_endpoint(dev, &ep); if (!remote)
break;
if (ret) {
of_node_put(ep_np); ret = atmel_hlcdc_attach_endpoint(dev, remote);
return ret; of_node_put(remote);
} if (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; return ret;
}
} }
return 0; if (!endpoint)
return -ENODEV;
return ret;
} }
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_graph.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include "drm_crtc.h" #include "drm_crtc.h"
...@@ -292,7 +292,6 @@ static int ptn3460_probe(struct i2c_client *client, ...@@ -292,7 +292,6 @@ static int ptn3460_probe(struct i2c_client *client,
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct ptn3460_bridge *ptn_bridge; struct ptn3460_bridge *ptn_bridge;
struct device_node *endpoint, *panel_node;
int ret; int ret;
ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL); ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
...@@ -300,16 +299,9 @@ static int ptn3460_probe(struct i2c_client *client, ...@@ -300,16 +299,9 @@ static int ptn3460_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
} }
endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ptn_bridge->panel, NULL);
if (endpoint) { if (ret)
panel_node = of_graph_get_remote_port_parent(endpoint); return ret;
if (panel_node) {
ptn_bridge->panel = of_drm_find_panel(panel_node);
of_node_put(panel_node);
if (!ptn_bridge->panel)
return -EPROBE_DEFER;
}
}
ptn_bridge->client = client; ptn_bridge->client = client;
......
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include "drmP.h" #include "drmP.h"
...@@ -536,7 +536,6 @@ static int ps8622_probe(struct i2c_client *client, ...@@ -536,7 +536,6 @@ static int ps8622_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct device_node *endpoint, *panel_node;
struct ps8622_bridge *ps8622; struct ps8622_bridge *ps8622;
int ret; int ret;
...@@ -544,16 +543,9 @@ static int ps8622_probe(struct i2c_client *client, ...@@ -544,16 +543,9 @@ static int ps8622_probe(struct i2c_client *client,
if (!ps8622) if (!ps8622)
return -ENOMEM; return -ENOMEM;
endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ps8622->panel, NULL);
if (endpoint) { if (ret)
panel_node = of_graph_get_remote_port_parent(endpoint); return ret;
if (panel_node) {
ps8622->panel = of_drm_find_panel(panel_node);
of_node_put(panel_node);
if (!ps8622->panel)
return -EPROBE_DEFER;
}
}
ps8622->client = client; ps8622->client = client;
......
...@@ -1244,7 +1244,6 @@ static const struct regmap_config tc_regmap_config = { ...@@ -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) static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct device_node *ep;
struct tc_data *tc; struct tc_data *tc;
int ret; int ret;
...@@ -1255,29 +1254,9 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -1255,29 +1254,9 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
tc->dev = dev; tc->dev = dev;
/* port@2 is the output port */ /* port@2 is the output port */
ep = of_graph_get_endpoint_by_regs(dev->of_node, 2, -1); ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &tc->panel, NULL);
if (ep) { if (ret)
struct device_node *remote; return ret;
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);
}
/* Shut down GPIO is optional */ /* Shut down GPIO is optional */
tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include <drm/bridge/analogix_dp.h> #include <drm/bridge/analogix_dp.h>
...@@ -211,8 +212,11 @@ static const struct component_ops exynos_dp_ops = { ...@@ -211,8 +212,11 @@ static const struct component_ops exynos_dp_ops = {
static int exynos_dp_probe(struct platform_device *pdev) static int exynos_dp_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = NULL, *endpoint = NULL; struct device_node *np;
struct exynos_dp_device *dp; 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), dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
GFP_KERNEL); GFP_KERNEL);
...@@ -236,28 +240,13 @@ static int exynos_dp_probe(struct platform_device *pdev) ...@@ -236,28 +240,13 @@ static int exynos_dp_probe(struct platform_device *pdev)
goto out; goto out;
} }
endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, &bridge);
if (endpoint) { if (ret)
np = of_graph_get_remote_port_parent(endpoint); return ret;
if (np) {
/* The remote port can be either a panel or a bridge */ /* The remote port can be either a panel or a bridge */
dp->plat_data.panel = of_drm_find_panel(np); dp->plat_data.panel = panel;
if (!dp->plat_data.panel) { dp->ptn_bridge = bridge;
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;
}
out: out:
return component_add(&pdev->dev, &exynos_dp_ops); return component_add(&pdev->dev, &exynos_dp_ops);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include "fsl_dcu_drm_drv.h" #include "fsl_dcu_drm_drv.h"
...@@ -141,32 +142,11 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev, ...@@ -141,32 +142,11 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
return ret; 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) int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
{ {
struct of_endpoint ep; struct device_node *panel_node;
struct device_node *ep_node, *panel_node; struct drm_panel *panel;
struct drm_bridge *bridge;
int ret; int ret;
/* This is for backward compatibility */ /* This is for backward compatibility */
...@@ -179,14 +159,14 @@ int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev) ...@@ -179,14 +159,14 @@ int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
} }
ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL); ret = drm_of_find_panel_or_bridge(fsl_dev->np, 0, 0, &panel, &bridge);
if (!ep_node)
return -ENODEV;
ret = of_graph_parse_endpoint(ep_node, &ep);
of_node_put(ep_node);
if (ret) 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);
} }
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/of_graph.h>
#include <drm/drm_of.h> #include <drm/drm_of.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
...@@ -754,34 +753,16 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi) ...@@ -754,34 +753,16 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
{ {
struct dsi_hw_ctx *ctx = dsi->ctx; struct dsi_hw_ctx *ctx = dsi->ctx;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct device_node *endpoint, *bridge_node;
struct drm_bridge *bridge;
struct resource *res; struct resource *res;
int ret;
/* /*
* Get the endpoint node. In our case, dsi has one output port1 * Get the endpoint node. In our case, dsi has one output port1
* to which the external HDMI bridge is connected. * to which the external HDMI bridge is connected.
*/ */
endpoint = of_graph_get_endpoint_by_regs(np, 1, -1); ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
if (!endpoint) { if (ret)
DRM_ERROR("no valid endpoint node\n"); return ret;
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;
ctx->pclk = devm_clk_get(&pdev->dev, "pclk"); ctx->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(ctx->pclk)) { if (IS_ERR(ctx->pclk)) {
......
...@@ -647,7 +647,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -647,7 +647,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
for_each_child_of_node(np, child) { for_each_child_of_node(np, child) {
struct imx_ldb_channel *channel; struct imx_ldb_channel *channel;
struct device_node *ep;
int bus_format; int bus_format;
ret = of_property_read_u32(child, "reg", &i); ret = of_property_read_u32(child, "reg", &i);
...@@ -671,27 +670,11 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -671,27 +670,11 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
* The output port is port@4 with an external 4-port mux or * The output port is port@4 with an external 4-port mux or
* port@2 with the internal 2-port mux. * port@2 with the internal 2-port mux.
*/ */
ep = of_graph_get_endpoint_by_regs(child, ret = drm_of_find_panel_or_bridge(child,
imx_ldb->lvds_mux ? 4 : 2, imx_ldb->lvds_mux ? 4 : 2, 0,
-1); &channel->panel, &channel->bridge);
if (ep) { if (ret)
struct device_node *remote; return ret;
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;
}
}
/* panel ddc only if there is no bridge */ /* panel ddc only if there is no bridge */
if (!channel->bridge) { if (!channel->bridge) {
......
...@@ -19,10 +19,10 @@ ...@@ -19,10 +19,10 @@
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <video/of_display_timing.h> #include <video/of_display_timing.h>
#include <linux/of_graph.h>
#include "imx-drm.h" #include "imx-drm.h"
...@@ -208,7 +208,6 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) ...@@ -208,7 +208,6 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
{ {
struct drm_device *drm = data; struct drm_device *drm = data;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct device_node *ep;
const u8 *edidp; const u8 *edidp;
struct imx_parallel_display *imxpd; struct imx_parallel_display *imxpd;
int ret; int ret;
...@@ -237,36 +236,9 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) ...@@ -237,36 +236,9 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
imxpd->bus_format = bus_format; imxpd->bus_format = bus_format;
/* port@1 is the output port */ /* port@1 is the output port */
ep = of_graph_get_endpoint_by_regs(np, 1, -1); ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel, &imxpd->bridge);
if (ep) { if (ret)
struct device_node *remote; return ret;
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);
}
imxpd->dev = dev; imxpd->dev = dev;
......
...@@ -16,11 +16,11 @@ ...@@ -16,11 +16,11 @@
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_mipi_dsi.h> #include <drm/drm_mipi_dsi.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include <drm/drm_of.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/of_graph.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <video/videomode.h> #include <video/videomode.h>
...@@ -801,7 +801,6 @@ static int mtk_dsi_probe(struct platform_device *pdev) ...@@ -801,7 +801,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
{ {
struct mtk_dsi *dsi; struct mtk_dsi *dsi;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *remote_node, *endpoint;
struct resource *regs; struct resource *regs;
int comp_id; int comp_id;
int ret; int ret;
...@@ -813,22 +812,10 @@ static int mtk_dsi_probe(struct platform_device *pdev) ...@@ -813,22 +812,10 @@ static int mtk_dsi_probe(struct platform_device *pdev)
dsi->host.ops = &mtk_dsi_ops; dsi->host.ops = &mtk_dsi_ops;
dsi->host.dev = dev; dsi->host.dev = dev;
endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
if (endpoint) { &dsi->panel, &dsi->bridge);
remote_node = of_graph_get_remote_port_parent(endpoint); if (ret)
if (!remote_node) { return ret;
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;
}
}
dsi->engine_clk = devm_clk_get(dev, "engine"); dsi->engine_clk = devm_clk_get(dev, "engine");
if (IS_ERR(dsi->engine_clk)) { if (IS_ERR(dsi->engine_clk)) {
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include <drm/drm_simple_kms_helper.h> #include <drm/drm_simple_kms_helper.h>
...@@ -82,20 +83,15 @@ static const struct drm_connector_funcs mxsfb_panel_connector_funcs = { ...@@ -82,20 +83,15 @@ static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
}; };
static int mxsfb_attach_endpoint(struct drm_device *drm, int mxsfb_create_output(struct drm_device *drm)
const struct of_endpoint *ep)
{ {
struct mxsfb_drm_private *mxsfb = drm->dev_private; struct mxsfb_drm_private *mxsfb = drm->dev_private;
struct device_node *np;
struct drm_panel *panel; struct drm_panel *panel;
int ret = -EPROBE_DEFER; int ret;
np = of_graph_get_remote_port_parent(ep->local_node);
panel = of_drm_find_panel(np);
of_node_put(np);
if (!panel) ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, NULL);
return -EPROBE_DEFER; if (ret)
return ret;
mxsfb->connector.dpms = DRM_MODE_DPMS_OFF; mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
mxsfb->connector.polled = 0; mxsfb->connector.polled = 0;
...@@ -109,27 +105,3 @@ static int mxsfb_attach_endpoint(struct drm_device *drm, ...@@ -109,27 +105,3 @@ static int mxsfb_attach_endpoint(struct drm_device *drm,
return ret; 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;
}
...@@ -428,31 +428,13 @@ static const struct component_ops rockchip_dp_component_ops = { ...@@ -428,31 +428,13 @@ static const struct component_ops rockchip_dp_component_ops = {
static int rockchip_dp_probe(struct platform_device *pdev) static int rockchip_dp_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *panel_node, *port, *endpoint;
struct drm_panel *panel = NULL; struct drm_panel *panel = NULL;
struct rockchip_dp_device *dp; struct rockchip_dp_device *dp;
int ret;
port = of_graph_get_port_by_id(dev->of_node, 1); ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
if (port) { if (ret)
endpoint = of_get_child_by_name(port, "endpoint"); return ret;
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;
}
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
if (!dp) if (!dp)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include "sun4i_drv.h" #include "sun4i_drv.h"
...@@ -218,9 +219,9 @@ int sun4i_rgb_init(struct drm_device *drm) ...@@ -218,9 +219,9 @@ int sun4i_rgb_init(struct drm_device *drm)
rgb->drv = drv; rgb->drv = drv;
encoder = &rgb->encoder; encoder = &rgb->encoder;
tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node); ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
bridge = sun4i_tcon_find_bridge(tcon->dev->of_node); &tcon->panel, &bridge);
if (IS_ERR(tcon->panel) && IS_ERR(bridge)) { if (ret) {
dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n"); dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
return 0; return 0;
} }
...@@ -240,7 +241,7 @@ int sun4i_rgb_init(struct drm_device *drm) ...@@ -240,7 +241,7 @@ int sun4i_rgb_init(struct drm_device *drm)
/* The RGB encoder can only work with the TCON channel 0 */ /* The RGB encoder can only work with the TCON channel 0 */
rgb->encoder.possible_crtcs = BIT(0); rgb->encoder.possible_crtcs = BIT(0);
if (!IS_ERR(tcon->panel)) { if (tcon->panel) {
drm_connector_helper_add(&rgb->connector, drm_connector_helper_add(&rgb->connector,
&sun4i_rgb_con_helper_funcs); &sun4i_rgb_con_helper_funcs);
ret = drm_connector_init(drm, &rgb->connector, ret = drm_connector_init(drm, &rgb->connector,
...@@ -261,7 +262,7 @@ int sun4i_rgb_init(struct drm_device *drm) ...@@ -261,7 +262,7 @@ int sun4i_rgb_init(struct drm_device *drm)
} }
} }
if (!IS_ERR(bridge)) { if (bridge) {
ret = drm_bridge_attach(encoder, bridge, NULL); ret = drm_bridge_attach(encoder, bridge, NULL);
if (ret) { if (ret) {
dev_err(drm->dev, "Couldn't attach our bridge\n"); dev_err(drm->dev, "Couldn't attach our bridge\n");
......
...@@ -15,13 +15,12 @@ ...@@ -15,13 +15,12 @@
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_modes.h> #include <drm/drm_modes.h>
#include <drm/drm_panel.h> #include <drm/drm_of.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/reset.h> #include <linux/reset.h>
...@@ -405,74 +404,6 @@ static int sun4i_tcon_init_regmap(struct device *dev, ...@@ -405,74 +404,6 @@ static int sun4i_tcon_init_regmap(struct device *dev,
return 0; 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, static int sun4i_tcon_bind(struct device *dev, struct device *master,
void *data) void *data)
{ {
...@@ -555,22 +486,11 @@ static int sun4i_tcon_probe(struct platform_device *pdev) ...@@ -555,22 +486,11 @@ static int sun4i_tcon_probe(struct platform_device *pdev)
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
struct drm_bridge *bridge; struct drm_bridge *bridge;
struct drm_panel *panel; struct drm_panel *panel;
int ret;
/* ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
* Neither the bridge or the panel is ready. if (ret == -EPROBE_DEFER)
* Defer the probe. return ret;
*/
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;
}
return component_add(&pdev->dev, &sun4i_tcon_ops); return component_add(&pdev->dev, &sun4i_tcon_ops);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册