|
11 | 11 | #include <linux/delay.h>
|
12 | 12 | #include <linux/fs.h>
|
13 | 13 | #include <linux/module.h>
|
| 14 | +#include <linux/of_graph.h> |
14 | 15 | #include <linux/of_platform.h>
|
15 | 16 | #include <linux/pinctrl/consumer.h>
|
16 | 17 | #include <linux/platform_device.h>
|
@@ -127,50 +128,6 @@ imx_media_add_async_subdev(struct imx_media_dev *imxmd,
|
127 | 128 | return imxsd;
|
128 | 129 | }
|
129 | 130 |
|
130 |
| -/* |
131 |
| - * Adds an imx-media link to a subdev pad's link list. This is called |
132 |
| - * during driver load when forming the links between subdevs. |
133 |
| - * |
134 |
| - * @pad: the local pad |
135 |
| - * @remote_node: the device node of the remote subdev |
136 |
| - * @remote_devname: the device name of the remote subdev |
137 |
| - * @local_pad: local pad index |
138 |
| - * @remote_pad: remote pad index |
139 |
| - */ |
140 |
| -int imx_media_add_pad_link(struct imx_media_dev *imxmd, |
141 |
| - struct imx_media_pad *pad, |
142 |
| - struct device_node *remote_node, |
143 |
| - const char *remote_devname, |
144 |
| - int local_pad, int remote_pad) |
145 |
| -{ |
146 |
| - struct imx_media_link *link; |
147 |
| - int link_idx, ret = 0; |
148 |
| - |
149 |
| - mutex_lock(&imxmd->mutex); |
150 |
| - |
151 |
| - link_idx = pad->num_links; |
152 |
| - if (link_idx >= IMX_MEDIA_MAX_LINKS) { |
153 |
| - dev_err(imxmd->md.dev, "%s: too many links!\n", __func__); |
154 |
| - ret = -ENOSPC; |
155 |
| - goto out; |
156 |
| - } |
157 |
| - |
158 |
| - link = &pad->link[link_idx]; |
159 |
| - |
160 |
| - link->remote_sd_node = remote_node; |
161 |
| - if (remote_devname) |
162 |
| - strncpy(link->remote_devname, remote_devname, |
163 |
| - sizeof(link->remote_devname)); |
164 |
| - |
165 |
| - link->local_pad = local_pad; |
166 |
| - link->remote_pad = remote_pad; |
167 |
| - |
168 |
| - pad->num_links++; |
169 |
| -out: |
170 |
| - mutex_unlock(&imxmd->mutex); |
171 |
| - return ret; |
172 |
| -} |
173 |
| - |
174 | 131 | /*
|
175 | 132 | * get IPU from this CSI and add it to the list of IPUs
|
176 | 133 | * the media driver will control.
|
@@ -240,76 +197,38 @@ static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
|
240 | 197 | }
|
241 | 198 |
|
242 | 199 | /*
|
243 |
| - * Create a single source->sink media link given a subdev and a single |
244 |
| - * link from one of its source pads. Called after all subdevs have |
245 |
| - * registered. |
246 |
| - */ |
247 |
| -static int imx_media_create_link(struct imx_media_dev *imxmd, |
248 |
| - struct imx_media_subdev *src, |
249 |
| - struct imx_media_link *link) |
250 |
| -{ |
251 |
| - struct imx_media_subdev *sink; |
252 |
| - u16 source_pad, sink_pad; |
253 |
| - int ret; |
254 |
| - |
255 |
| - sink = imx_media_find_async_subdev(imxmd, link->remote_sd_node, |
256 |
| - link->remote_devname); |
257 |
| - if (!sink) { |
258 |
| - v4l2_warn(&imxmd->v4l2_dev, "%s: no sink for %s:%d\n", |
259 |
| - __func__, src->sd->name, link->local_pad); |
260 |
| - return 0; |
261 |
| - } |
262 |
| - |
263 |
| - source_pad = link->local_pad; |
264 |
| - sink_pad = link->remote_pad; |
265 |
| - |
266 |
| - v4l2_info(&imxmd->v4l2_dev, "%s: %s:%d -> %s:%d\n", __func__, |
267 |
| - src->sd->name, source_pad, sink->sd->name, sink_pad); |
268 |
| - |
269 |
| - ret = media_create_pad_link(&src->sd->entity, source_pad, |
270 |
| - &sink->sd->entity, sink_pad, 0); |
271 |
| - if (ret) |
272 |
| - v4l2_err(&imxmd->v4l2_dev, |
273 |
| - "create_pad_link failed: %d\n", ret); |
274 |
| - |
275 |
| - return ret; |
276 |
| -} |
277 |
| - |
278 |
| -/* |
279 |
| - * create the media links from all imx-media pads and their links. |
| 200 | + * create the media links from all pads and their links. |
280 | 201 | * Called after all subdevs have registered.
|
281 | 202 | */
|
282 | 203 | static int imx_media_create_links(struct imx_media_dev *imxmd)
|
283 | 204 | {
|
284 | 205 | struct imx_media_subdev *imxsd;
|
285 |
| - struct imx_media_link *link; |
286 |
| - struct imx_media_pad *pad; |
287 |
| - int num_pads, i, j, k; |
288 |
| - int ret = 0; |
| 206 | + struct v4l2_subdev *sd; |
| 207 | + int i, ret; |
289 | 208 |
|
290 | 209 | for (i = 0; i < imxmd->num_subdevs; i++) {
|
291 | 210 | imxsd = &imxmd->subdev[i];
|
292 |
| - num_pads = imxsd->num_sink_pads + imxsd->num_src_pads; |
293 |
| - |
294 |
| - for (j = 0; j < num_pads; j++) { |
295 |
| - pad = &imxsd->pad[j]; |
296 |
| - |
297 |
| - /* only create the source->sink links */ |
298 |
| - if (!(pad->pad.flags & MEDIA_PAD_FL_SOURCE)) |
299 |
| - continue; |
300 |
| - |
301 |
| - for (k = 0; k < pad->num_links; k++) { |
302 |
| - link = &pad->link[k]; |
| 211 | + sd = imxsd->sd; |
303 | 212 |
|
304 |
| - ret = imx_media_create_link(imxmd, imxsd, link); |
305 |
| - if (ret) |
306 |
| - goto out; |
307 |
| - } |
| 213 | + if (((sd->grp_id & IMX_MEDIA_GRP_ID_CSI) || imxsd->pdev)) { |
| 214 | + /* this is an internal subdev or a CSI */ |
| 215 | + ret = imx_media_create_internal_links(imxmd, imxsd); |
| 216 | + if (ret) |
| 217 | + return ret; |
| 218 | + /* |
| 219 | + * the CSIs straddle between the external and the IPU |
| 220 | + * internal entities, so create the external links |
| 221 | + * to the CSI sink pads. |
| 222 | + */ |
| 223 | + if (sd->grp_id & IMX_MEDIA_GRP_ID_CSI) |
| 224 | + imx_media_create_csi_of_links(imxmd, imxsd); |
| 225 | + } else { |
| 226 | + /* this is an external fwnode subdev */ |
| 227 | + imx_media_create_of_links(imxmd, imxsd); |
308 | 228 | }
|
309 | 229 | }
|
310 | 230 |
|
311 |
| -out: |
312 |
| - return ret; |
| 231 | + return 0; |
313 | 232 | }
|
314 | 233 |
|
315 | 234 | /*
|
@@ -550,7 +469,6 @@ static int imx_media_probe(struct platform_device *pdev)
|
550 | 469 | {
|
551 | 470 | struct device *dev = &pdev->dev;
|
552 | 471 | struct device_node *node = dev->of_node;
|
553 |
| - struct imx_media_subdev *csi[4] = {0}; |
554 | 472 | struct imx_media_dev *imxmd;
|
555 | 473 | int ret;
|
556 | 474 |
|
@@ -581,14 +499,14 @@ static int imx_media_probe(struct platform_device *pdev)
|
581 | 499 |
|
582 | 500 | dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
|
583 | 501 |
|
584 |
| - ret = imx_media_of_parse(imxmd, &csi, node); |
| 502 | + ret = imx_media_add_of_subdevs(imxmd, node); |
585 | 503 | if (ret) {
|
586 | 504 | v4l2_err(&imxmd->v4l2_dev,
|
587 |
| - "imx_media_of_parse failed with %d\n", ret); |
| 505 | + "add_of_subdevs failed with %d\n", ret); |
588 | 506 | goto unreg_dev;
|
589 | 507 | }
|
590 | 508 |
|
591 |
| - ret = imx_media_add_internal_subdevs(imxmd, csi); |
| 509 | + ret = imx_media_add_internal_subdevs(imxmd); |
592 | 510 | if (ret) {
|
593 | 511 | v4l2_err(&imxmd->v4l2_dev,
|
594 | 512 | "add_internal_subdevs failed with %d\n", ret);
|
|
0 commit comments