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