On Thu Jun 25 11:33:02 2026 +0300, Svyatoslav Ryhel wrote:
> The existing tegra_vi_graph_build function relies heavily on a one-to-one
> match between Device Tree nodes and media pad links. While this works for
> simpler configurations, it causes issues when Device Tree nodes do not
> match media pad link logic (e.g., mt9m114). Switch to the
> media_entity_get_fwnode_pad helper to verify and retrieve the correct pad
> linked to an endpoint, rather than assuming the endpoint ID matches the
> pad ID.
> 
> Tested-by: Luca Ceresoli <[email protected]> # tegra20, parallel 
> camera
> Signed-off-by: Svyatoslav Ryhel <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/staging/media/tegra-video/vi.c | 78 +++++++++++++++-------------------
 1 file changed, 35 insertions(+), 43 deletions(-)

---

diff --git a/drivers/staging/media/tegra-video/vi.c 
b/drivers/staging/media/tegra-video/vi.c
index 456134a9e8cf..ce09949178f6 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -1468,7 +1468,6 @@ static int tegra_vi_graph_build(struct tegra_vi_channel 
*chan,
        struct tegra_vi *vi = chan->vi;
        struct tegra_vi_graph_entity *ent;
        struct fwnode_handle *ep = NULL;
-       struct v4l2_fwnode_link link;
        struct media_entity *local = entity->entity;
        struct media_entity *remote;
        struct media_pad *local_pad;
@@ -1478,70 +1477,64 @@ static int tegra_vi_graph_build(struct tegra_vi_channel 
*chan,
 
        dev_dbg(vi->dev, "creating links for entity %s\n", local->name);
 
-       while (1) {
-               ep = fwnode_graph_get_next_endpoint(entity->asd.match.fwnode,
-                                                   ep);
-               if (!ep)
-                       break;
+       fwnode_graph_for_each_endpoint(entity->asd.match.fwnode, ep) {
+               struct fwnode_handle *remote_parent __free(fwnode_handle) = 
NULL;
+               struct fwnode_handle *sink_ep __free(fwnode_handle) = NULL;
+               int src_idx, sink_idx;
 
-               ret = v4l2_fwnode_parse_link(ep, &link);
-               if (ret < 0) {
-                       dev_err(vi->dev, "failed to parse link for %pOF: %d\n",
-                               to_of_node(ep), ret);
+               src_idx = media_entity_get_fwnode_pad(local, ep,
+                                                     MEDIA_PAD_FL_SOURCE);
+               if (src_idx < 0) {
+                       dev_dbg(vi->dev, "no source pad found for %pfw\n", ep);
                        continue;
                }
 
-               if (link.local_port >= local->num_pads) {
-                       dev_err(vi->dev, "invalid port number %u on %pOF\n",
-                               link.local_port, to_of_node(link.local_node));
-                       v4l2_fwnode_put_link(&link);
-                       ret = -EINVAL;
-                       break;
+               remote_parent = fwnode_graph_get_remote_port_parent(ep);
+               if (!remote_parent) {
+                       dev_dbg(vi->dev, "no remote parent found for %pfw\n",
+                               ep);
+                       continue;
                }
 
-               local_pad = &local->pads[link.local_port];
+               local_pad = &local->pads[src_idx];
                /* Remote node is vi node. So use channel video entity and pad
                 * as remote/sink.
                 */
-               if (link.remote_node == of_fwnode_handle(vi->dev->of_node)) {
+               if (remote_parent == of_fwnode_handle(vi->dev->of_node)) {
                        remote = &chan->video.entity;
                        remote_pad = &chan->pad;
                        goto create_link;
                }
 
-               /*
-                * Skip sink ports, they will be processed from the other end
-                * of the link.
-                */
-               if (local_pad->flags & MEDIA_PAD_FL_SINK) {
-                       dev_dbg(vi->dev, "skipping sink port %pOF:%u\n",
-                               to_of_node(link.local_node), link.local_port);
-                       v4l2_fwnode_put_link(&link);
-                       continue;
-               }
-
                /* find the remote entity from notifier list */
                ent = tegra_vi_graph_find_entity(&chan->notifier.done_list,
-                                                link.remote_node);
+                                                remote_parent);
                if (!ent) {
-                       dev_err(vi->dev, "no entity found for %pOF\n",
-                               to_of_node(link.remote_node));
-                       v4l2_fwnode_put_link(&link);
+                       fwnode_handle_put(ep);
+                       dev_err(vi->dev, "no entity found for %pfw\n",
+                               remote_parent);
                        ret = -ENODEV;
                        break;
                }
 
                remote = ent->entity;
-               if (link.remote_port >= remote->num_pads) {
-                       dev_err(vi->dev, "invalid port number %u on %pOF\n",
-                               link.remote_port,
-                               to_of_node(link.remote_node));
-                       v4l2_fwnode_put_link(&link);
-                       ret = -EINVAL;
-                       break;
+
+               sink_ep = fwnode_graph_get_remote_endpoint(ep);
+               if (!sink_ep) {
+                       dev_dbg(vi->dev, "no sink ep found for %pfw\n",
+                               ep);
+                       continue;
+               }
+
+               sink_idx = media_entity_get_fwnode_pad(remote, sink_ep,
+                                                      MEDIA_PAD_FL_SINK);
+               if (sink_idx < 0) {
+                       dev_dbg(vi->dev, "no sink pad found for %pfw\n",
+                               sink_ep);
+                       continue;
                }
 
-               remote_pad = &remote->pads[link.remote_port];
+               remote_pad = &remote->pads[sink_idx];
 
 create_link:
                dev_dbg(vi->dev, "creating %s:%u -> %s:%u link\n",
@@ -1551,8 +1544,8 @@ create_link:
                ret = media_create_pad_link(local, local_pad->index,
                                            remote, remote_pad->index,
                                            link_flags);
-               v4l2_fwnode_put_link(&link);
                if (ret < 0) {
+                       fwnode_handle_put(ep);
                        dev_err(vi->dev,
                                "failed to create %s:%u -> %s:%u link: %d\n",
                                local->name, local_pad->index,
@@ -1561,7 +1554,6 @@ create_link:
                }
        }
 
-       fwnode_handle_put(ep);
        return ret;
 }
 
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to