2024-03-11 08:58:21

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v3 0/5] drm/bridge: Allow using fwnode API to get the next bridge

Currently, the various drm bridge drivers relay on OF infrastructures to
works very well. Yet there are platforms and/or devices absence of OF
support. Such as virtual display drivers, USB display apapters and ACPI
based systems etc.

Add fwnode based helpers to fill the niche, this allows part of the drm
display bridge drivers to work across systems. As the fwnode based API
has wider coverage than DT and the fwnode graphs are compatible with
the OF graph, so the provided helpers can be used on all systems in theory.
Assumed that the system has valid fwnode graphs established before the
drm bridge driver is probed, and there is a fwnode assigned to the instance
of specific drm bridge driver.

Tested on TI BeaglePlay board and other platforms.

v1 -> v2:
* Modify it66121 to switch togather
* Drop the 'side-by-side' implement
* Add drm_bridge_find_next_bridge_by_fwnode() helper
* Add drm_bridge_set_node() helper

v2 -> v3:
* Read kernel-doc and improve function comments
* Drop the 'port' argument of it66121_read_bus_width() (Dmitry)
* Do more by covertering the sii902x drm bridge drviers

Sui Jingfeng (5):
drm/bridge: Add fwnode based helpers to get the next bridge
drm/bridge: simple-bridge: Use fwnode API to acquire device properties
drm-bridge: display-connector: Use fwnode API to acquire device
properties
drm-bridge: it66121: Use fwnode API to acquire device properties
drm-bridge: sii902x: Use fwnode API to acquire device properties

drivers/gpu/drm/bridge/display-connector.c | 24 ++++----
drivers/gpu/drm/bridge/ite-it66121.c | 63 ++++++++++---------
drivers/gpu/drm/bridge/sii902x.c | 43 +++++--------
drivers/gpu/drm/bridge/simple-bridge.c | 22 +++----
drivers/gpu/drm/drm_bridge.c | 72 ++++++++++++++++++++++
include/drm/drm_bridge.h | 16 +++++
6 files changed, 159 insertions(+), 81 deletions(-)


base-commit: 3fde6df89bac97416ce1c82b14237a1a67ce3285
--
2.34.1



2024-03-11 08:58:42

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v3 1/5] drm/bridge: Allow using fwnode API to get the next bridge

Currently, the various drm bridge drivers relay on OF infrastructures to
works very well. Yet there are platforms and/or devices absence of OF
support. Such as virtual display drivers, USB display apapters and ACPI
based systems etc.

Add fwnode based helpers to fill the niche, this allows part of the drm
display bridge drivers to work across systems. As the fwnode based API
has wider coverage than DT and the fwnode graphs are compatible with
the OF graph, so the provided helpers can be used on all systems in theory.
Assumed that the system has valid fwnode graphs established before the
drm bridge driver is probed, and there is a fwnode assigned to the instance
of specific drm bridge driver.

Signed-off-by: Sui Jingfeng <[email protected]>
---
drivers/gpu/drm/drm_bridge.c | 72 ++++++++++++++++++++++++++++++++++++
include/drm/drm_bridge.h | 16 ++++++++
2 files changed, 88 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 28abe9aa99ca..ffc6162e2517 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -1368,6 +1368,78 @@ struct drm_bridge *of_drm_find_bridge(struct device_node *np)
EXPORT_SYMBOL(of_drm_find_bridge);
#endif

+/**
+ * drm_bridge_find_by_fwnode - Find the bridge corresponding to the fwnode
+ *
+ * @fwnode: fwnode for which to find the matching drm_bridge
+ *
+ * This function looks up a drm_bridge in the global bridge list, based on
+ * its associated fwnode. Drivers who want to use this function should has
+ * fwnode handle assigned to the fwnode member of the struct drm_bridge
+ * instance.
+ *
+ * Return:
+ * A reference to the drm_bridge if found, return NULL otherwise.
+ */
+struct drm_bridge *drm_bridge_find_by_fwnode(struct fwnode_handle *fwnode)
+{
+ struct drm_bridge *ret = NULL;
+ struct drm_bridge *bridge;
+
+ if (!fwnode)
+ return NULL;
+
+ mutex_lock(&bridge_lock);
+
+ list_for_each_entry(bridge, &bridge_list, list) {
+ if (bridge->fwnode == fwnode) {
+ ret = bridge;
+ break;
+ }
+ }
+
+ mutex_unlock(&bridge_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(drm_bridge_find_by_fwnode);
+
+/**
+ * drm_bridge_find_next_bridge_by_fwnode - Find the next bridge by fwnode
+ * @fwnode: fwnode pointer to the current device.
+ * @port: identifier of the port node of the next bridge is connected.
+ *
+ * This function find the next bridge at the current node, it assumed that
+ * that there has valid fwnode graph established.
+ *
+ * Return:
+ * A reference to the drm_bridge if found.
+ * %NULL if not found or the next bridge is not finish probe yet.
+ * A negative error code otherwise.
+ */
+struct drm_bridge *
+drm_bridge_find_next_bridge_by_fwnode(struct fwnode_handle *fwnode, u32 port)
+{
+ struct drm_bridge *bridge;
+ struct fwnode_handle *ep;
+ struct fwnode_handle *remote;
+
+ ep = fwnode_graph_get_endpoint_by_id(fwnode, port, 0, 0);
+ if (!ep)
+ return ERR_PTR(-EINVAL);
+
+ remote = fwnode_graph_get_remote_port_parent(ep);
+ fwnode_handle_put(ep);
+ if (!remote)
+ return ERR_PTR(-ENODEV);
+
+ bridge = drm_bridge_find_by_fwnode(remote);
+ fwnode_handle_put(remote);
+
+ return bridge;
+}
+EXPORT_SYMBOL_GPL(drm_bridge_find_next_bridge_by_fwnode);
+
MODULE_AUTHOR("Ajay Kumar <[email protected]>");
MODULE_DESCRIPTION("DRM bridge infrastructure");
MODULE_LICENSE("GPL and additional rights");
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 3606e1a7f965..d4c95afdd662 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -26,6 +26,7 @@
#include <linux/ctype.h>
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/of.h>

#include <drm/drm_atomic.h>
#include <drm/drm_encoder.h>
@@ -721,6 +722,8 @@ struct drm_bridge {
struct list_head chain_node;
/** @of_node: device node pointer to the bridge */
struct device_node *of_node;
+ /** @fwnode: fwnode pointer to the bridge */
+ struct fwnode_handle *fwnode;
/** @list: to keep track of all added bridges */
struct list_head list;
/**
@@ -788,6 +791,13 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
struct drm_bridge *previous,
enum drm_bridge_attach_flags flags);

+static inline void
+drm_bridge_set_node(struct drm_bridge *bridge, struct fwnode_handle *fwnode)
+{
+ bridge->fwnode = fwnode;
+ bridge->of_node = to_of_node(fwnode);
+}
+
#ifdef CONFIG_OF
struct drm_bridge *of_drm_find_bridge(struct device_node *np);
#else
@@ -797,6 +807,12 @@ static inline struct drm_bridge *of_drm_find_bridge(struct device_node *np)
}
#endif

+struct drm_bridge *
+drm_bridge_find_by_fwnode(struct fwnode_handle *fwnode);
+
+struct drm_bridge *
+drm_bridge_find_next_bridge_by_fwnode(struct fwnode_handle *fwnode, u32 port);
+
/**
* drm_bridge_get_next_bridge() - Get the next bridge in the chain
* @bridge: bridge object
--
2.34.1


2024-03-11 08:59:02

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v3 2/5] drm/bridge: simple-bridge: Use fwnode API to acquire device properties

Make this driver less DT-dependent by calling the freshly created helpers,
should be no functional changes for DT based systems. But open the door for
otherwise use cases. Even though there is no user emerged yet, this still
do no harms.

Signed-off-by: Sui Jingfeng <[email protected]>
---
drivers/gpu/drm/bridge/simple-bridge.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
index 5813a2c4fc5e..3b09bdd5ad4d 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -9,7 +9,6 @@
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>

@@ -169,33 +168,32 @@ static const struct drm_bridge_funcs simple_bridge_bridge_funcs = {

static int simple_bridge_probe(struct platform_device *pdev)
{
+ struct fwnode_handle *fwnode = dev_fwnode(&pdev->dev);
struct simple_bridge *sbridge;
- struct device_node *remote;
+ int ret;

sbridge = devm_kzalloc(&pdev->dev, sizeof(*sbridge), GFP_KERNEL);
if (!sbridge)
return -ENOMEM;
platform_set_drvdata(pdev, sbridge);

- sbridge->info = of_device_get_match_data(&pdev->dev);
+ sbridge->info = device_get_match_data(&pdev->dev);

/* Get the next bridge in the pipeline. */
- remote = of_graph_get_remote_node(pdev->dev.of_node, 1, -1);
- if (!remote)
- return -EINVAL;
-
- sbridge->next_bridge = of_drm_find_bridge(remote);
- of_node_put(remote);
-
+ sbridge->next_bridge = drm_bridge_find_next_bridge_by_fwnode(fwnode, 1);
if (!sbridge->next_bridge) {
dev_dbg(&pdev->dev, "Next bridge not found, deferring probe\n");
return -EPROBE_DEFER;
+ } else if (IS_ERR(sbridge->next_bridge)) {
+ ret = PTR_ERR(sbridge->next_bridge);
+ dev_err(&pdev->dev, "Error on finding the next bridge: %d\n", ret);
+ return ret;
}

/* Get the regulator and GPIO resources. */
sbridge->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
if (IS_ERR(sbridge->vdd)) {
- int ret = PTR_ERR(sbridge->vdd);
+ ret = PTR_ERR(sbridge->vdd);
if (ret == -EPROBE_DEFER)
return -EPROBE_DEFER;
sbridge->vdd = NULL;
@@ -210,9 +208,9 @@ static int simple_bridge_probe(struct platform_device *pdev)

/* Register the bridge. */
sbridge->bridge.funcs = &simple_bridge_bridge_funcs;
- sbridge->bridge.of_node = pdev->dev.of_node;
sbridge->bridge.timings = sbridge->info->timings;

+ drm_bridge_set_node(&sbridge->bridge, fwnode);
drm_bridge_add(&sbridge->bridge);

return 0;
--
2.34.1


2024-03-11 08:59:24

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v3 3/5] drm-bridge: display-connector: Use fwnode API to acquire device properties

Make this driver less DT-dependent by using the fwnode helper function,
should be no functional changes for DT based systems. Do the necessary
works before it can be truely subsystem independent, even though there
is no user yet, this still do no harms.

Signed-off-by: Sui Jingfeng <[email protected]>
---
drivers/gpu/drm/bridge/display-connector.c | 24 +++++++++++-----------
1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c
index ab8e00baf3f1..d80cb7bc59e6 100644
--- a/drivers/gpu/drm/bridge/display-connector.c
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -204,6 +204,7 @@ static int display_connector_get_supply(struct platform_device *pdev,

static int display_connector_probe(struct platform_device *pdev)
{
+ struct fwnode_handle *fwnode = dev_fwnode(&pdev->dev);
struct display_connector *conn;
unsigned int type;
const char *label = NULL;
@@ -215,15 +216,15 @@ static int display_connector_probe(struct platform_device *pdev)

platform_set_drvdata(pdev, conn);

- type = (uintptr_t)of_device_get_match_data(&pdev->dev);
+ type = (uintptr_t)device_get_match_data(&pdev->dev);

/* Get the exact connector type. */
switch (type) {
case DRM_MODE_CONNECTOR_DVII: {
bool analog, digital;

- analog = of_property_read_bool(pdev->dev.of_node, "analog");
- digital = of_property_read_bool(pdev->dev.of_node, "digital");
+ analog = fwnode_property_present(fwnode, "analog");
+ digital = fwnode_property_present(fwnode, "digital");
if (analog && !digital) {
conn->bridge.type = DRM_MODE_CONNECTOR_DVIA;
} else if (!analog && digital) {
@@ -240,8 +241,7 @@ static int display_connector_probe(struct platform_device *pdev)
case DRM_MODE_CONNECTOR_HDMIA: {
const char *hdmi_type;

- ret = of_property_read_string(pdev->dev.of_node, "type",
- &hdmi_type);
+ ret = fwnode_property_read_string(fwnode, "type", &hdmi_type);
if (ret < 0) {
dev_err(&pdev->dev, "HDMI connector with no type\n");
return -EINVAL;
@@ -271,7 +271,7 @@ static int display_connector_probe(struct platform_device *pdev)
conn->bridge.interlace_allowed = true;

/* Get the optional connector label. */
- of_property_read_string(pdev->dev.of_node, "label", &label);
+ fwnode_property_read_string(fwnode, "label", &label);

/*
* Get the HPD GPIO for DVI, HDMI and DP connectors. If the GPIO can provide
@@ -309,12 +309,12 @@ static int display_connector_probe(struct platform_device *pdev)
if (type == DRM_MODE_CONNECTOR_DVII ||
type == DRM_MODE_CONNECTOR_HDMIA ||
type == DRM_MODE_CONNECTOR_VGA) {
- struct device_node *phandle;
+ struct fwnode_handle *phandle;

- phandle = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
- if (phandle) {
- conn->bridge.ddc = of_get_i2c_adapter_by_node(phandle);
- of_node_put(phandle);
+ phandle = fwnode_find_reference(fwnode, "ddc-i2c-bus", 0);
+ if (!IS_ERR_OR_NULL(phandle)) {
+ conn->bridge.ddc = i2c_get_adapter_by_fwnode(phandle);
+ fwnode_handle_put(phandle);
if (!conn->bridge.ddc)
return -EPROBE_DEFER;
} else {
@@ -358,7 +358,7 @@ static int display_connector_probe(struct platform_device *pdev)
}

conn->bridge.funcs = &display_connector_bridge_funcs;
- conn->bridge.of_node = pdev->dev.of_node;
+ drm_bridge_set_node(&conn->bridge, fwnode);

if (conn->bridge.ddc)
conn->bridge.ops |= DRM_BRIDGE_OP_EDID
--
2.34.1


2024-03-11 08:59:28

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v3 4/5] drm-bridge: it66121: Use fwnode API to acquire device properties

Make this driver less DT-dependent by calling the freshly created helpers,
should be no functional changes for DT based systems. But open the door for
otherwise use cases. Even though there is no user emerged yet, this still
do no harms. In fact, we reduce boilerplate across drm bridge drivers.

Signed-off-by: Sui Jingfeng <[email protected]>
---
drivers/gpu/drm/bridge/ite-it66121.c | 63 +++++++++++++++-------------
1 file changed, 35 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c
index 1c3433b5e366..a04d755fed4c 100644
--- a/drivers/gpu/drm/bridge/ite-it66121.c
+++ b/drivers/gpu/drm/bridge/ite-it66121.c
@@ -15,7 +15,6 @@
#include <linux/bitfield.h>
#include <linux/property.h>
#include <linux/regmap.h>
-#include <linux/of_graph.h>
#include <linux/gpio/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>
@@ -1480,7 +1479,7 @@ static int it66121_audio_codec_init(struct it66121_ctx *ctx, struct device *dev)

dev_dbg(dev, "%s\n", __func__);

- if (!of_property_read_bool(dev->of_node, "#sound-dai-cells")) {
+ if (!fwnode_property_present(dev_fwnode(dev), "#sound-dai-cells")) {
dev_info(dev, "No \"#sound-dai-cells\", no audio\n");
return 0;
}
@@ -1503,13 +1502,36 @@ static const char * const it66121_supplies[] = {
"vcn33", "vcn18", "vrf12"
};

+static int it66121_read_bus_width(struct fwnode_handle *fwnode, u32 *bus_width)
+{
+ struct fwnode_handle *endpoint;
+ u32 val;
+ int ret;
+
+ endpoint = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0, 0);
+ if (!endpoint)
+ return -EINVAL;
+
+ ret = fwnode_property_read_u32(endpoint, "bus-width", &val);
+ fwnode_handle_put(endpoint);
+ if (ret)
+ return ret;
+
+ if (val != 12 && val != 24)
+ return -EINVAL;
+
+ *bus_width = val;
+
+ return 0;
+}
+
static int it66121_probe(struct i2c_client *client)
{
u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 };
- struct device_node *ep;
int ret;
struct it66121_ctx *ctx;
struct device *dev = &client->dev;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);

if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(dev, "I2C check functionality failed.\n");
@@ -1520,35 +1542,20 @@ static int it66121_probe(struct i2c_client *client)
if (!ctx)
return -ENOMEM;

- ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0);
- if (!ep)
- return -EINVAL;
-
ctx->dev = dev;
ctx->client = client;
ctx->info = i2c_get_match_data(client);

- of_property_read_u32(ep, "bus-width", &ctx->bus_width);
- of_node_put(ep);
-
- if (ctx->bus_width != 12 && ctx->bus_width != 24)
- return -EINVAL;
-
- ep = of_graph_get_remote_node(dev->of_node, 1, -1);
- if (!ep) {
- dev_err(ctx->dev, "The endpoint is unconnected\n");
- return -EINVAL;
- }
-
- if (!of_device_is_available(ep)) {
- of_node_put(ep);
- dev_err(ctx->dev, "The remote device is disabled\n");
- return -ENODEV;
- }
+ ret = it66121_read_bus_width(fwnode, &ctx->bus_width);
+ if (ret)
+ return ret;

- ctx->next_bridge = of_drm_find_bridge(ep);
- of_node_put(ep);
- if (!ctx->next_bridge) {
+ ctx->next_bridge = drm_bridge_find_next_bridge_by_fwnode(fwnode, 1);
+ if (IS_ERR(ctx->next_bridge)) {
+ ret = PTR_ERR(ctx->next_bridge);
+ dev_err(dev, "Error in founding the next bridge: %d\n", ret);
+ return ret;
+ } else if (!ctx->next_bridge) {
dev_dbg(ctx->dev, "Next bridge not found, deferring probe\n");
return -EPROBE_DEFER;
}
@@ -1584,9 +1591,9 @@ static int it66121_probe(struct i2c_client *client)
}

ctx->bridge.funcs = &it66121_bridge_funcs;
- ctx->bridge.of_node = dev->of_node;
ctx->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
ctx->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
+ drm_bridge_set_node(&ctx->bridge, fwnode);

ret = devm_request_threaded_irq(dev, client->irq, NULL, it66121_irq_threaded_handler,
IRQF_ONESHOT, dev_name(dev), ctx);
--
2.34.1


2024-03-11 08:59:42

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v3 5/5] drm-bridge: sii902x: Use fwnode API to acquire device properties

Make this driver less DT-dependent by calling the freshly created helpers
and other manually improve. Should be no functional changes for DT based
systems, but do helps to reduce boilerplate.

Signed-off-by: Sui Jingfeng <[email protected]>
---
drivers/gpu/drm/bridge/sii902x.c | 43 +++++++++++---------------------
1 file changed, 14 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 8f84e98249c7..04436f318c7f 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -827,20 +827,19 @@ static int sii902x_audio_codec_init(struct sii902x *sii902x,
.spdif = 0,
.max_i2s_channels = 0,
};
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
u8 lanes[4];
int num_lanes, i;

- if (!of_property_read_bool(dev->of_node, "#sound-dai-cells")) {
+ if (!fwnode_property_present(fwnode, "#sound-dai-cells")) {
dev_dbg(dev, "%s: No \"#sound-dai-cells\", no audio\n",
__func__);
return 0;
}

- num_lanes = of_property_read_variable_u8_array(dev->of_node,
- "sil,i2s-data-lanes",
- lanes, 1,
- ARRAY_SIZE(lanes));
-
+ num_lanes = fwnode_property_read_u8_array(fwnode,
+ "sil,i2s-data-lanes",
+ lanes, ARRAY_SIZE(lanes));
if (num_lanes == -EINVAL) {
dev_dbg(dev,
"%s: No \"sil,i2s-data-lanes\", use default <0>\n",
@@ -1097,13 +1096,13 @@ static int sii902x_init(struct sii902x *sii902x)
goto err_unreg_audio;

sii902x->bridge.funcs = &sii902x_bridge_funcs;
- sii902x->bridge.of_node = dev->of_node;
sii902x->bridge.timings = &default_sii902x_timings;
sii902x->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID;

if (sii902x->i2c->irq > 0)
sii902x->bridge.ops |= DRM_BRIDGE_OP_HPD;

+ drm_bridge_set_node(&sii902x->bridge, dev_fwnode(dev));
drm_bridge_add(&sii902x->bridge);

return 0;
@@ -1118,7 +1117,6 @@ static int sii902x_init(struct sii902x *sii902x)
static int sii902x_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
- struct device_node *endpoint;
struct sii902x *sii902x;
static const char * const supplies[] = {"iovcc", "cvcc12"};
int ret;
@@ -1147,27 +1145,14 @@ static int sii902x_probe(struct i2c_client *client)
return PTR_ERR(sii902x->reset_gpio);
}

- endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
- if (endpoint) {
- struct device_node *remote = of_graph_get_remote_port_parent(endpoint);
-
- of_node_put(endpoint);
- if (!remote) {
- dev_err(dev, "Endpoint in port@1 unconnected\n");
- return -ENODEV;
- }
-
- if (!of_device_is_available(remote)) {
- dev_err(dev, "port@1 remote device is disabled\n");
- of_node_put(remote);
- return -ENODEV;
- }
-
- sii902x->next_bridge = of_drm_find_bridge(remote);
- of_node_put(remote);
- if (!sii902x->next_bridge)
- return dev_err_probe(dev, -EPROBE_DEFER,
- "Failed to find remote bridge\n");
+ sii902x->next_bridge = drm_bridge_find_next_bridge_by_fwnode(dev_fwnode(dev), 1);
+ if (!sii902x->next_bridge) {
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "Failed to find the next bridge\n");
+ } else if (IS_ERR(sii902x->next_bridge)) {
+ ret = PTR_ERR(sii902x->next_bridge);
+ dev_err(dev, "Error on find the next bridge: %d\n", ret);
+ return ret;
}

mutex_init(&sii902x->mutex);
--
2.34.1