13d0407baSopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 23d0407baSopenharmony_ci/* 33d0407baSopenharmony_ci * V4L2 asynchronous subdevice registration API 43d0407baSopenharmony_ci * 53d0407baSopenharmony_ci * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.de> 63d0407baSopenharmony_ci */ 73d0407baSopenharmony_ci 83d0407baSopenharmony_ci#ifndef V4L2_ASYNC_H 93d0407baSopenharmony_ci#define V4L2_ASYNC_H 103d0407baSopenharmony_ci 113d0407baSopenharmony_ci#include <linux/list.h> 123d0407baSopenharmony_ci#include <linux/mutex.h> 133d0407baSopenharmony_ci 143d0407baSopenharmony_cistruct device; 153d0407baSopenharmony_cistruct device_node; 163d0407baSopenharmony_cistruct v4l2_device; 173d0407baSopenharmony_cistruct v4l2_subdev; 183d0407baSopenharmony_cistruct v4l2_async_notifier; 193d0407baSopenharmony_ci 203d0407baSopenharmony_ci/** 213d0407baSopenharmony_ci * enum v4l2_async_match_type - type of asynchronous subdevice logic to be used 223d0407baSopenharmony_ci * in order to identify a match 233d0407baSopenharmony_ci * 243d0407baSopenharmony_ci * @V4L2_ASYNC_MATCH_CUSTOM: Match will use the logic provided by &struct 253d0407baSopenharmony_ci * v4l2_async_subdev.match ops 263d0407baSopenharmony_ci * @V4L2_ASYNC_MATCH_DEVNAME: Match will use the device name 273d0407baSopenharmony_ci * @V4L2_ASYNC_MATCH_I2C: Match will check for I2C adapter ID and address 283d0407baSopenharmony_ci * @V4L2_ASYNC_MATCH_FWNODE: Match will use firmware node 293d0407baSopenharmony_ci * 303d0407baSopenharmony_ci * This enum is used by the asyncrhronous sub-device logic to define the 313d0407baSopenharmony_ci * algorithm that will be used to match an asynchronous device. 323d0407baSopenharmony_ci */ 333d0407baSopenharmony_cienum v4l2_async_match_type { 343d0407baSopenharmony_ci V4L2_ASYNC_MATCH_CUSTOM, 353d0407baSopenharmony_ci V4L2_ASYNC_MATCH_DEVNAME, 363d0407baSopenharmony_ci V4L2_ASYNC_MATCH_I2C, 373d0407baSopenharmony_ci V4L2_ASYNC_MATCH_FWNODE, 383d0407baSopenharmony_ci}; 393d0407baSopenharmony_ci 403d0407baSopenharmony_ci/** 413d0407baSopenharmony_ci * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge 423d0407baSopenharmony_ci * 433d0407baSopenharmony_ci * @match_type: type of match that will be used 443d0407baSopenharmony_ci * @match: union of per-bus type matching data sets 453d0407baSopenharmony_ci * @match.fwnode: 463d0407baSopenharmony_ci * pointer to &struct fwnode_handle to be matched. 473d0407baSopenharmony_ci * Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE. 483d0407baSopenharmony_ci * @match.device_name: 493d0407baSopenharmony_ci * string containing the device name to be matched. 503d0407baSopenharmony_ci * Used if @match_type is %V4L2_ASYNC_MATCH_DEVNAME. 513d0407baSopenharmony_ci * @match.i2c: embedded struct with I2C parameters to be matched. 523d0407baSopenharmony_ci * Both @match.i2c.adapter_id and @match.i2c.address 533d0407baSopenharmony_ci * should be matched. 543d0407baSopenharmony_ci * Used if @match_type is %V4L2_ASYNC_MATCH_I2C. 553d0407baSopenharmony_ci * @match.i2c.adapter_id: 563d0407baSopenharmony_ci * I2C adapter ID to be matched. 573d0407baSopenharmony_ci * Used if @match_type is %V4L2_ASYNC_MATCH_I2C. 583d0407baSopenharmony_ci * @match.i2c.address: 593d0407baSopenharmony_ci * I2C address to be matched. 603d0407baSopenharmony_ci * Used if @match_type is %V4L2_ASYNC_MATCH_I2C. 613d0407baSopenharmony_ci * @match.custom: 623d0407baSopenharmony_ci * Driver-specific match criteria. 633d0407baSopenharmony_ci * Used if @match_type is %V4L2_ASYNC_MATCH_CUSTOM. 643d0407baSopenharmony_ci * @match.custom.match: 653d0407baSopenharmony_ci * Driver-specific match function to be used if 663d0407baSopenharmony_ci * %V4L2_ASYNC_MATCH_CUSTOM. 673d0407baSopenharmony_ci * @match.custom.priv: 683d0407baSopenharmony_ci * Driver-specific private struct with match parameters 693d0407baSopenharmony_ci * to be used if %V4L2_ASYNC_MATCH_CUSTOM. 703d0407baSopenharmony_ci * @asd_list: used to add struct v4l2_async_subdev objects to the 713d0407baSopenharmony_ci * master notifier @asd_list 723d0407baSopenharmony_ci * @list: used to link struct v4l2_async_subdev objects, waiting to be 733d0407baSopenharmony_ci * probed, to a notifier->waiting list 743d0407baSopenharmony_ci * 753d0407baSopenharmony_ci * When this struct is used as a member in a driver specific struct, 763d0407baSopenharmony_ci * the driver specific struct shall contain the &struct 773d0407baSopenharmony_ci * v4l2_async_subdev as its first member. 783d0407baSopenharmony_ci */ 793d0407baSopenharmony_cistruct v4l2_async_subdev { 803d0407baSopenharmony_ci enum v4l2_async_match_type match_type; 813d0407baSopenharmony_ci union { 823d0407baSopenharmony_ci struct fwnode_handle *fwnode; 833d0407baSopenharmony_ci const char *device_name; 843d0407baSopenharmony_ci struct { 853d0407baSopenharmony_ci int adapter_id; 863d0407baSopenharmony_ci unsigned short address; 873d0407baSopenharmony_ci } i2c; 883d0407baSopenharmony_ci struct { 893d0407baSopenharmony_ci bool (*match)(struct device *dev, struct v4l2_async_subdev *sd); 903d0407baSopenharmony_ci void *priv; 913d0407baSopenharmony_ci } custom; 923d0407baSopenharmony_ci } match; 933d0407baSopenharmony_ci 943d0407baSopenharmony_ci /* v4l2-async core private: not to be used by drivers */ 953d0407baSopenharmony_ci struct list_head list; 963d0407baSopenharmony_ci struct list_head asd_list; 973d0407baSopenharmony_ci}; 983d0407baSopenharmony_ci 993d0407baSopenharmony_ci/** 1003d0407baSopenharmony_ci * struct v4l2_async_notifier_operations - Asynchronous V4L2 notifier operations 1013d0407baSopenharmony_ci * @bound: a subdevice driver has successfully probed one of the subdevices 1023d0407baSopenharmony_ci * @complete: All subdevices have been probed successfully. The complete 1033d0407baSopenharmony_ci * callback is only executed for the root notifier. 1043d0407baSopenharmony_ci * @unbind: a subdevice is leaving 1053d0407baSopenharmony_ci */ 1063d0407baSopenharmony_cistruct v4l2_async_notifier_operations { 1073d0407baSopenharmony_ci int (*bound)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd); 1083d0407baSopenharmony_ci int (*complete)(struct v4l2_async_notifier *notifier); 1093d0407baSopenharmony_ci void (*unbind)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd); 1103d0407baSopenharmony_ci}; 1113d0407baSopenharmony_ci 1123d0407baSopenharmony_ci/** 1133d0407baSopenharmony_ci * struct v4l2_async_notifier - v4l2_device notifier data 1143d0407baSopenharmony_ci * 1153d0407baSopenharmony_ci * @ops: notifier operations 1163d0407baSopenharmony_ci * @v4l2_dev: v4l2_device of the root notifier, NULL otherwise 1173d0407baSopenharmony_ci * @sd: sub-device that registered the notifier, NULL otherwise 1183d0407baSopenharmony_ci * @parent: parent notifier 1193d0407baSopenharmony_ci * @asd_list: master list of struct v4l2_async_subdev 1203d0407baSopenharmony_ci * @waiting: list of struct v4l2_async_subdev, waiting for their drivers 1213d0407baSopenharmony_ci * @done: list of struct v4l2_subdev, already probed 1223d0407baSopenharmony_ci * @list: member in a global list of notifiers 1233d0407baSopenharmony_ci */ 1243d0407baSopenharmony_cistruct v4l2_async_notifier { 1253d0407baSopenharmony_ci const struct v4l2_async_notifier_operations *ops; 1263d0407baSopenharmony_ci struct v4l2_device *v4l2_dev; 1273d0407baSopenharmony_ci struct v4l2_subdev *sd; 1283d0407baSopenharmony_ci struct v4l2_async_notifier *parent; 1293d0407baSopenharmony_ci struct list_head asd_list; 1303d0407baSopenharmony_ci struct list_head waiting; 1313d0407baSopenharmony_ci struct list_head done; 1323d0407baSopenharmony_ci struct list_head list; 1333d0407baSopenharmony_ci}; 1343d0407baSopenharmony_ci 1353d0407baSopenharmony_ci/** 1363d0407baSopenharmony_ci * v4l2_async_notifier_init - Initialize a notifier. 1373d0407baSopenharmony_ci * 1383d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier 1393d0407baSopenharmony_ci * 1403d0407baSopenharmony_ci * This function initializes the notifier @asd_list. It must be called 1413d0407baSopenharmony_ci * before the first call to @v4l2_async_notifier_add_subdev. 1423d0407baSopenharmony_ci */ 1433d0407baSopenharmony_civoid v4l2_async_notifier_init(struct v4l2_async_notifier *notifier); 1443d0407baSopenharmony_ci 1453d0407baSopenharmony_ci/** 1463d0407baSopenharmony_ci * v4l2_async_notifier_add_subdev - Add an async subdev to the 1473d0407baSopenharmony_ci * notifier's master asd list. 1483d0407baSopenharmony_ci * 1493d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier 1503d0407baSopenharmony_ci * @asd: pointer to &struct v4l2_async_subdev 1513d0407baSopenharmony_ci * 1523d0407baSopenharmony_ci * Call this function before registering a notifier to link the provided @asd to 1533d0407baSopenharmony_ci * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as 1543d0407baSopenharmony_ci * it will be freed by the framework when the notifier is destroyed. 1553d0407baSopenharmony_ci */ 1563d0407baSopenharmony_ciint v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd); 1573d0407baSopenharmony_ci 1583d0407baSopenharmony_ci/** 1593d0407baSopenharmony_ci * v4l2_async_notifier_add_fwnode_subdev - Allocate and add a fwnode async 1603d0407baSopenharmony_ci * subdev to the notifier's master asd_list. 1613d0407baSopenharmony_ci * 1623d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier 1633d0407baSopenharmony_ci * @fwnode: fwnode handle of the sub-device to be matched 1643d0407baSopenharmony_ci * @asd_struct_size: size of the driver's async sub-device struct, including 1653d0407baSopenharmony_ci * sizeof(struct v4l2_async_subdev). The &struct 1663d0407baSopenharmony_ci * v4l2_async_subdev shall be the first member of 1673d0407baSopenharmony_ci * the driver's async sub-device struct, i.e. both 1683d0407baSopenharmony_ci * begin at the same memory address. 1693d0407baSopenharmony_ci * 1703d0407baSopenharmony_ci * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the 1713d0407baSopenharmony_ci * notifiers @asd_list. The function also gets a reference of the fwnode which 1723d0407baSopenharmony_ci * is released later at notifier cleanup time. 1733d0407baSopenharmony_ci */ 1743d0407baSopenharmony_cistruct v4l2_async_subdev *v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, 1753d0407baSopenharmony_ci struct fwnode_handle *fwnode, 1763d0407baSopenharmony_ci unsigned int asd_struct_size); 1773d0407baSopenharmony_ci 1783d0407baSopenharmony_ci/** 1793d0407baSopenharmony_ci * v4l2_async_notifier_add_fwnode_remote_subdev - Allocate and add a fwnode 1803d0407baSopenharmony_ci * remote async subdev to the 1813d0407baSopenharmony_ci * notifier's master asd_list. 1823d0407baSopenharmony_ci * 1833d0407baSopenharmony_ci * @notif: pointer to &struct v4l2_async_notifier 1843d0407baSopenharmony_ci * @endpoint: local endpoint pointing to the remote sub-device to be matched 1853d0407baSopenharmony_ci * @asd_struct_size: size of the driver's async sub-device struct, including 1863d0407baSopenharmony_ci * sizeof(struct v4l2_async_subdev). The &struct 1873d0407baSopenharmony_ci * v4l2_async_subdev shall be the first member of 1883d0407baSopenharmony_ci * the driver's async sub-device struct, i.e. both 1893d0407baSopenharmony_ci * begin at the same memory address. 1903d0407baSopenharmony_ci * 1913d0407baSopenharmony_ci * Gets the remote endpoint of a given local endpoint, set it up for fwnode 1923d0407baSopenharmony_ci * matching and adds the async sub-device to the notifier's @asd_list. The 1933d0407baSopenharmony_ci * function also gets a reference of the fwnode which is released later at 1943d0407baSopenharmony_ci * notifier cleanup time. 1953d0407baSopenharmony_ci * 1963d0407baSopenharmony_ci * This is just like @v4l2_async_notifier_add_fwnode_subdev, but with the 1973d0407baSopenharmony_ci * exception that the fwnode refers to a local endpoint, not the remote one. 1983d0407baSopenharmony_ci */ 1993d0407baSopenharmony_cistruct v4l2_async_subdev *v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif, 2003d0407baSopenharmony_ci struct fwnode_handle *endpoint, 2013d0407baSopenharmony_ci unsigned int asd_struct_size); 2023d0407baSopenharmony_ci 2033d0407baSopenharmony_ci/** 2043d0407baSopenharmony_ci * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async 2053d0407baSopenharmony_ci * subdev to the notifier's master asd_list. 2063d0407baSopenharmony_ci * 2073d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier 2083d0407baSopenharmony_ci * @adapter_id: I2C adapter ID to be matched 2093d0407baSopenharmony_ci * @address: I2C address of sub-device to be matched 2103d0407baSopenharmony_ci * @asd_struct_size: size of the driver's async sub-device struct, including 2113d0407baSopenharmony_ci * sizeof(struct v4l2_async_subdev). The &struct 2123d0407baSopenharmony_ci * v4l2_async_subdev shall be the first member of 2133d0407baSopenharmony_ci * the driver's async sub-device struct, i.e. both 2143d0407baSopenharmony_ci * begin at the same memory address. 2153d0407baSopenharmony_ci * 2163d0407baSopenharmony_ci * Same as above but for I2C matched sub-devices. 2173d0407baSopenharmony_ci */ 2183d0407baSopenharmony_cistruct v4l2_async_subdev *v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier, int adapter_id, 2193d0407baSopenharmony_ci unsigned short address, unsigned int asd_struct_size); 2203d0407baSopenharmony_ci 2213d0407baSopenharmony_ci/** 2223d0407baSopenharmony_ci * v4l2_async_notifier_add_devname_subdev - Allocate and add a device-name 2233d0407baSopenharmony_ci * async subdev to the notifier's master asd_list. 2243d0407baSopenharmony_ci * 2253d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier 2263d0407baSopenharmony_ci * @device_name: device name string to be matched 2273d0407baSopenharmony_ci * @asd_struct_size: size of the driver's async sub-device struct, including 2283d0407baSopenharmony_ci * sizeof(struct v4l2_async_subdev). The &struct 2293d0407baSopenharmony_ci * v4l2_async_subdev shall be the first member of 2303d0407baSopenharmony_ci * the driver's async sub-device struct, i.e. both 2313d0407baSopenharmony_ci * begin at the same memory address. 2323d0407baSopenharmony_ci * 2333d0407baSopenharmony_ci * Same as above but for device-name matched sub-devices. 2343d0407baSopenharmony_ci */ 2353d0407baSopenharmony_cistruct v4l2_async_subdev *v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier, 2363d0407baSopenharmony_ci const char *device_name, unsigned int asd_struct_size); 2373d0407baSopenharmony_ci 2383d0407baSopenharmony_ci/** 2393d0407baSopenharmony_ci * v4l2_async_notifier_register - registers a subdevice asynchronous notifier 2403d0407baSopenharmony_ci * 2413d0407baSopenharmony_ci * @v4l2_dev: pointer to &struct v4l2_device 2423d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier 2433d0407baSopenharmony_ci */ 2443d0407baSopenharmony_ciint v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, struct v4l2_async_notifier *notifier); 2453d0407baSopenharmony_ci 2463d0407baSopenharmony_ci/** 2473d0407baSopenharmony_ci * v4l2_async_subdev_notifier_register - registers a subdevice asynchronous 2483d0407baSopenharmony_ci * notifier for a sub-device 2493d0407baSopenharmony_ci * 2503d0407baSopenharmony_ci * @sd: pointer to &struct v4l2_subdev 2513d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier 2523d0407baSopenharmony_ci */ 2533d0407baSopenharmony_ciint v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd, struct v4l2_async_notifier *notifier); 2543d0407baSopenharmony_ci 2553d0407baSopenharmony_ci/** 2563d0407baSopenharmony_ci * v4l2_async_notifier_clr_unready_dev - remove unready subdevice 2573d0407baSopenharmony_ci * 2583d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier 2593d0407baSopenharmony_ci */ 2603d0407baSopenharmony_ci#if IS_ENABLED(CONFIG_NO_GKI) 2613d0407baSopenharmony_ciint v4l2_async_notifier_clr_unready_dev(struct v4l2_async_notifier *notifier); 2623d0407baSopenharmony_ci#else 2633d0407baSopenharmony_cistatic inline int v4l2_async_notifier_clr_unready_dev(struct v4l2_async_notifier *notifier) 2643d0407baSopenharmony_ci{ 2653d0407baSopenharmony_ci return 0; 2663d0407baSopenharmony_ci} 2673d0407baSopenharmony_ci#endif 2683d0407baSopenharmony_ci 2693d0407baSopenharmony_ci/** 2703d0407baSopenharmony_ci * v4l2_async_notifier_unregister - unregisters a subdevice 2713d0407baSopenharmony_ci * asynchronous notifier 2723d0407baSopenharmony_ci * 2733d0407baSopenharmony_ci * @notifier: pointer to &struct v4l2_async_notifier 2743d0407baSopenharmony_ci */ 2753d0407baSopenharmony_civoid v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier); 2763d0407baSopenharmony_ci 2773d0407baSopenharmony_ci/** 2783d0407baSopenharmony_ci * v4l2_async_notifier_cleanup - clean up notifier resources 2793d0407baSopenharmony_ci * @notifier: the notifier the resources of which are to be cleaned up 2803d0407baSopenharmony_ci * 2813d0407baSopenharmony_ci * Release memory resources related to a notifier, including the async 2823d0407baSopenharmony_ci * sub-devices allocated for the purposes of the notifier but not the notifier 2833d0407baSopenharmony_ci * itself. The user is responsible for calling this function to clean up the 2843d0407baSopenharmony_ci * notifier after calling 2853d0407baSopenharmony_ci * @v4l2_async_notifier_add_subdev, 2863d0407baSopenharmony_ci * @v4l2_async_notifier_parse_fwnode_endpoints or 2873d0407baSopenharmony_ci * @v4l2_fwnode_reference_parse_sensor_common. 2883d0407baSopenharmony_ci * 2893d0407baSopenharmony_ci * There is no harm from calling v4l2_async_notifier_cleanup in other 2903d0407baSopenharmony_ci * cases as long as its memory has been zeroed after it has been 2913d0407baSopenharmony_ci * allocated. 2923d0407baSopenharmony_ci */ 2933d0407baSopenharmony_civoid v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier); 2943d0407baSopenharmony_ci 2953d0407baSopenharmony_ci/** 2963d0407baSopenharmony_ci * v4l2_async_register_subdev - registers a sub-device to the asynchronous 2973d0407baSopenharmony_ci * subdevice framework 2983d0407baSopenharmony_ci * 2993d0407baSopenharmony_ci * @sd: pointer to &struct v4l2_subdev 3003d0407baSopenharmony_ci */ 3013d0407baSopenharmony_ciint v4l2_async_register_subdev(struct v4l2_subdev *sd); 3023d0407baSopenharmony_ci 3033d0407baSopenharmony_ci/** 3043d0407baSopenharmony_ci * v4l2_async_register_subdev_sensor_common - registers a sensor sub-device to 3053d0407baSopenharmony_ci * the asynchronous sub-device 3063d0407baSopenharmony_ci * framework and parse set up common 3073d0407baSopenharmony_ci * sensor related devices 3083d0407baSopenharmony_ci * 3093d0407baSopenharmony_ci * @sd: pointer to struct &v4l2_subdev 3103d0407baSopenharmony_ci * 3113d0407baSopenharmony_ci * This function is just like v4l2_async_register_subdev() with the exception 3123d0407baSopenharmony_ci * that calling it will also parse firmware interfaces for remote references 3133d0407baSopenharmony_ci * using v4l2_async_notifier_parse_fwnode_sensor_common() and registers the 3143d0407baSopenharmony_ci * async sub-devices. The sub-device is similarly unregistered by calling 3153d0407baSopenharmony_ci * v4l2_async_unregister_subdev(). 3163d0407baSopenharmony_ci * 3173d0407baSopenharmony_ci * While registered, the subdev module is marked as in-use. 3183d0407baSopenharmony_ci * 3193d0407baSopenharmony_ci * An error is returned if the module is no longer loaded on any attempts 3203d0407baSopenharmony_ci * to register it. 3213d0407baSopenharmony_ci */ 3223d0407baSopenharmony_ciint __must_check v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd); 3233d0407baSopenharmony_ci 3243d0407baSopenharmony_ci/** 3253d0407baSopenharmony_ci * v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous 3263d0407baSopenharmony_ci * subdevice framework 3273d0407baSopenharmony_ci * 3283d0407baSopenharmony_ci * @sd: pointer to &struct v4l2_subdev 3293d0407baSopenharmony_ci */ 3303d0407baSopenharmony_civoid v4l2_async_unregister_subdev(struct v4l2_subdev *sd); 3313d0407baSopenharmony_ci#endif 332