18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci    V4L2 device support header.
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci    Copyright (C) 2008  Hans Verkuil <hverkuil@xs4all.nl>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#ifndef _V4L2_DEVICE_H
108c2ecf20Sopenharmony_ci#define _V4L2_DEVICE_H
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <media/media-device.h>
138c2ecf20Sopenharmony_ci#include <media/v4l2-subdev.h>
148c2ecf20Sopenharmony_ci#include <media/v4l2-dev.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define V4L2_DEVICE_NAME_SIZE (20 + 16)
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistruct v4l2_ctrl_handler;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci/**
218c2ecf20Sopenharmony_ci * struct v4l2_device - main struct to for V4L2 device drivers
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * @dev: pointer to struct device.
248c2ecf20Sopenharmony_ci * @mdev: pointer to struct media_device, may be NULL.
258c2ecf20Sopenharmony_ci * @subdevs: used to keep track of the registered subdevs
268c2ecf20Sopenharmony_ci * @lock: lock this struct; can be used by the driver as well
278c2ecf20Sopenharmony_ci *	if this struct is embedded into a larger struct.
288c2ecf20Sopenharmony_ci * @name: unique device name, by default the driver name + bus ID
298c2ecf20Sopenharmony_ci * @notify: notify operation called by some sub-devices.
308c2ecf20Sopenharmony_ci * @ctrl_handler: The control handler. May be %NULL.
318c2ecf20Sopenharmony_ci * @prio: Device's priority state
328c2ecf20Sopenharmony_ci * @ref: Keep track of the references to this struct.
338c2ecf20Sopenharmony_ci * @release: Release function that is called when the ref count
348c2ecf20Sopenharmony_ci *	goes to 0.
358c2ecf20Sopenharmony_ci *
368c2ecf20Sopenharmony_ci * Each instance of a V4L2 device should create the v4l2_device struct,
378c2ecf20Sopenharmony_ci * either stand-alone or embedded in a larger struct.
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci * It allows easy access to sub-devices (see v4l2-subdev.h) and provides
408c2ecf20Sopenharmony_ci * basic V4L2 device-level support.
418c2ecf20Sopenharmony_ci *
428c2ecf20Sopenharmony_ci * .. note::
438c2ecf20Sopenharmony_ci *
448c2ecf20Sopenharmony_ci *    #) @dev->driver_data points to this struct.
458c2ecf20Sopenharmony_ci *    #) @dev might be %NULL if there is no parent device
468c2ecf20Sopenharmony_ci */
478c2ecf20Sopenharmony_cistruct v4l2_device {
488c2ecf20Sopenharmony_ci	struct device *dev;
498c2ecf20Sopenharmony_ci	struct media_device *mdev;
508c2ecf20Sopenharmony_ci	struct list_head subdevs;
518c2ecf20Sopenharmony_ci	spinlock_t lock;
528c2ecf20Sopenharmony_ci	char name[V4L2_DEVICE_NAME_SIZE];
538c2ecf20Sopenharmony_ci	void (*notify)(struct v4l2_subdev *sd,
548c2ecf20Sopenharmony_ci			unsigned int notification, void *arg);
558c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *ctrl_handler;
568c2ecf20Sopenharmony_ci	struct v4l2_prio_state prio;
578c2ecf20Sopenharmony_ci	struct kref ref;
588c2ecf20Sopenharmony_ci	void (*release)(struct v4l2_device *v4l2_dev);
598c2ecf20Sopenharmony_ci};
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/**
628c2ecf20Sopenharmony_ci * v4l2_device_get - gets a V4L2 device reference
638c2ecf20Sopenharmony_ci *
648c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct &v4l2_device
658c2ecf20Sopenharmony_ci *
668c2ecf20Sopenharmony_ci * This is an ancillary routine meant to increment the usage for the
678c2ecf20Sopenharmony_ci * struct &v4l2_device pointed by @v4l2_dev.
688c2ecf20Sopenharmony_ci */
698c2ecf20Sopenharmony_cistatic inline void v4l2_device_get(struct v4l2_device *v4l2_dev)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	kref_get(&v4l2_dev->ref);
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/**
758c2ecf20Sopenharmony_ci * v4l2_device_put - puts a V4L2 device reference
768c2ecf20Sopenharmony_ci *
778c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct &v4l2_device
788c2ecf20Sopenharmony_ci *
798c2ecf20Sopenharmony_ci * This is an ancillary routine meant to decrement the usage for the
808c2ecf20Sopenharmony_ci * struct &v4l2_device pointed by @v4l2_dev.
818c2ecf20Sopenharmony_ci */
828c2ecf20Sopenharmony_ciint v4l2_device_put(struct v4l2_device *v4l2_dev);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/**
858c2ecf20Sopenharmony_ci * v4l2_device_register - Initialize v4l2_dev and make @dev->driver_data
868c2ecf20Sopenharmony_ci *	point to @v4l2_dev.
878c2ecf20Sopenharmony_ci *
888c2ecf20Sopenharmony_ci * @dev: pointer to struct &device
898c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct &v4l2_device
908c2ecf20Sopenharmony_ci *
918c2ecf20Sopenharmony_ci * .. note::
928c2ecf20Sopenharmony_ci *	@dev may be %NULL in rare cases (ISA devices).
938c2ecf20Sopenharmony_ci *	In such case the caller must fill in the @v4l2_dev->name field
948c2ecf20Sopenharmony_ci *	before calling this function.
958c2ecf20Sopenharmony_ci */
968c2ecf20Sopenharmony_ciint __must_check v4l2_device_register(struct device *dev,
978c2ecf20Sopenharmony_ci				      struct v4l2_device *v4l2_dev);
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/**
1008c2ecf20Sopenharmony_ci * v4l2_device_set_name - Optional function to initialize the
1018c2ecf20Sopenharmony_ci *	name field of struct &v4l2_device
1028c2ecf20Sopenharmony_ci *
1038c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct &v4l2_device
1048c2ecf20Sopenharmony_ci * @basename: base name for the device name
1058c2ecf20Sopenharmony_ci * @instance: pointer to a static atomic_t var with the instance usage for
1068c2ecf20Sopenharmony_ci *	the device driver.
1078c2ecf20Sopenharmony_ci *
1088c2ecf20Sopenharmony_ci * v4l2_device_set_name() initializes the name field of struct &v4l2_device
1098c2ecf20Sopenharmony_ci * using the driver name and a driver-global atomic_t instance.
1108c2ecf20Sopenharmony_ci *
1118c2ecf20Sopenharmony_ci * This function will increment the instance counter and returns the
1128c2ecf20Sopenharmony_ci * instance value used in the name.
1138c2ecf20Sopenharmony_ci *
1148c2ecf20Sopenharmony_ci * Example:
1158c2ecf20Sopenharmony_ci *
1168c2ecf20Sopenharmony_ci *   static atomic_t drv_instance = ATOMIC_INIT(0);
1178c2ecf20Sopenharmony_ci *
1188c2ecf20Sopenharmony_ci *   ...
1198c2ecf20Sopenharmony_ci *
1208c2ecf20Sopenharmony_ci *   instance = v4l2_device_set_name(&\ v4l2_dev, "foo", &\ drv_instance);
1218c2ecf20Sopenharmony_ci *
1228c2ecf20Sopenharmony_ci * The first time this is called the name field will be set to foo0 and
1238c2ecf20Sopenharmony_ci * this function returns 0. If the name ends with a digit (e.g. cx18),
1248c2ecf20Sopenharmony_ci * then the name will be set to cx18-0 since cx180 would look really odd.
1258c2ecf20Sopenharmony_ci */
1268c2ecf20Sopenharmony_ciint v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
1278c2ecf20Sopenharmony_ci			 atomic_t *instance);
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci/**
1308c2ecf20Sopenharmony_ci * v4l2_device_disconnect - Change V4L2 device state to disconnected.
1318c2ecf20Sopenharmony_ci *
1328c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct v4l2_device
1338c2ecf20Sopenharmony_ci *
1348c2ecf20Sopenharmony_ci * Should be called when the USB parent disconnects.
1358c2ecf20Sopenharmony_ci * Since the parent disappears, this ensures that @v4l2_dev doesn't have
1368c2ecf20Sopenharmony_ci * an invalid parent pointer.
1378c2ecf20Sopenharmony_ci *
1388c2ecf20Sopenharmony_ci * .. note:: This function sets @v4l2_dev->dev to NULL.
1398c2ecf20Sopenharmony_ci */
1408c2ecf20Sopenharmony_civoid v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci/**
1438c2ecf20Sopenharmony_ci *  v4l2_device_unregister - Unregister all sub-devices and any other
1448c2ecf20Sopenharmony_ci *	 resources related to @v4l2_dev.
1458c2ecf20Sopenharmony_ci *
1468c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct v4l2_device
1478c2ecf20Sopenharmony_ci */
1488c2ecf20Sopenharmony_civoid v4l2_device_unregister(struct v4l2_device *v4l2_dev);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci/**
1518c2ecf20Sopenharmony_ci * v4l2_device_register_subdev - Registers a subdev with a v4l2 device.
1528c2ecf20Sopenharmony_ci *
1538c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct &v4l2_device
1548c2ecf20Sopenharmony_ci * @sd: pointer to &struct v4l2_subdev
1558c2ecf20Sopenharmony_ci *
1568c2ecf20Sopenharmony_ci * While registered, the subdev module is marked as in-use.
1578c2ecf20Sopenharmony_ci *
1588c2ecf20Sopenharmony_ci * An error is returned if the module is no longer loaded on any attempts
1598c2ecf20Sopenharmony_ci * to register it.
1608c2ecf20Sopenharmony_ci */
1618c2ecf20Sopenharmony_ciint __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
1628c2ecf20Sopenharmony_ci					     struct v4l2_subdev *sd);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci/**
1658c2ecf20Sopenharmony_ci * v4l2_device_unregister_subdev - Unregisters a subdev with a v4l2 device.
1668c2ecf20Sopenharmony_ci *
1678c2ecf20Sopenharmony_ci * @sd: pointer to &struct v4l2_subdev
1688c2ecf20Sopenharmony_ci *
1698c2ecf20Sopenharmony_ci * .. note ::
1708c2ecf20Sopenharmony_ci *
1718c2ecf20Sopenharmony_ci *	Can also be called if the subdev wasn't registered. In such
1728c2ecf20Sopenharmony_ci *	case, it will do nothing.
1738c2ecf20Sopenharmony_ci */
1748c2ecf20Sopenharmony_civoid v4l2_device_unregister_subdev(struct v4l2_subdev *sd);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/**
1778c2ecf20Sopenharmony_ci * __v4l2_device_register_ro_subdev_nodes - Registers device nodes for
1788c2ecf20Sopenharmony_ci *      all subdevs of the v4l2 device that are marked with the
1798c2ecf20Sopenharmony_ci *      %V4L2_SUBDEV_FL_HAS_DEVNODE flag.
1808c2ecf20Sopenharmony_ci *
1818c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct v4l2_device
1828c2ecf20Sopenharmony_ci * @read_only: subdevices read-only flag. True to register the subdevices
1838c2ecf20Sopenharmony_ci *	device nodes in read-only mode, false to allow full access to the
1848c2ecf20Sopenharmony_ci *	subdevice userspace API.
1858c2ecf20Sopenharmony_ci */
1868c2ecf20Sopenharmony_ciint __must_check
1878c2ecf20Sopenharmony_ci__v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev,
1888c2ecf20Sopenharmony_ci				    bool read_only);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci/**
1918c2ecf20Sopenharmony_ci * v4l2_device_register_subdev_nodes - Registers subdevices device nodes with
1928c2ecf20Sopenharmony_ci *	unrestricted access to the subdevice userspace operations
1938c2ecf20Sopenharmony_ci *
1948c2ecf20Sopenharmony_ci * Internally calls __v4l2_device_register_subdev_nodes(). See its documentation
1958c2ecf20Sopenharmony_ci * for more details.
1968c2ecf20Sopenharmony_ci *
1978c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct v4l2_device
1988c2ecf20Sopenharmony_ci */
1998c2ecf20Sopenharmony_cistatic inline int __must_check
2008c2ecf20Sopenharmony_civ4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
2038c2ecf20Sopenharmony_ci	return __v4l2_device_register_subdev_nodes(v4l2_dev, false);
2048c2ecf20Sopenharmony_ci#else
2058c2ecf20Sopenharmony_ci	return 0;
2068c2ecf20Sopenharmony_ci#endif
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci/**
2108c2ecf20Sopenharmony_ci * v4l2_device_register_ro_subdev_nodes - Registers subdevices device nodes
2118c2ecf20Sopenharmony_ci *	in read-only mode
2128c2ecf20Sopenharmony_ci *
2138c2ecf20Sopenharmony_ci * Internally calls __v4l2_device_register_subdev_nodes(). See its documentation
2148c2ecf20Sopenharmony_ci * for more details.
2158c2ecf20Sopenharmony_ci *
2168c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct v4l2_device
2178c2ecf20Sopenharmony_ci */
2188c2ecf20Sopenharmony_cistatic inline int __must_check
2198c2ecf20Sopenharmony_civ4l2_device_register_ro_subdev_nodes(struct v4l2_device *v4l2_dev)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
2228c2ecf20Sopenharmony_ci	return __v4l2_device_register_subdev_nodes(v4l2_dev, true);
2238c2ecf20Sopenharmony_ci#else
2248c2ecf20Sopenharmony_ci	return 0;
2258c2ecf20Sopenharmony_ci#endif
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/**
2298c2ecf20Sopenharmony_ci * v4l2_subdev_notify - Sends a notification to v4l2_device.
2308c2ecf20Sopenharmony_ci *
2318c2ecf20Sopenharmony_ci * @sd: pointer to &struct v4l2_subdev
2328c2ecf20Sopenharmony_ci * @notification: type of notification. Please notice that the notification
2338c2ecf20Sopenharmony_ci *	type is driver-specific.
2348c2ecf20Sopenharmony_ci * @arg: arguments for the notification. Those are specific to each
2358c2ecf20Sopenharmony_ci *	notification type.
2368c2ecf20Sopenharmony_ci */
2378c2ecf20Sopenharmony_cistatic inline void v4l2_subdev_notify(struct v4l2_subdev *sd,
2388c2ecf20Sopenharmony_ci				      unsigned int notification, void *arg)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	if (sd && sd->v4l2_dev && sd->v4l2_dev->notify)
2418c2ecf20Sopenharmony_ci		sd->v4l2_dev->notify(sd, notification, arg);
2428c2ecf20Sopenharmony_ci}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci/**
2458c2ecf20Sopenharmony_ci * v4l2_device_supports_requests - Test if requests are supported.
2468c2ecf20Sopenharmony_ci *
2478c2ecf20Sopenharmony_ci * @v4l2_dev: pointer to struct v4l2_device
2488c2ecf20Sopenharmony_ci */
2498c2ecf20Sopenharmony_cistatic inline bool v4l2_device_supports_requests(struct v4l2_device *v4l2_dev)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	return v4l2_dev->mdev && v4l2_dev->mdev->ops &&
2528c2ecf20Sopenharmony_ci	       v4l2_dev->mdev->ops->req_queue;
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci/* Helper macros to iterate over all subdevs. */
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci/**
2588c2ecf20Sopenharmony_ci * v4l2_device_for_each_subdev - Helper macro that interates over all
2598c2ecf20Sopenharmony_ci *	sub-devices of a given &v4l2_device.
2608c2ecf20Sopenharmony_ci *
2618c2ecf20Sopenharmony_ci * @sd: pointer that will be filled by the macro with all
2628c2ecf20Sopenharmony_ci *	&struct v4l2_subdev pointer used as an iterator by the loop.
2638c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
2648c2ecf20Sopenharmony_ci *
2658c2ecf20Sopenharmony_ci * This macro iterates over all sub-devices owned by the @v4l2_dev device.
2668c2ecf20Sopenharmony_ci * It acts as a for loop iterator and executes the next statement with
2678c2ecf20Sopenharmony_ci * the @sd variable pointing to each sub-device in turn.
2688c2ecf20Sopenharmony_ci */
2698c2ecf20Sopenharmony_ci#define v4l2_device_for_each_subdev(sd, v4l2_dev)			\
2708c2ecf20Sopenharmony_ci	list_for_each_entry(sd, &(v4l2_dev)->subdevs, list)
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci/**
2738c2ecf20Sopenharmony_ci * __v4l2_device_call_subdevs_p - Calls the specified operation for
2748c2ecf20Sopenharmony_ci *	all subdevs matching the condition.
2758c2ecf20Sopenharmony_ci *
2768c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
2778c2ecf20Sopenharmony_ci * @sd: pointer that will be filled by the macro with all
2788c2ecf20Sopenharmony_ci *	&struct v4l2_subdev pointer used as an iterator by the loop.
2798c2ecf20Sopenharmony_ci * @cond: condition to be match
2808c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
2818c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
2828c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
2838c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
2848c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
2858c2ecf20Sopenharmony_ci * @args: arguments for @f.
2868c2ecf20Sopenharmony_ci *
2878c2ecf20Sopenharmony_ci * Ignore any errors.
2888c2ecf20Sopenharmony_ci *
2898c2ecf20Sopenharmony_ci * Note: subdevs cannot be added or deleted while walking
2908c2ecf20Sopenharmony_ci * the subdevs list.
2918c2ecf20Sopenharmony_ci */
2928c2ecf20Sopenharmony_ci#define __v4l2_device_call_subdevs_p(v4l2_dev, sd, cond, o, f, args...)	\
2938c2ecf20Sopenharmony_ci	do {								\
2948c2ecf20Sopenharmony_ci		list_for_each_entry((sd), &(v4l2_dev)->subdevs, list)	\
2958c2ecf20Sopenharmony_ci			if ((cond) && (sd)->ops->o && (sd)->ops->o->f)	\
2968c2ecf20Sopenharmony_ci				(sd)->ops->o->f((sd) , ##args);		\
2978c2ecf20Sopenharmony_ci	} while (0)
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci/**
3008c2ecf20Sopenharmony_ci * __v4l2_device_call_subdevs - Calls the specified operation for
3018c2ecf20Sopenharmony_ci *	all subdevs matching the condition.
3028c2ecf20Sopenharmony_ci *
3038c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
3048c2ecf20Sopenharmony_ci * @cond: condition to be match
3058c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
3068c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
3078c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
3088c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
3098c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
3108c2ecf20Sopenharmony_ci * @args: arguments for @f.
3118c2ecf20Sopenharmony_ci *
3128c2ecf20Sopenharmony_ci * Ignore any errors.
3138c2ecf20Sopenharmony_ci *
3148c2ecf20Sopenharmony_ci * Note: subdevs cannot be added or deleted while walking
3158c2ecf20Sopenharmony_ci * the subdevs list.
3168c2ecf20Sopenharmony_ci */
3178c2ecf20Sopenharmony_ci#define __v4l2_device_call_subdevs(v4l2_dev, cond, o, f, args...)	\
3188c2ecf20Sopenharmony_ci	do {								\
3198c2ecf20Sopenharmony_ci		struct v4l2_subdev *__sd;				\
3208c2ecf20Sopenharmony_ci									\
3218c2ecf20Sopenharmony_ci		__v4l2_device_call_subdevs_p(v4l2_dev, __sd, cond, o,	\
3228c2ecf20Sopenharmony_ci						f , ##args);		\
3238c2ecf20Sopenharmony_ci	} while (0)
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci/**
3268c2ecf20Sopenharmony_ci * __v4l2_device_call_subdevs_until_err_p - Calls the specified operation for
3278c2ecf20Sopenharmony_ci *	all subdevs matching the condition.
3288c2ecf20Sopenharmony_ci *
3298c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
3308c2ecf20Sopenharmony_ci * @sd: pointer that will be filled by the macro with all
3318c2ecf20Sopenharmony_ci *	&struct v4l2_subdev sub-devices associated with @v4l2_dev.
3328c2ecf20Sopenharmony_ci * @cond: condition to be match
3338c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
3348c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
3358c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
3368c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
3378c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
3388c2ecf20Sopenharmony_ci * @args: arguments for @f.
3398c2ecf20Sopenharmony_ci *
3408c2ecf20Sopenharmony_ci * Return:
3418c2ecf20Sopenharmony_ci *
3428c2ecf20Sopenharmony_ci * If the operation returns an error other than 0 or ``-ENOIOCTLCMD``
3438c2ecf20Sopenharmony_ci * for any subdevice, then abort and return with that error code, zero
3448c2ecf20Sopenharmony_ci * otherwise.
3458c2ecf20Sopenharmony_ci *
3468c2ecf20Sopenharmony_ci * Note: subdevs cannot be added or deleted while walking
3478c2ecf20Sopenharmony_ci * the subdevs list.
3488c2ecf20Sopenharmony_ci */
3498c2ecf20Sopenharmony_ci#define __v4l2_device_call_subdevs_until_err_p(v4l2_dev, sd, cond, o, f, args...) \
3508c2ecf20Sopenharmony_ci({									\
3518c2ecf20Sopenharmony_ci	long __err = 0;							\
3528c2ecf20Sopenharmony_ci									\
3538c2ecf20Sopenharmony_ci	list_for_each_entry((sd), &(v4l2_dev)->subdevs, list) {		\
3548c2ecf20Sopenharmony_ci		if ((cond) && (sd)->ops->o && (sd)->ops->o->f)		\
3558c2ecf20Sopenharmony_ci			__err = (sd)->ops->o->f((sd) , ##args);		\
3568c2ecf20Sopenharmony_ci		if (__err && __err != -ENOIOCTLCMD)			\
3578c2ecf20Sopenharmony_ci			break;						\
3588c2ecf20Sopenharmony_ci	}								\
3598c2ecf20Sopenharmony_ci	(__err == -ENOIOCTLCMD) ? 0 : __err;				\
3608c2ecf20Sopenharmony_ci})
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci/**
3638c2ecf20Sopenharmony_ci * __v4l2_device_call_subdevs_until_err - Calls the specified operation for
3648c2ecf20Sopenharmony_ci *	all subdevs matching the condition.
3658c2ecf20Sopenharmony_ci *
3668c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
3678c2ecf20Sopenharmony_ci * @cond: condition to be match
3688c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
3698c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
3708c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
3718c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
3728c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
3738c2ecf20Sopenharmony_ci * @args: arguments for @f.
3748c2ecf20Sopenharmony_ci *
3758c2ecf20Sopenharmony_ci * Return:
3768c2ecf20Sopenharmony_ci *
3778c2ecf20Sopenharmony_ci * If the operation returns an error other than 0 or ``-ENOIOCTLCMD``
3788c2ecf20Sopenharmony_ci * for any subdevice, then abort and return with that error code,
3798c2ecf20Sopenharmony_ci * zero otherwise.
3808c2ecf20Sopenharmony_ci *
3818c2ecf20Sopenharmony_ci * Note: subdevs cannot be added or deleted while walking
3828c2ecf20Sopenharmony_ci * the subdevs list.
3838c2ecf20Sopenharmony_ci */
3848c2ecf20Sopenharmony_ci#define __v4l2_device_call_subdevs_until_err(v4l2_dev, cond, o, f, args...) \
3858c2ecf20Sopenharmony_ci({									\
3868c2ecf20Sopenharmony_ci	struct v4l2_subdev *__sd;					\
3878c2ecf20Sopenharmony_ci	__v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd, cond, o,	\
3888c2ecf20Sopenharmony_ci						f , ##args);		\
3898c2ecf20Sopenharmony_ci})
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci/**
3928c2ecf20Sopenharmony_ci * v4l2_device_call_all - Calls the specified operation for
3938c2ecf20Sopenharmony_ci *	all subdevs matching the &v4l2_subdev.grp_id, as assigned
3948c2ecf20Sopenharmony_ci *	by the bridge driver.
3958c2ecf20Sopenharmony_ci *
3968c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
3978c2ecf20Sopenharmony_ci * @grpid: &struct v4l2_subdev->grp_id group ID to match.
3988c2ecf20Sopenharmony_ci *	    Use 0 to match them all.
3998c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
4008c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
4018c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
4028c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
4038c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
4048c2ecf20Sopenharmony_ci * @args: arguments for @f.
4058c2ecf20Sopenharmony_ci *
4068c2ecf20Sopenharmony_ci * Ignore any errors.
4078c2ecf20Sopenharmony_ci *
4088c2ecf20Sopenharmony_ci * Note: subdevs cannot be added or deleted while walking
4098c2ecf20Sopenharmony_ci * the subdevs list.
4108c2ecf20Sopenharmony_ci */
4118c2ecf20Sopenharmony_ci#define v4l2_device_call_all(v4l2_dev, grpid, o, f, args...)		\
4128c2ecf20Sopenharmony_ci	do {								\
4138c2ecf20Sopenharmony_ci		struct v4l2_subdev *__sd;				\
4148c2ecf20Sopenharmony_ci									\
4158c2ecf20Sopenharmony_ci		__v4l2_device_call_subdevs_p(v4l2_dev, __sd,		\
4168c2ecf20Sopenharmony_ci			(grpid) == 0 || __sd->grp_id == (grpid), o, f ,	\
4178c2ecf20Sopenharmony_ci			##args);					\
4188c2ecf20Sopenharmony_ci	} while (0)
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci/**
4218c2ecf20Sopenharmony_ci * v4l2_device_call_until_err - Calls the specified operation for
4228c2ecf20Sopenharmony_ci *	all subdevs matching the &v4l2_subdev.grp_id, as assigned
4238c2ecf20Sopenharmony_ci *	by the bridge driver, until an error occurs.
4248c2ecf20Sopenharmony_ci *
4258c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
4268c2ecf20Sopenharmony_ci * @grpid: &struct v4l2_subdev->grp_id group ID to match.
4278c2ecf20Sopenharmony_ci *	   Use 0 to match them all.
4288c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
4298c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
4308c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
4318c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
4328c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
4338c2ecf20Sopenharmony_ci * @args: arguments for @f.
4348c2ecf20Sopenharmony_ci *
4358c2ecf20Sopenharmony_ci * Return:
4368c2ecf20Sopenharmony_ci *
4378c2ecf20Sopenharmony_ci * If the operation returns an error other than 0 or ``-ENOIOCTLCMD``
4388c2ecf20Sopenharmony_ci * for any subdevice, then abort and return with that error code,
4398c2ecf20Sopenharmony_ci * zero otherwise.
4408c2ecf20Sopenharmony_ci *
4418c2ecf20Sopenharmony_ci * Note: subdevs cannot be added or deleted while walking
4428c2ecf20Sopenharmony_ci * the subdevs list.
4438c2ecf20Sopenharmony_ci */
4448c2ecf20Sopenharmony_ci#define v4l2_device_call_until_err(v4l2_dev, grpid, o, f, args...)	\
4458c2ecf20Sopenharmony_ci({									\
4468c2ecf20Sopenharmony_ci	struct v4l2_subdev *__sd;					\
4478c2ecf20Sopenharmony_ci	__v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd,		\
4488c2ecf20Sopenharmony_ci			(grpid) == 0 || __sd->grp_id == (grpid), o, f ,	\
4498c2ecf20Sopenharmony_ci			##args);					\
4508c2ecf20Sopenharmony_ci})
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci/**
4538c2ecf20Sopenharmony_ci * v4l2_device_mask_call_all - Calls the specified operation for
4548c2ecf20Sopenharmony_ci *	all subdevices where a group ID matches a specified bitmask.
4558c2ecf20Sopenharmony_ci *
4568c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
4578c2ecf20Sopenharmony_ci * @grpmsk: bitmask to be checked against &struct v4l2_subdev->grp_id
4588c2ecf20Sopenharmony_ci *	    group ID to be matched. Use 0 to match them all.
4598c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
4608c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
4618c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
4628c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
4638c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
4648c2ecf20Sopenharmony_ci * @args: arguments for @f.
4658c2ecf20Sopenharmony_ci *
4668c2ecf20Sopenharmony_ci * Ignore any errors.
4678c2ecf20Sopenharmony_ci *
4688c2ecf20Sopenharmony_ci * Note: subdevs cannot be added or deleted while walking
4698c2ecf20Sopenharmony_ci * the subdevs list.
4708c2ecf20Sopenharmony_ci */
4718c2ecf20Sopenharmony_ci#define v4l2_device_mask_call_all(v4l2_dev, grpmsk, o, f, args...)	\
4728c2ecf20Sopenharmony_ci	do {								\
4738c2ecf20Sopenharmony_ci		struct v4l2_subdev *__sd;				\
4748c2ecf20Sopenharmony_ci									\
4758c2ecf20Sopenharmony_ci		__v4l2_device_call_subdevs_p(v4l2_dev, __sd,		\
4768c2ecf20Sopenharmony_ci			(grpmsk) == 0 || (__sd->grp_id & (grpmsk)), o,	\
4778c2ecf20Sopenharmony_ci			f , ##args);					\
4788c2ecf20Sopenharmony_ci	} while (0)
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci/**
4818c2ecf20Sopenharmony_ci * v4l2_device_mask_call_until_err - Calls the specified operation for
4828c2ecf20Sopenharmony_ci *	all subdevices where a group ID matches a specified bitmask.
4838c2ecf20Sopenharmony_ci *
4848c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
4858c2ecf20Sopenharmony_ci * @grpmsk: bitmask to be checked against &struct v4l2_subdev->grp_id
4868c2ecf20Sopenharmony_ci *	    group ID to be matched. Use 0 to match them all.
4878c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
4888c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
4898c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
4908c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
4918c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
4928c2ecf20Sopenharmony_ci * @args: arguments for @f.
4938c2ecf20Sopenharmony_ci *
4948c2ecf20Sopenharmony_ci * Return:
4958c2ecf20Sopenharmony_ci *
4968c2ecf20Sopenharmony_ci * If the operation returns an error other than 0 or ``-ENOIOCTLCMD``
4978c2ecf20Sopenharmony_ci * for any subdevice, then abort and return with that error code,
4988c2ecf20Sopenharmony_ci * zero otherwise.
4998c2ecf20Sopenharmony_ci *
5008c2ecf20Sopenharmony_ci * Note: subdevs cannot be added or deleted while walking
5018c2ecf20Sopenharmony_ci * the subdevs list.
5028c2ecf20Sopenharmony_ci */
5038c2ecf20Sopenharmony_ci#define v4l2_device_mask_call_until_err(v4l2_dev, grpmsk, o, f, args...) \
5048c2ecf20Sopenharmony_ci({									\
5058c2ecf20Sopenharmony_ci	struct v4l2_subdev *__sd;					\
5068c2ecf20Sopenharmony_ci	__v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd,		\
5078c2ecf20Sopenharmony_ci			(grpmsk) == 0 || (__sd->grp_id & (grpmsk)), o,	\
5088c2ecf20Sopenharmony_ci			f , ##args);					\
5098c2ecf20Sopenharmony_ci})
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci/**
5138c2ecf20Sopenharmony_ci * v4l2_device_has_op - checks if any subdev with matching grpid has a
5148c2ecf20Sopenharmony_ci *	given ops.
5158c2ecf20Sopenharmony_ci *
5168c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
5178c2ecf20Sopenharmony_ci * @grpid: &struct v4l2_subdev->grp_id group ID to match.
5188c2ecf20Sopenharmony_ci *	   Use 0 to match them all.
5198c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
5208c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
5218c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
5228c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
5238c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
5248c2ecf20Sopenharmony_ci */
5258c2ecf20Sopenharmony_ci#define v4l2_device_has_op(v4l2_dev, grpid, o, f)			\
5268c2ecf20Sopenharmony_ci({									\
5278c2ecf20Sopenharmony_ci	struct v4l2_subdev *__sd;					\
5288c2ecf20Sopenharmony_ci	bool __result = false;						\
5298c2ecf20Sopenharmony_ci	list_for_each_entry(__sd, &(v4l2_dev)->subdevs, list) {		\
5308c2ecf20Sopenharmony_ci		if ((grpid) && __sd->grp_id != (grpid))			\
5318c2ecf20Sopenharmony_ci			continue;					\
5328c2ecf20Sopenharmony_ci		if (v4l2_subdev_has_op(__sd, o, f)) {			\
5338c2ecf20Sopenharmony_ci			__result = true;				\
5348c2ecf20Sopenharmony_ci			break;						\
5358c2ecf20Sopenharmony_ci		}							\
5368c2ecf20Sopenharmony_ci	}								\
5378c2ecf20Sopenharmony_ci	__result;							\
5388c2ecf20Sopenharmony_ci})
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci/**
5418c2ecf20Sopenharmony_ci * v4l2_device_mask_has_op - checks if any subdev with matching group
5428c2ecf20Sopenharmony_ci *	mask has a given ops.
5438c2ecf20Sopenharmony_ci *
5448c2ecf20Sopenharmony_ci * @v4l2_dev: &struct v4l2_device owning the sub-devices to iterate over.
5458c2ecf20Sopenharmony_ci * @grpmsk: bitmask to be checked against &struct v4l2_subdev->grp_id
5468c2ecf20Sopenharmony_ci *	    group ID to be matched. Use 0 to match them all.
5478c2ecf20Sopenharmony_ci * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
5488c2ecf20Sopenharmony_ci *     Each element there groups a set of operations functions.
5498c2ecf20Sopenharmony_ci * @f: operation function that will be called if @cond matches.
5508c2ecf20Sopenharmony_ci *	The operation functions are defined in groups, according to
5518c2ecf20Sopenharmony_ci *	each element at &struct v4l2_subdev_ops.
5528c2ecf20Sopenharmony_ci */
5538c2ecf20Sopenharmony_ci#define v4l2_device_mask_has_op(v4l2_dev, grpmsk, o, f)			\
5548c2ecf20Sopenharmony_ci({									\
5558c2ecf20Sopenharmony_ci	struct v4l2_subdev *__sd;					\
5568c2ecf20Sopenharmony_ci	bool __result = false;						\
5578c2ecf20Sopenharmony_ci	list_for_each_entry(__sd, &(v4l2_dev)->subdevs, list) {		\
5588c2ecf20Sopenharmony_ci		if ((grpmsk) && !(__sd->grp_id & (grpmsk)))		\
5598c2ecf20Sopenharmony_ci			continue;					\
5608c2ecf20Sopenharmony_ci		if (v4l2_subdev_has_op(__sd, o, f)) {			\
5618c2ecf20Sopenharmony_ci			__result = true;				\
5628c2ecf20Sopenharmony_ci			break;						\
5638c2ecf20Sopenharmony_ci		}							\
5648c2ecf20Sopenharmony_ci	}								\
5658c2ecf20Sopenharmony_ci	__result;							\
5668c2ecf20Sopenharmony_ci})
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci#endif
569