This source file includes following definitions.
- imx_media_of_add_csi
- imx_media_add_of_subdevs
- create_of_link
- imx_media_create_of_links
- imx_media_create_csi_of_links
1
2
3
4
5
6
7
8
9 #include <linux/of_platform.h>
10 #include <media/v4l2-ctrls.h>
11 #include <media/v4l2-device.h>
12 #include <media/v4l2-fwnode.h>
13 #include <media/v4l2-subdev.h>
14 #include <media/videobuf2-dma-contig.h>
15 #include <linux/of_graph.h>
16 #include <video/imx-ipu-v3.h>
17 #include "imx-media.h"
18
19 int imx_media_of_add_csi(struct imx_media_dev *imxmd,
20 struct device_node *csi_np)
21 {
22 struct v4l2_async_subdev *asd;
23 int ret = 0;
24
25 if (!of_device_is_available(csi_np)) {
26 dev_dbg(imxmd->md.dev, "%s: %pOFn not enabled\n", __func__,
27 csi_np);
28 return -ENODEV;
29 }
30
31
32 asd = v4l2_async_notifier_add_fwnode_subdev(&imxmd->notifier,
33 of_fwnode_handle(csi_np),
34 sizeof(*asd));
35 if (IS_ERR(asd)) {
36 ret = PTR_ERR(asd);
37 if (ret == -EEXIST)
38 dev_dbg(imxmd->md.dev, "%s: already added %pOFn\n",
39 __func__, csi_np);
40 }
41
42 return ret;
43 }
44 EXPORT_SYMBOL_GPL(imx_media_of_add_csi);
45
46 int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
47 struct device_node *np)
48 {
49 struct device_node *csi_np;
50 int i, ret;
51
52 for (i = 0; ; i++) {
53 csi_np = of_parse_phandle(np, "ports", i);
54 if (!csi_np)
55 break;
56
57 ret = imx_media_of_add_csi(imxmd, csi_np);
58 if (ret) {
59
60 if (ret == -ENODEV || ret == -EEXIST) {
61 of_node_put(csi_np);
62 continue;
63 }
64
65
66 goto err_out;
67 }
68 }
69
70 return 0;
71
72 err_out:
73 of_node_put(csi_np);
74 return ret;
75 }
76 EXPORT_SYMBOL_GPL(imx_media_add_of_subdevs);
77
78
79
80
81
82
83
84
85 static int create_of_link(struct imx_media_dev *imxmd,
86 struct v4l2_subdev *sd,
87 struct v4l2_fwnode_link *link)
88 {
89 struct v4l2_subdev *remote, *src, *sink;
90 int src_pad, sink_pad;
91
92 if (link->local_port >= sd->entity.num_pads)
93 return -EINVAL;
94
95 remote = imx_media_find_subdev_by_fwnode(imxmd, link->remote_node);
96 if (!remote)
97 return 0;
98
99 if (sd->entity.pads[link->local_port].flags & MEDIA_PAD_FL_SINK) {
100 src = remote;
101 src_pad = link->remote_port;
102 sink = sd;
103 sink_pad = link->local_port;
104 } else {
105 src = sd;
106 src_pad = link->local_port;
107 sink = remote;
108 sink_pad = link->remote_port;
109 }
110
111
112 if (media_entity_find_link(&src->entity.pads[src_pad],
113 &sink->entity.pads[sink_pad]))
114 return 0;
115
116 v4l2_info(sd->v4l2_dev, "%s:%d -> %s:%d\n",
117 src->name, src_pad, sink->name, sink_pad);
118
119 return media_create_pad_link(&src->entity, src_pad,
120 &sink->entity, sink_pad, 0);
121 }
122
123
124
125
126 int imx_media_create_of_links(struct imx_media_dev *imxmd,
127 struct v4l2_subdev *sd)
128 {
129 struct v4l2_fwnode_link link;
130 struct device_node *ep;
131 int ret;
132
133 for_each_endpoint_of_node(sd->dev->of_node, ep) {
134 ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link);
135 if (ret)
136 continue;
137
138 ret = create_of_link(imxmd, sd, &link);
139 v4l2_fwnode_put_link(&link);
140 if (ret)
141 return ret;
142 }
143
144 return 0;
145 }
146 EXPORT_SYMBOL_GPL(imx_media_create_of_links);
147
148
149
150
151
152 int imx_media_create_csi_of_links(struct imx_media_dev *imxmd,
153 struct v4l2_subdev *csi)
154 {
155 struct device_node *csi_np = csi->dev->of_node;
156 struct device_node *ep;
157
158 for_each_child_of_node(csi_np, ep) {
159 struct fwnode_handle *fwnode, *csi_ep;
160 struct v4l2_fwnode_link link;
161 int ret;
162
163 memset(&link, 0, sizeof(link));
164
165 link.local_node = of_fwnode_handle(csi_np);
166 link.local_port = CSI_SINK_PAD;
167
168 csi_ep = of_fwnode_handle(ep);
169
170 fwnode = fwnode_graph_get_remote_endpoint(csi_ep);
171 if (!fwnode)
172 continue;
173
174 fwnode = fwnode_get_parent(fwnode);
175 fwnode_property_read_u32(fwnode, "reg", &link.remote_port);
176 fwnode = fwnode_get_next_parent(fwnode);
177 if (is_of_node(fwnode) &&
178 of_node_name_eq(to_of_node(fwnode), "ports"))
179 fwnode = fwnode_get_next_parent(fwnode);
180 link.remote_node = fwnode;
181
182 ret = create_of_link(imxmd, csi, &link);
183 fwnode_handle_put(link.remote_node);
184 if (ret)
185 return ret;
186 }
187
188 return 0;
189 }
190 EXPORT_SYMBOL_GPL(imx_media_create_csi_of_links);