1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * V4L2 asynchronous subdevice registration API
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #ifndef V4L2_ASYNC_H
9*4882a593Smuzhiyun #define V4L2_ASYNC_H
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/list.h>
12*4882a593Smuzhiyun #include <linux/mutex.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun struct device;
15*4882a593Smuzhiyun struct device_node;
16*4882a593Smuzhiyun struct v4l2_device;
17*4882a593Smuzhiyun struct v4l2_subdev;
18*4882a593Smuzhiyun struct v4l2_async_notifier;
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /**
21*4882a593Smuzhiyun * enum v4l2_async_match_type - type of asynchronous subdevice logic to be used
22*4882a593Smuzhiyun * in order to identify a match
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * @V4L2_ASYNC_MATCH_CUSTOM: Match will use the logic provided by &struct
25*4882a593Smuzhiyun * v4l2_async_subdev.match ops
26*4882a593Smuzhiyun * @V4L2_ASYNC_MATCH_DEVNAME: Match will use the device name
27*4882a593Smuzhiyun * @V4L2_ASYNC_MATCH_I2C: Match will check for I2C adapter ID and address
28*4882a593Smuzhiyun * @V4L2_ASYNC_MATCH_FWNODE: Match will use firmware node
29*4882a593Smuzhiyun *
30*4882a593Smuzhiyun * This enum is used by the asyncrhronous sub-device logic to define the
31*4882a593Smuzhiyun * algorithm that will be used to match an asynchronous device.
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun enum v4l2_async_match_type {
34*4882a593Smuzhiyun V4L2_ASYNC_MATCH_CUSTOM,
35*4882a593Smuzhiyun V4L2_ASYNC_MATCH_DEVNAME,
36*4882a593Smuzhiyun V4L2_ASYNC_MATCH_I2C,
37*4882a593Smuzhiyun V4L2_ASYNC_MATCH_FWNODE,
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /**
41*4882a593Smuzhiyun * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge
42*4882a593Smuzhiyun *
43*4882a593Smuzhiyun * @match_type: type of match that will be used
44*4882a593Smuzhiyun * @match: union of per-bus type matching data sets
45*4882a593Smuzhiyun * @match.fwnode:
46*4882a593Smuzhiyun * pointer to &struct fwnode_handle to be matched.
47*4882a593Smuzhiyun * Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE.
48*4882a593Smuzhiyun * @match.device_name:
49*4882a593Smuzhiyun * string containing the device name to be matched.
50*4882a593Smuzhiyun * Used if @match_type is %V4L2_ASYNC_MATCH_DEVNAME.
51*4882a593Smuzhiyun * @match.i2c: embedded struct with I2C parameters to be matched.
52*4882a593Smuzhiyun * Both @match.i2c.adapter_id and @match.i2c.address
53*4882a593Smuzhiyun * should be matched.
54*4882a593Smuzhiyun * Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
55*4882a593Smuzhiyun * @match.i2c.adapter_id:
56*4882a593Smuzhiyun * I2C adapter ID to be matched.
57*4882a593Smuzhiyun * Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
58*4882a593Smuzhiyun * @match.i2c.address:
59*4882a593Smuzhiyun * I2C address to be matched.
60*4882a593Smuzhiyun * Used if @match_type is %V4L2_ASYNC_MATCH_I2C.
61*4882a593Smuzhiyun * @match.custom:
62*4882a593Smuzhiyun * Driver-specific match criteria.
63*4882a593Smuzhiyun * Used if @match_type is %V4L2_ASYNC_MATCH_CUSTOM.
64*4882a593Smuzhiyun * @match.custom.match:
65*4882a593Smuzhiyun * Driver-specific match function to be used if
66*4882a593Smuzhiyun * %V4L2_ASYNC_MATCH_CUSTOM.
67*4882a593Smuzhiyun * @match.custom.priv:
68*4882a593Smuzhiyun * Driver-specific private struct with match parameters
69*4882a593Smuzhiyun * to be used if %V4L2_ASYNC_MATCH_CUSTOM.
70*4882a593Smuzhiyun * @asd_list: used to add struct v4l2_async_subdev objects to the
71*4882a593Smuzhiyun * master notifier @asd_list
72*4882a593Smuzhiyun * @list: used to link struct v4l2_async_subdev objects, waiting to be
73*4882a593Smuzhiyun * probed, to a notifier->waiting list
74*4882a593Smuzhiyun *
75*4882a593Smuzhiyun * When this struct is used as a member in a driver specific struct,
76*4882a593Smuzhiyun * the driver specific struct shall contain the &struct
77*4882a593Smuzhiyun * v4l2_async_subdev as its first member.
78*4882a593Smuzhiyun */
79*4882a593Smuzhiyun struct v4l2_async_subdev {
80*4882a593Smuzhiyun enum v4l2_async_match_type match_type;
81*4882a593Smuzhiyun union {
82*4882a593Smuzhiyun struct fwnode_handle *fwnode;
83*4882a593Smuzhiyun const char *device_name;
84*4882a593Smuzhiyun struct {
85*4882a593Smuzhiyun int adapter_id;
86*4882a593Smuzhiyun unsigned short address;
87*4882a593Smuzhiyun } i2c;
88*4882a593Smuzhiyun struct {
89*4882a593Smuzhiyun bool (*match)(struct device *dev,
90*4882a593Smuzhiyun struct v4l2_async_subdev *sd);
91*4882a593Smuzhiyun void *priv;
92*4882a593Smuzhiyun } custom;
93*4882a593Smuzhiyun } match;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /* v4l2-async core private: not to be used by drivers */
96*4882a593Smuzhiyun struct list_head list;
97*4882a593Smuzhiyun struct list_head asd_list;
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /**
101*4882a593Smuzhiyun * struct v4l2_async_notifier_operations - Asynchronous V4L2 notifier operations
102*4882a593Smuzhiyun * @bound: a subdevice driver has successfully probed one of the subdevices
103*4882a593Smuzhiyun * @complete: All subdevices have been probed successfully. The complete
104*4882a593Smuzhiyun * callback is only executed for the root notifier.
105*4882a593Smuzhiyun * @unbind: a subdevice is leaving
106*4882a593Smuzhiyun */
107*4882a593Smuzhiyun struct v4l2_async_notifier_operations {
108*4882a593Smuzhiyun int (*bound)(struct v4l2_async_notifier *notifier,
109*4882a593Smuzhiyun struct v4l2_subdev *subdev,
110*4882a593Smuzhiyun struct v4l2_async_subdev *asd);
111*4882a593Smuzhiyun int (*complete)(struct v4l2_async_notifier *notifier);
112*4882a593Smuzhiyun void (*unbind)(struct v4l2_async_notifier *notifier,
113*4882a593Smuzhiyun struct v4l2_subdev *subdev,
114*4882a593Smuzhiyun struct v4l2_async_subdev *asd);
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun /**
118*4882a593Smuzhiyun * struct v4l2_async_notifier - v4l2_device notifier data
119*4882a593Smuzhiyun *
120*4882a593Smuzhiyun * @ops: notifier operations
121*4882a593Smuzhiyun * @v4l2_dev: v4l2_device of the root notifier, NULL otherwise
122*4882a593Smuzhiyun * @sd: sub-device that registered the notifier, NULL otherwise
123*4882a593Smuzhiyun * @parent: parent notifier
124*4882a593Smuzhiyun * @asd_list: master list of struct v4l2_async_subdev
125*4882a593Smuzhiyun * @waiting: list of struct v4l2_async_subdev, waiting for their drivers
126*4882a593Smuzhiyun * @done: list of struct v4l2_subdev, already probed
127*4882a593Smuzhiyun * @list: member in a global list of notifiers
128*4882a593Smuzhiyun */
129*4882a593Smuzhiyun struct v4l2_async_notifier {
130*4882a593Smuzhiyun const struct v4l2_async_notifier_operations *ops;
131*4882a593Smuzhiyun struct v4l2_device *v4l2_dev;
132*4882a593Smuzhiyun struct v4l2_subdev *sd;
133*4882a593Smuzhiyun struct v4l2_async_notifier *parent;
134*4882a593Smuzhiyun struct list_head asd_list;
135*4882a593Smuzhiyun struct list_head waiting;
136*4882a593Smuzhiyun struct list_head done;
137*4882a593Smuzhiyun struct list_head list;
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /**
141*4882a593Smuzhiyun * v4l2_async_notifier_init - Initialize a notifier.
142*4882a593Smuzhiyun *
143*4882a593Smuzhiyun * @notifier: pointer to &struct v4l2_async_notifier
144*4882a593Smuzhiyun *
145*4882a593Smuzhiyun * This function initializes the notifier @asd_list. It must be called
146*4882a593Smuzhiyun * before the first call to @v4l2_async_notifier_add_subdev.
147*4882a593Smuzhiyun */
148*4882a593Smuzhiyun void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /**
151*4882a593Smuzhiyun * v4l2_async_notifier_add_subdev - Add an async subdev to the
152*4882a593Smuzhiyun * notifier's master asd list.
153*4882a593Smuzhiyun *
154*4882a593Smuzhiyun * @notifier: pointer to &struct v4l2_async_notifier
155*4882a593Smuzhiyun * @asd: pointer to &struct v4l2_async_subdev
156*4882a593Smuzhiyun *
157*4882a593Smuzhiyun * Call this function before registering a notifier to link the provided @asd to
158*4882a593Smuzhiyun * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
159*4882a593Smuzhiyun * it will be freed by the framework when the notifier is destroyed.
160*4882a593Smuzhiyun */
161*4882a593Smuzhiyun int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
162*4882a593Smuzhiyun struct v4l2_async_subdev *asd);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /**
165*4882a593Smuzhiyun * v4l2_async_notifier_add_fwnode_subdev - Allocate and add a fwnode async
166*4882a593Smuzhiyun * subdev to the notifier's master asd_list.
167*4882a593Smuzhiyun *
168*4882a593Smuzhiyun * @notifier: pointer to &struct v4l2_async_notifier
169*4882a593Smuzhiyun * @fwnode: fwnode handle of the sub-device to be matched
170*4882a593Smuzhiyun * @asd_struct_size: size of the driver's async sub-device struct, including
171*4882a593Smuzhiyun * sizeof(struct v4l2_async_subdev). The &struct
172*4882a593Smuzhiyun * v4l2_async_subdev shall be the first member of
173*4882a593Smuzhiyun * the driver's async sub-device struct, i.e. both
174*4882a593Smuzhiyun * begin at the same memory address.
175*4882a593Smuzhiyun *
176*4882a593Smuzhiyun * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
177*4882a593Smuzhiyun * notifiers @asd_list. The function also gets a reference of the fwnode which
178*4882a593Smuzhiyun * is released later at notifier cleanup time.
179*4882a593Smuzhiyun */
180*4882a593Smuzhiyun struct v4l2_async_subdev *
181*4882a593Smuzhiyun v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
182*4882a593Smuzhiyun struct fwnode_handle *fwnode,
183*4882a593Smuzhiyun unsigned int asd_struct_size);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /**
186*4882a593Smuzhiyun * v4l2_async_notifier_add_fwnode_remote_subdev - Allocate and add a fwnode
187*4882a593Smuzhiyun * remote async subdev to the
188*4882a593Smuzhiyun * notifier's master asd_list.
189*4882a593Smuzhiyun *
190*4882a593Smuzhiyun * @notif: pointer to &struct v4l2_async_notifier
191*4882a593Smuzhiyun * @endpoint: local endpoint pointing to the remote sub-device to be matched
192*4882a593Smuzhiyun * @asd_struct_size: size of the driver's async sub-device struct, including
193*4882a593Smuzhiyun * sizeof(struct v4l2_async_subdev). The &struct
194*4882a593Smuzhiyun * v4l2_async_subdev shall be the first member of
195*4882a593Smuzhiyun * the driver's async sub-device struct, i.e. both
196*4882a593Smuzhiyun * begin at the same memory address.
197*4882a593Smuzhiyun *
198*4882a593Smuzhiyun * Gets the remote endpoint of a given local endpoint, set it up for fwnode
199*4882a593Smuzhiyun * matching and adds the async sub-device to the notifier's @asd_list. The
200*4882a593Smuzhiyun * function also gets a reference of the fwnode which is released later at
201*4882a593Smuzhiyun * notifier cleanup time.
202*4882a593Smuzhiyun *
203*4882a593Smuzhiyun * This is just like @v4l2_async_notifier_add_fwnode_subdev, but with the
204*4882a593Smuzhiyun * exception that the fwnode refers to a local endpoint, not the remote one.
205*4882a593Smuzhiyun */
206*4882a593Smuzhiyun struct v4l2_async_subdev *
207*4882a593Smuzhiyun v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
208*4882a593Smuzhiyun struct fwnode_handle *endpoint,
209*4882a593Smuzhiyun unsigned int asd_struct_size);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /**
212*4882a593Smuzhiyun * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async
213*4882a593Smuzhiyun * subdev to the notifier's master asd_list.
214*4882a593Smuzhiyun *
215*4882a593Smuzhiyun * @notifier: pointer to &struct v4l2_async_notifier
216*4882a593Smuzhiyun * @adapter_id: I2C adapter ID to be matched
217*4882a593Smuzhiyun * @address: I2C address of sub-device to be matched
218*4882a593Smuzhiyun * @asd_struct_size: size of the driver's async sub-device struct, including
219*4882a593Smuzhiyun * sizeof(struct v4l2_async_subdev). The &struct
220*4882a593Smuzhiyun * v4l2_async_subdev shall be the first member of
221*4882a593Smuzhiyun * the driver's async sub-device struct, i.e. both
222*4882a593Smuzhiyun * begin at the same memory address.
223*4882a593Smuzhiyun *
224*4882a593Smuzhiyun * Same as above but for I2C matched sub-devices.
225*4882a593Smuzhiyun */
226*4882a593Smuzhiyun struct v4l2_async_subdev *
227*4882a593Smuzhiyun v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
228*4882a593Smuzhiyun int adapter_id, unsigned short address,
229*4882a593Smuzhiyun unsigned int asd_struct_size);
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun /**
232*4882a593Smuzhiyun * v4l2_async_notifier_add_devname_subdev - Allocate and add a device-name
233*4882a593Smuzhiyun * async subdev to the notifier's master asd_list.
234*4882a593Smuzhiyun *
235*4882a593Smuzhiyun * @notifier: pointer to &struct v4l2_async_notifier
236*4882a593Smuzhiyun * @device_name: device name string to be matched
237*4882a593Smuzhiyun * @asd_struct_size: size of the driver's async sub-device struct, including
238*4882a593Smuzhiyun * sizeof(struct v4l2_async_subdev). The &struct
239*4882a593Smuzhiyun * v4l2_async_subdev shall be the first member of
240*4882a593Smuzhiyun * the driver's async sub-device struct, i.e. both
241*4882a593Smuzhiyun * begin at the same memory address.
242*4882a593Smuzhiyun *
243*4882a593Smuzhiyun * Same as above but for device-name matched sub-devices.
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun struct v4l2_async_subdev *
246*4882a593Smuzhiyun v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
247*4882a593Smuzhiyun const char *device_name,
248*4882a593Smuzhiyun unsigned int asd_struct_size);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun /**
251*4882a593Smuzhiyun * v4l2_async_notifier_register - registers a subdevice asynchronous notifier
252*4882a593Smuzhiyun *
253*4882a593Smuzhiyun * @v4l2_dev: pointer to &struct v4l2_device
254*4882a593Smuzhiyun * @notifier: pointer to &struct v4l2_async_notifier
255*4882a593Smuzhiyun */
256*4882a593Smuzhiyun int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
257*4882a593Smuzhiyun struct v4l2_async_notifier *notifier);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun /**
260*4882a593Smuzhiyun * v4l2_async_subdev_notifier_register - registers a subdevice asynchronous
261*4882a593Smuzhiyun * notifier for a sub-device
262*4882a593Smuzhiyun *
263*4882a593Smuzhiyun * @sd: pointer to &struct v4l2_subdev
264*4882a593Smuzhiyun * @notifier: pointer to &struct v4l2_async_notifier
265*4882a593Smuzhiyun */
266*4882a593Smuzhiyun int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd,
267*4882a593Smuzhiyun struct v4l2_async_notifier *notifier);
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun /**
270*4882a593Smuzhiyun * v4l2_async_notifier_clr_unready_dev - remove unready subdevice
271*4882a593Smuzhiyun *
272*4882a593Smuzhiyun * @notifier: pointer to &struct v4l2_async_notifier
273*4882a593Smuzhiyun */
274*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_NO_GKI)
275*4882a593Smuzhiyun int v4l2_async_notifier_clr_unready_dev(struct v4l2_async_notifier *notifier);
276*4882a593Smuzhiyun #else
277*4882a593Smuzhiyun static inline int
v4l2_async_notifier_clr_unready_dev(struct v4l2_async_notifier * notifier)278*4882a593Smuzhiyun v4l2_async_notifier_clr_unready_dev(struct v4l2_async_notifier *notifier)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun return 0;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun #endif
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun /**
285*4882a593Smuzhiyun * v4l2_async_notifier_unregister - unregisters a subdevice
286*4882a593Smuzhiyun * asynchronous notifier
287*4882a593Smuzhiyun *
288*4882a593Smuzhiyun * @notifier: pointer to &struct v4l2_async_notifier
289*4882a593Smuzhiyun */
290*4882a593Smuzhiyun void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun /**
293*4882a593Smuzhiyun * v4l2_async_notifier_cleanup - clean up notifier resources
294*4882a593Smuzhiyun * @notifier: the notifier the resources of which are to be cleaned up
295*4882a593Smuzhiyun *
296*4882a593Smuzhiyun * Release memory resources related to a notifier, including the async
297*4882a593Smuzhiyun * sub-devices allocated for the purposes of the notifier but not the notifier
298*4882a593Smuzhiyun * itself. The user is responsible for calling this function to clean up the
299*4882a593Smuzhiyun * notifier after calling
300*4882a593Smuzhiyun * @v4l2_async_notifier_add_subdev,
301*4882a593Smuzhiyun * @v4l2_async_notifier_parse_fwnode_endpoints or
302*4882a593Smuzhiyun * @v4l2_fwnode_reference_parse_sensor_common.
303*4882a593Smuzhiyun *
304*4882a593Smuzhiyun * There is no harm from calling v4l2_async_notifier_cleanup in other
305*4882a593Smuzhiyun * cases as long as its memory has been zeroed after it has been
306*4882a593Smuzhiyun * allocated.
307*4882a593Smuzhiyun */
308*4882a593Smuzhiyun void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier);
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun /**
311*4882a593Smuzhiyun * v4l2_async_register_subdev - registers a sub-device to the asynchronous
312*4882a593Smuzhiyun * subdevice framework
313*4882a593Smuzhiyun *
314*4882a593Smuzhiyun * @sd: pointer to &struct v4l2_subdev
315*4882a593Smuzhiyun */
316*4882a593Smuzhiyun int v4l2_async_register_subdev(struct v4l2_subdev *sd);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun /**
319*4882a593Smuzhiyun * v4l2_async_register_subdev_sensor_common - registers a sensor sub-device to
320*4882a593Smuzhiyun * the asynchronous sub-device
321*4882a593Smuzhiyun * framework and parse set up common
322*4882a593Smuzhiyun * sensor related devices
323*4882a593Smuzhiyun *
324*4882a593Smuzhiyun * @sd: pointer to struct &v4l2_subdev
325*4882a593Smuzhiyun *
326*4882a593Smuzhiyun * This function is just like v4l2_async_register_subdev() with the exception
327*4882a593Smuzhiyun * that calling it will also parse firmware interfaces for remote references
328*4882a593Smuzhiyun * using v4l2_async_notifier_parse_fwnode_sensor_common() and registers the
329*4882a593Smuzhiyun * async sub-devices. The sub-device is similarly unregistered by calling
330*4882a593Smuzhiyun * v4l2_async_unregister_subdev().
331*4882a593Smuzhiyun *
332*4882a593Smuzhiyun * While registered, the subdev module is marked as in-use.
333*4882a593Smuzhiyun *
334*4882a593Smuzhiyun * An error is returned if the module is no longer loaded on any attempts
335*4882a593Smuzhiyun * to register it.
336*4882a593Smuzhiyun */
337*4882a593Smuzhiyun int __must_check
338*4882a593Smuzhiyun v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd);
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun /**
341*4882a593Smuzhiyun * v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous
342*4882a593Smuzhiyun * subdevice framework
343*4882a593Smuzhiyun *
344*4882a593Smuzhiyun * @sd: pointer to &struct v4l2_subdev
345*4882a593Smuzhiyun */
346*4882a593Smuzhiyun void v4l2_async_unregister_subdev(struct v4l2_subdev *sd);
347*4882a593Smuzhiyun #endif
348