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