mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
staging: media: tegra-video: vi: Improve media graph building logic
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 <luca.ceresoli@bootlin.com> # tegra20, parallel camera Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
committed by
Hans Verkuil
parent
e1880f52cb
commit
dd5f981d02
@@ -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;
|
||||
}
|
||||
|
||||
remote_pad = &remote->pads[link.remote_port];
|
||||
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[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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user