diff options
author | Steve Longerbeam <slongerbeam@gmail.com> | 2018-09-29 15:54:09 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2018-10-04 15:34:24 -0400 |
commit | 1634f0eded87d1f150e823fa56cd782ea0775eb2 (patch) | |
tree | 3d275cbd636c85955440ac61be383a505c850ed0 | |
parent | eae2aed1eab9bf08146403ac702517d2e4fe932e (diff) |
media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers
Adds v4l2_async_register_fwnode_subdev(), which is a convenience function
for parsing a sub-device's fwnode port endpoints for connected remote
sub-devices, registering a sub-device notifier, and then registering
the sub-device itself.
Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r-- | drivers/media/v4l2-core/v4l2-fwnode.c | 64 | ||||
-rw-r--r-- | include/media/v4l2-fwnode.h | 38 |
2 files changed, 102 insertions, 0 deletions
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 88383d3d5974..be75d9900667 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c | |||
@@ -876,6 +876,70 @@ out_cleanup: | |||
876 | } | 876 | } |
877 | EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common); | 877 | EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common); |
878 | 878 | ||
879 | int v4l2_async_register_fwnode_subdev( | ||
880 | struct v4l2_subdev *sd, size_t asd_struct_size, | ||
881 | unsigned int *ports, unsigned int num_ports, | ||
882 | int (*parse_endpoint)(struct device *dev, | ||
883 | struct v4l2_fwnode_endpoint *vep, | ||
884 | struct v4l2_async_subdev *asd)) | ||
885 | { | ||
886 | struct v4l2_async_notifier *notifier; | ||
887 | struct device *dev = sd->dev; | ||
888 | struct fwnode_handle *fwnode; | ||
889 | int ret; | ||
890 | |||
891 | if (WARN_ON(!dev)) | ||
892 | return -ENODEV; | ||
893 | |||
894 | fwnode = dev_fwnode(dev); | ||
895 | if (!fwnode_device_is_available(fwnode)) | ||
896 | return -ENODEV; | ||
897 | |||
898 | notifier = kzalloc(sizeof(*notifier), GFP_KERNEL); | ||
899 | if (!notifier) | ||
900 | return -ENOMEM; | ||
901 | |||
902 | v4l2_async_notifier_init(notifier); | ||
903 | |||
904 | if (!ports) { | ||
905 | ret = v4l2_async_notifier_parse_fwnode_endpoints( | ||
906 | dev, notifier, asd_struct_size, parse_endpoint); | ||
907 | if (ret < 0) | ||
908 | goto out_cleanup; | ||
909 | } else { | ||
910 | unsigned int i; | ||
911 | |||
912 | for (i = 0; i < num_ports; i++) { | ||
913 | ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port( | ||
914 | dev, notifier, asd_struct_size, | ||
915 | ports[i], parse_endpoint); | ||
916 | if (ret < 0) | ||
917 | goto out_cleanup; | ||
918 | } | ||
919 | } | ||
920 | |||
921 | ret = v4l2_async_subdev_notifier_register(sd, notifier); | ||
922 | if (ret < 0) | ||
923 | goto out_cleanup; | ||
924 | |||
925 | ret = v4l2_async_register_subdev(sd); | ||
926 | if (ret < 0) | ||
927 | goto out_unregister; | ||
928 | |||
929 | sd->subdev_notifier = notifier; | ||
930 | |||
931 | return 0; | ||
932 | |||
933 | out_unregister: | ||
934 | v4l2_async_notifier_unregister(notifier); | ||
935 | out_cleanup: | ||
936 | v4l2_async_notifier_cleanup(notifier); | ||
937 | kfree(notifier); | ||
938 | |||
939 | return ret; | ||
940 | } | ||
941 | EXPORT_SYMBOL_GPL(v4l2_async_register_fwnode_subdev); | ||
942 | |||
879 | MODULE_LICENSE("GPL"); | 943 | MODULE_LICENSE("GPL"); |
880 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); | 944 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); |
881 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | 945 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); |
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h index ea7a8b247e19..031ebb069dcb 100644 --- a/include/media/v4l2-fwnode.h +++ b/include/media/v4l2-fwnode.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | 24 | ||
25 | #include <media/v4l2-mediabus.h> | 25 | #include <media/v4l2-mediabus.h> |
26 | #include <media/v4l2-subdev.h> | ||
26 | 27 | ||
27 | struct fwnode_handle; | 28 | struct fwnode_handle; |
28 | struct v4l2_async_notifier; | 29 | struct v4l2_async_notifier; |
@@ -360,4 +361,41 @@ int v4l2_async_notifier_parse_fwnode_endpoints_by_port( | |||
360 | int v4l2_async_notifier_parse_fwnode_sensor_common( | 361 | int v4l2_async_notifier_parse_fwnode_sensor_common( |
361 | struct device *dev, struct v4l2_async_notifier *notifier); | 362 | struct device *dev, struct v4l2_async_notifier *notifier); |
362 | 363 | ||
364 | /** | ||
365 | * v4l2_async_register_fwnode_subdev - registers a sub-device to the | ||
366 | * asynchronous sub-device framework | ||
367 | * and parses fwnode endpoints | ||
368 | * | ||
369 | * @sd: pointer to struct &v4l2_subdev | ||
370 | * @asd_struct_size: size of the driver's async sub-device struct, including | ||
371 | * sizeof(struct v4l2_async_subdev). The &struct | ||
372 | * v4l2_async_subdev shall be the first member of | ||
373 | * the driver's async sub-device struct, i.e. both | ||
374 | * begin at the same memory address. | ||
375 | * @ports: array of port id's to parse for fwnode endpoints. If NULL, will | ||
376 | * parse all ports owned by the sub-device. | ||
377 | * @num_ports: number of ports in @ports array. Ignored if @ports is NULL. | ||
378 | * @parse_endpoint: Driver's callback function called on each V4L2 fwnode | ||
379 | * endpoint. Optional. | ||
380 | * | ||
381 | * This function is just like v4l2_async_register_subdev() with the | ||
382 | * exception that calling it will also allocate a notifier for the | ||
383 | * sub-device, parse the sub-device's firmware node endpoints using | ||
384 | * v4l2_async_notifier_parse_fwnode_endpoints() or | ||
385 | * v4l2_async_notifier_parse_fwnode_endpoints_by_port(), and | ||
386 | * registers the sub-device notifier. The sub-device is similarly | ||
387 | * unregistered by calling v4l2_async_unregister_subdev(). | ||
388 | * | ||
389 | * While registered, the subdev module is marked as in-use. | ||
390 | * | ||
391 | * An error is returned if the module is no longer loaded on any attempts | ||
392 | * to register it. | ||
393 | */ | ||
394 | int v4l2_async_register_fwnode_subdev( | ||
395 | struct v4l2_subdev *sd, size_t asd_struct_size, | ||
396 | unsigned int *ports, unsigned int num_ports, | ||
397 | int (*parse_endpoint)(struct device *dev, | ||
398 | struct v4l2_fwnode_endpoint *vep, | ||
399 | struct v4l2_async_subdev *asd)); | ||
400 | |||
363 | #endif /* _V4L2_FWNODE_H */ | 401 | #endif /* _V4L2_FWNODE_H */ |