forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/media/platform/video-mux.c
....@@ -1,17 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * video stream multiplexer controlled via mux control
34 *
45 * Copyright (C) 2013 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
56 * Copyright (C) 2016-2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License
9
- * as published by the Free Software Foundation; either version 2
10
- * of the License, or (at your option) any later version.
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
157 */
168
179 #include <linux/err.h>
....@@ -21,12 +13,16 @@
2113 #include <linux/of.h>
2214 #include <linux/of_graph.h>
2315 #include <linux/platform_device.h>
16
+#include <linux/slab.h>
2417 #include <media/v4l2-async.h>
2518 #include <media/v4l2-device.h>
19
+#include <media/v4l2-fwnode.h>
20
+#include <media/v4l2-mc.h>
2621 #include <media/v4l2-subdev.h>
2722
2823 struct video_mux {
2924 struct v4l2_subdev subdev;
25
+ struct v4l2_async_notifier notifier;
3026 struct media_pad *pads;
3127 struct v4l2_mbus_framefmt *format_mbus;
3228 struct mux_control *mux;
....@@ -40,6 +36,12 @@
4036 .code = MEDIA_BUS_FMT_Y8_1X8,
4137 .field = V4L2_FIELD_NONE,
4238 };
39
+
40
+static inline struct video_mux *
41
+notifier_to_video_mux(struct v4l2_async_notifier *n)
42
+{
43
+ return container_of(n, struct video_mux, notifier);
44
+}
4345
4446 static inline struct video_mux *v4l2_subdev_to_video_mux(struct v4l2_subdev *sd)
4547 {
....@@ -102,6 +104,7 @@
102104 static const struct media_entity_operations video_mux_ops = {
103105 .link_setup = video_mux_link_setup,
104106 .link_validate = v4l2_subdev_link_validate,
107
+ .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
105108 };
106109
107110 static int video_mux_s_stream(struct v4l2_subdev *sd, int enable)
....@@ -261,6 +264,26 @@
261264 case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
262265 case MEDIA_BUS_FMT_JPEG_1X8:
263266 case MEDIA_BUS_FMT_AHSV8888_1X32:
267
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
268
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
269
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
270
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
271
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
272
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
273
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
274
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
275
+ case MEDIA_BUS_FMT_SBGGR12_1X12:
276
+ case MEDIA_BUS_FMT_SGBRG12_1X12:
277
+ case MEDIA_BUS_FMT_SGRBG12_1X12:
278
+ case MEDIA_BUS_FMT_SRGGB12_1X12:
279
+ case MEDIA_BUS_FMT_SBGGR14_1X14:
280
+ case MEDIA_BUS_FMT_SGBRG14_1X14:
281
+ case MEDIA_BUS_FMT_SGRBG14_1X14:
282
+ case MEDIA_BUS_FMT_SRGGB14_1X14:
283
+ case MEDIA_BUS_FMT_SBGGR16_1X16:
284
+ case MEDIA_BUS_FMT_SGBRG16_1X16:
285
+ case MEDIA_BUS_FMT_SGRBG16_1X16:
286
+ case MEDIA_BUS_FMT_SRGGB16_1X16:
264287 break;
265288 default:
266289 sdformat->format.code = MEDIA_BUS_FMT_Y8_1X8;
....@@ -316,6 +339,68 @@
316339 .video = &video_mux_subdev_video_ops,
317340 };
318341
342
+static int video_mux_notify_bound(struct v4l2_async_notifier *notifier,
343
+ struct v4l2_subdev *sd,
344
+ struct v4l2_async_subdev *asd)
345
+{
346
+ struct video_mux *vmux = notifier_to_video_mux(notifier);
347
+
348
+ return v4l2_create_fwnode_links(sd, &vmux->subdev);
349
+}
350
+
351
+static const struct v4l2_async_notifier_operations video_mux_notify_ops = {
352
+ .bound = video_mux_notify_bound,
353
+};
354
+
355
+static int video_mux_async_register(struct video_mux *vmux,
356
+ unsigned int num_input_pads)
357
+{
358
+ unsigned int i;
359
+ int ret;
360
+
361
+ v4l2_async_notifier_init(&vmux->notifier);
362
+
363
+ for (i = 0; i < num_input_pads; i++) {
364
+ struct v4l2_async_subdev *asd;
365
+ struct fwnode_handle *ep, *remote_ep;
366
+
367
+ ep = fwnode_graph_get_endpoint_by_id(
368
+ dev_fwnode(vmux->subdev.dev), i, 0,
369
+ FWNODE_GRAPH_ENDPOINT_NEXT);
370
+ if (!ep)
371
+ continue;
372
+
373
+ /* Skip dangling endpoints for backwards compatibility */
374
+ remote_ep = fwnode_graph_get_remote_endpoint(ep);
375
+ if (!remote_ep) {
376
+ fwnode_handle_put(ep);
377
+ continue;
378
+ }
379
+ fwnode_handle_put(remote_ep);
380
+
381
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
382
+ &vmux->notifier, ep, sizeof(*asd));
383
+
384
+ fwnode_handle_put(ep);
385
+
386
+ if (IS_ERR(asd)) {
387
+ ret = PTR_ERR(asd);
388
+ /* OK if asd already exists */
389
+ if (ret != -EEXIST)
390
+ return ret;
391
+ }
392
+ }
393
+
394
+ vmux->notifier.ops = &video_mux_notify_ops;
395
+
396
+ ret = v4l2_async_subdev_notifier_register(&vmux->subdev,
397
+ &vmux->notifier);
398
+ if (ret)
399
+ return ret;
400
+
401
+ return v4l2_async_register_subdev(&vmux->subdev);
402
+}
403
+
319404 static int video_mux_probe(struct platform_device *pdev)
320405 {
321406 struct device_node *np = pdev->dev.of_node;
....@@ -333,7 +418,7 @@
333418 platform_set_drvdata(pdev, vmux);
334419
335420 v4l2_subdev_init(&vmux->subdev, &video_mux_subdev_ops);
336
- snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%s", np->name);
421
+ snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%pOFn", np);
337422 vmux->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
338423 vmux->subdev.dev = dev;
339424
....@@ -388,7 +473,13 @@
388473
389474 vmux->subdev.entity.ops = &video_mux_ops;
390475
391
- return v4l2_async_register_subdev(&vmux->subdev);
476
+ ret = video_mux_async_register(vmux, num_pads - 1);
477
+ if (ret) {
478
+ v4l2_async_notifier_unregister(&vmux->notifier);
479
+ v4l2_async_notifier_cleanup(&vmux->notifier);
480
+ }
481
+
482
+ return ret;
392483 }
393484
394485 static int video_mux_remove(struct platform_device *pdev)
....@@ -396,6 +487,8 @@
396487 struct video_mux *vmux = platform_get_drvdata(pdev);
397488 struct v4l2_subdev *sd = &vmux->subdev;
398489
490
+ v4l2_async_notifier_unregister(&vmux->notifier);
491
+ v4l2_async_notifier_cleanup(&vmux->notifier);
399492 v4l2_async_unregister_subdev(sd);
400493 media_entity_cleanup(&sd->entity);
401494