forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/drivers/media/platform/xilinx/xilinx-vipp.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * Xilinx Video IP Composite Device
34 *
....@@ -6,10 +7,6 @@
67 *
78 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
89 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9
- *
10
- * This program is free software; you can redistribute it and/or modify
11
- * it under the terms of the GNU General Public License version 2 as
12
- * published by the Free Software Foundation.
1310 */
1411
1512 #include <linux/list.h>
....@@ -32,20 +29,21 @@
3229
3330 /**
3431 * struct xvip_graph_entity - Entity in the video graph
35
- * @list: list entry in a graph entities list
36
- * @node: the entity's DT node
37
- * @entity: media entity, from the corresponding V4L2 subdev
3832 * @asd: subdev asynchronous registration information
33
+ * @entity: media entity, from the corresponding V4L2 subdev
3934 * @subdev: V4L2 subdev
4035 */
4136 struct xvip_graph_entity {
42
- struct list_head list;
43
- struct device_node *node;
37
+ struct v4l2_async_subdev asd; /* must be first */
4438 struct media_entity *entity;
45
-
46
- struct v4l2_async_subdev asd;
4739 struct v4l2_subdev *subdev;
4840 };
41
+
42
+static inline struct xvip_graph_entity *
43
+to_xvip_entity(struct v4l2_async_subdev *asd)
44
+{
45
+ return container_of(asd, struct xvip_graph_entity, asd);
46
+}
4947
5048 /* -----------------------------------------------------------------------------
5149 * Graph Management
....@@ -53,12 +51,14 @@
5351
5452 static struct xvip_graph_entity *
5553 xvip_graph_find_entity(struct xvip_composite_device *xdev,
56
- const struct device_node *node)
54
+ const struct fwnode_handle *fwnode)
5755 {
5856 struct xvip_graph_entity *entity;
57
+ struct v4l2_async_subdev *asd;
5958
60
- list_for_each_entry(entity, &xdev->entities, list) {
61
- if (entity->node == node)
59
+ list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
60
+ entity = to_xvip_entity(asd);
61
+ if (entity->asd.match.fwnode == fwnode)
6262 return entity;
6363 }
6464
....@@ -75,22 +75,23 @@
7575 struct media_pad *remote_pad;
7676 struct xvip_graph_entity *ent;
7777 struct v4l2_fwnode_link link;
78
- struct device_node *ep = NULL;
78
+ struct fwnode_handle *ep = NULL;
7979 int ret = 0;
8080
8181 dev_dbg(xdev->dev, "creating links for entity %s\n", local->name);
8282
8383 while (1) {
8484 /* Get the next endpoint and parse its link. */
85
- ep = of_graph_get_next_endpoint(entity->node, ep);
85
+ ep = fwnode_graph_get_next_endpoint(entity->asd.match.fwnode,
86
+ ep);
8687 if (ep == NULL)
8788 break;
8889
89
- dev_dbg(xdev->dev, "processing endpoint %pOF\n", ep);
90
+ dev_dbg(xdev->dev, "processing endpoint %p\n", ep);
9091
91
- ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link);
92
+ ret = v4l2_fwnode_parse_link(ep, &link);
9293 if (ret < 0) {
93
- dev_err(xdev->dev, "failed to parse link for %pOF\n",
94
+ dev_err(xdev->dev, "failed to parse link for %p\n",
9495 ep);
9596 continue;
9697 }
....@@ -99,9 +100,8 @@
99100 * the link.
100101 */
101102 if (link.local_port >= local->num_pads) {
102
- dev_err(xdev->dev, "invalid port number %u for %pOF\n",
103
- link.local_port,
104
- to_of_node(link.local_node));
103
+ dev_err(xdev->dev, "invalid port number %u for %p\n",
104
+ link.local_port, link.local_node);
105105 v4l2_fwnode_put_link(&link);
106106 ret = -EINVAL;
107107 break;
....@@ -110,28 +110,25 @@
110110 local_pad = &local->pads[link.local_port];
111111
112112 if (local_pad->flags & MEDIA_PAD_FL_SINK) {
113
- dev_dbg(xdev->dev, "skipping sink port %pOF:%u\n",
114
- to_of_node(link.local_node),
115
- link.local_port);
113
+ dev_dbg(xdev->dev, "skipping sink port %p:%u\n",
114
+ link.local_node, link.local_port);
116115 v4l2_fwnode_put_link(&link);
117116 continue;
118117 }
119118
120119 /* Skip DMA engines, they will be processed separately. */
121120 if (link.remote_node == of_fwnode_handle(xdev->dev->of_node)) {
122
- dev_dbg(xdev->dev, "skipping DMA port %pOF:%u\n",
123
- to_of_node(link.local_node),
124
- link.local_port);
121
+ dev_dbg(xdev->dev, "skipping DMA port %p:%u\n",
122
+ link.local_node, link.local_port);
125123 v4l2_fwnode_put_link(&link);
126124 continue;
127125 }
128126
129127 /* Find the remote entity. */
130
- ent = xvip_graph_find_entity(xdev,
131
- to_of_node(link.remote_node));
128
+ ent = xvip_graph_find_entity(xdev, link.remote_node);
132129 if (ent == NULL) {
133
- dev_err(xdev->dev, "no entity found for %pOF\n",
134
- to_of_node(link.remote_node));
130
+ dev_err(xdev->dev, "no entity found for %p\n",
131
+ link.remote_node);
135132 v4l2_fwnode_put_link(&link);
136133 ret = -ENODEV;
137134 break;
....@@ -140,8 +137,8 @@
140137 remote = ent->entity;
141138
142139 if (link.remote_port >= remote->num_pads) {
143
- dev_err(xdev->dev, "invalid port number %u on %pOF\n",
144
- link.remote_port, to_of_node(link.remote_node));
140
+ dev_err(xdev->dev, "invalid port number %u on %p\n",
141
+ link.remote_port, link.remote_node);
145142 v4l2_fwnode_put_link(&link);
146143 ret = -EINVAL;
147144 break;
....@@ -168,7 +165,7 @@
168165 }
169166 }
170167
171
- of_node_put(ep);
168
+ fwnode_handle_put(ep);
172169 return ret;
173170 }
174171
....@@ -230,8 +227,7 @@
230227 dma->video.name);
231228
232229 /* Find the remote entity. */
233
- ent = xvip_graph_find_entity(xdev,
234
- to_of_node(link.remote_node));
230
+ ent = xvip_graph_find_entity(xdev, link.remote_node);
235231 if (ent == NULL) {
236232 dev_err(xdev->dev, "no entity found for %pOF\n",
237233 to_of_node(link.remote_node));
....@@ -289,12 +285,14 @@
289285 struct xvip_composite_device *xdev =
290286 container_of(notifier, struct xvip_composite_device, notifier);
291287 struct xvip_graph_entity *entity;
288
+ struct v4l2_async_subdev *asd;
292289 int ret;
293290
294291 dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
295292
296293 /* Create links for every entity. */
297
- list_for_each_entry(entity, &xdev->entities, list) {
294
+ list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
295
+ entity = to_xvip_entity(asd);
298296 ret = xvip_graph_build_one(xdev, entity);
299297 if (ret < 0)
300298 return ret;
....@@ -314,22 +312,25 @@
314312
315313 static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier,
316314 struct v4l2_subdev *subdev,
317
- struct v4l2_async_subdev *asd)
315
+ struct v4l2_async_subdev *unused)
318316 {
319317 struct xvip_composite_device *xdev =
320318 container_of(notifier, struct xvip_composite_device, notifier);
321319 struct xvip_graph_entity *entity;
320
+ struct v4l2_async_subdev *asd;
322321
323322 /* Locate the entity corresponding to the bound subdev and store the
324323 * subdev pointer.
325324 */
326
- list_for_each_entry(entity, &xdev->entities, list) {
327
- if (entity->node != subdev->dev->of_node)
325
+ list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
326
+ entity = to_xvip_entity(asd);
327
+
328
+ if (entity->asd.match.fwnode != subdev->fwnode)
328329 continue;
329330
330331 if (entity->subdev) {
331
- dev_err(xdev->dev, "duplicate subdev for node %pOF\n",
332
- entity->node);
332
+ dev_err(xdev->dev, "duplicate subdev for node %p\n",
333
+ entity->asd.match.fwnode);
333334 return -EINVAL;
334335 }
335336
....@@ -349,56 +350,60 @@
349350 };
350351
351352 static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
352
- struct device_node *node)
353
+ struct fwnode_handle *fwnode)
353354 {
354
- struct xvip_graph_entity *entity;
355
- struct device_node *remote;
356
- struct device_node *ep = NULL;
355
+ struct fwnode_handle *remote;
356
+ struct fwnode_handle *ep = NULL;
357357 int ret = 0;
358358
359
- dev_dbg(xdev->dev, "parsing node %pOF\n", node);
359
+ dev_dbg(xdev->dev, "parsing node %p\n", fwnode);
360360
361361 while (1) {
362
- ep = of_graph_get_next_endpoint(node, ep);
362
+ struct v4l2_async_subdev *asd;
363
+
364
+ ep = fwnode_graph_get_next_endpoint(fwnode, ep);
363365 if (ep == NULL)
364366 break;
365367
366
- dev_dbg(xdev->dev, "handling endpoint %pOF\n", ep);
368
+ dev_dbg(xdev->dev, "handling endpoint %p\n", ep);
367369
368
- remote = of_graph_get_remote_port_parent(ep);
370
+ remote = fwnode_graph_get_remote_port_parent(ep);
369371 if (remote == NULL) {
370372 ret = -EINVAL;
371
- break;
373
+ goto err_notifier_cleanup;
372374 }
373375
376
+ fwnode_handle_put(ep);
377
+
374378 /* Skip entities that we have already processed. */
375
- if (remote == xdev->dev->of_node ||
379
+ if (remote == of_fwnode_handle(xdev->dev->of_node) ||
376380 xvip_graph_find_entity(xdev, remote)) {
377
- of_node_put(remote);
381
+ fwnode_handle_put(remote);
378382 continue;
379383 }
380384
381
- entity = devm_kzalloc(xdev->dev, sizeof(*entity), GFP_KERNEL);
382
- if (entity == NULL) {
383
- of_node_put(remote);
384
- ret = -ENOMEM;
385
- break;
385
+ asd = v4l2_async_notifier_add_fwnode_subdev(
386
+ &xdev->notifier, remote,
387
+ sizeof(struct xvip_graph_entity));
388
+ fwnode_handle_put(remote);
389
+ if (IS_ERR(asd)) {
390
+ ret = PTR_ERR(asd);
391
+ goto err_notifier_cleanup;
386392 }
387
-
388
- entity->node = remote;
389
- entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
390
- entity->asd.match.fwnode = of_fwnode_handle(remote);
391
- list_add_tail(&entity->list, &xdev->entities);
392
- xdev->num_subdevs++;
393393 }
394394
395
- of_node_put(ep);
395
+ return 0;
396
+
397
+err_notifier_cleanup:
398
+ v4l2_async_notifier_cleanup(&xdev->notifier);
399
+ fwnode_handle_put(ep);
396400 return ret;
397401 }
398402
399403 static int xvip_graph_parse(struct xvip_composite_device *xdev)
400404 {
401405 struct xvip_graph_entity *entity;
406
+ struct v4l2_async_subdev *asd;
402407 int ret;
403408
404409 /*
....@@ -407,14 +412,17 @@
407412 * loop will handle entities added at the end of the list while walking
408413 * the links.
409414 */
410
- ret = xvip_graph_parse_one(xdev, xdev->dev->of_node);
415
+ ret = xvip_graph_parse_one(xdev, of_fwnode_handle(xdev->dev->of_node));
411416 if (ret < 0)
412417 return 0;
413418
414
- list_for_each_entry(entity, &xdev->entities, list) {
415
- ret = xvip_graph_parse_one(xdev, entity->node);
416
- if (ret < 0)
419
+ list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
420
+ entity = to_xvip_entity(asd);
421
+ ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
422
+ if (ret < 0) {
423
+ v4l2_async_notifier_cleanup(&xdev->notifier);
417424 break;
425
+ }
418426 }
419427
420428 return ret;
....@@ -464,7 +472,7 @@
464472 {
465473 struct device_node *ports;
466474 struct device_node *port;
467
- int ret;
475
+ int ret = 0;
468476
469477 ports = of_get_child_by_name(xdev->dev->of_node, "ports");
470478 if (ports == NULL) {
....@@ -474,28 +482,23 @@
474482
475483 for_each_child_of_node(ports, port) {
476484 ret = xvip_graph_dma_init_one(xdev, port);
477
- if (ret < 0) {
485
+ if (ret) {
478486 of_node_put(port);
479
- return ret;
487
+ break;
480488 }
481489 }
482490
483
- return 0;
491
+ of_node_put(ports);
492
+ return ret;
484493 }
485494
486495 static void xvip_graph_cleanup(struct xvip_composite_device *xdev)
487496 {
488
- struct xvip_graph_entity *entityp;
489
- struct xvip_graph_entity *entity;
490497 struct xvip_dma *dmap;
491498 struct xvip_dma *dma;
492499
493500 v4l2_async_notifier_unregister(&xdev->notifier);
494
-
495
- list_for_each_entry_safe(entity, entityp, &xdev->entities, list) {
496
- of_node_put(entity->node);
497
- list_del(&entity->list);
498
- }
501
+ v4l2_async_notifier_cleanup(&xdev->notifier);
499502
500503 list_for_each_entry_safe(dma, dmap, &xdev->dmas, list) {
501504 xvip_dma_cleanup(dma);
....@@ -505,10 +508,6 @@
505508
506509 static int xvip_graph_init(struct xvip_composite_device *xdev)
507510 {
508
- struct xvip_graph_entity *entity;
509
- struct v4l2_async_subdev **subdevs = NULL;
510
- unsigned int num_subdevs;
511
- unsigned int i;
512511 int ret;
513512
514513 /* Init the DMA channels. */
....@@ -525,26 +524,12 @@
525524 goto done;
526525 }
527526
528
- if (!xdev->num_subdevs) {
527
+ if (list_empty(&xdev->notifier.asd_list)) {
529528 dev_err(xdev->dev, "no subdev found in graph\n");
530529 goto done;
531530 }
532531
533532 /* Register the subdevices notifier. */
534
- num_subdevs = xdev->num_subdevs;
535
- subdevs = devm_kcalloc(xdev->dev, num_subdevs, sizeof(*subdevs),
536
- GFP_KERNEL);
537
- if (subdevs == NULL) {
538
- ret = -ENOMEM;
539
- goto done;
540
- }
541
-
542
- i = 0;
543
- list_for_each_entry(entity, &xdev->entities, list)
544
- subdevs[i++] = &entity->asd;
545
-
546
- xdev->notifier.subdevs = subdevs;
547
- xdev->notifier.num_subdevs = num_subdevs;
548533 xdev->notifier.ops = &xvip_graph_notify_ops;
549534
550535 ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier);
....@@ -578,7 +563,7 @@
578563 int ret;
579564
580565 xdev->media_dev.dev = xdev->dev;
581
- strlcpy(xdev->media_dev.model, "Xilinx Video Composite Device",
566
+ strscpy(xdev->media_dev.model, "Xilinx Video Composite Device",
582567 sizeof(xdev->media_dev.model));
583568 xdev->media_dev.hw_revision = 0;
584569
....@@ -610,8 +595,8 @@
610595 return -ENOMEM;
611596
612597 xdev->dev = &pdev->dev;
613
- INIT_LIST_HEAD(&xdev->entities);
614598 INIT_LIST_HEAD(&xdev->dmas);
599
+ v4l2_async_notifier_init(&xdev->notifier);
615600
616601 ret = xvip_composite_v4l2_init(xdev);
617602 if (ret < 0)