1 /*
2  * V4L2 fwnode binding parsing library
3  *
4  * The origins of the V4L2 fwnode library are in V4L2 OF library that
5  * formerly was located in v4l2-of.c.
6  *
7  * Copyright (c) 2016 Intel Corporation.
8  * Author: Sakari Ailus <sakari.ailus@linux.intel.com>
9  *
10  * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
11  * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
12  *
13  * Copyright (C) 2012 Renesas Electronics Corp.
14  * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of version 2 of the GNU General Public License as
18  * published by the Free Software Foundation.
19  */
20 #include <linux/acpi.h>
21 #include <linux/kernel.h>
22 #include <linux/mm.h>
23 #include <linux/module.h>
24 #include <linux/of.h>
25 #include <linux/property.h>
26 #include <linux/slab.h>
27 #include <linux/string.h>
28 #include <linux/types.h>
29 
30 #include <media/v4l2-async.h>
31 #include <media/v4l2-fwnode.h>
32 #include <media/v4l2-subdev.h>
33 
34 enum v4l2_fwnode_bus_type {
35 	V4L2_FWNODE_BUS_TYPE_GUESS = 0,
36 	V4L2_FWNODE_BUS_TYPE_CSI2_CPHY,
37 	V4L2_FWNODE_BUS_TYPE_CSI1,
38 	V4L2_FWNODE_BUS_TYPE_CCP2,
39 	NR_OF_V4L2_FWNODE_BUS_TYPE,
40 };
41 
42 static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode,
43 					       struct v4l2_fwnode_endpoint *vep)
44 {
45 	struct v4l2_fwnode_bus_mipi_csi2 *bus = &vep->bus.mipi_csi2;
46 	bool have_clk_lane = false;
47 	unsigned int flags = 0, lanes_used = 0;
48 	unsigned int i;
49 	u32 v;
50 	int rval;
51 
52 	rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0);
53 	if (rval > 0) {
54 		u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES];
55 
56 		bus->num_data_lanes =
57 			min_t(int, V4L2_FWNODE_CSI2_MAX_DATA_LANES, rval);
58 
59 		fwnode_property_read_u32_array(fwnode, "data-lanes", array,
60 					       bus->num_data_lanes);
61 
62 		for (i = 0; i < bus->num_data_lanes; i++) {
63 			if (lanes_used & BIT(array[i]))
64 				pr_warn("duplicated lane %u in data-lanes\n",
65 					array[i]);
66 			lanes_used |= BIT(array[i]);
67 
68 			bus->data_lanes[i] = array[i];
69 		}
70 
71 		rval = fwnode_property_read_u32_array(fwnode,
72 						      "lane-polarities", NULL,
73 						      0);
74 		if (rval > 0) {
75 			if (rval != 1 + bus->num_data_lanes /* clock+data */) {
76 				pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n",
77 					1 + bus->num_data_lanes, rval);
78 				return -EINVAL;
79 			}
80 
81 			fwnode_property_read_u32_array(fwnode,
82 						       "lane-polarities", array,
83 						       1 + bus->num_data_lanes);
84 
85 			for (i = 0; i < 1 + bus->num_data_lanes; i++)
86 				bus->lane_polarities[i] = array[i];
87 		}
88 
89 	}
90 
91 	if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) {
92 		if (lanes_used & BIT(v))
93 			pr_warn("duplicated lane %u in clock-lanes\n", v);
94 		lanes_used |= BIT(v);
95 
96 		bus->clock_lane = v;
97 		have_clk_lane = true;
98 	}
99 
100 	if (fwnode_property_present(fwnode, "clock-noncontinuous"))
101 		flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
102 	else if (have_clk_lane || bus->num_data_lanes > 0)
103 		flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
104 
105 	bus->flags = flags;
106 	vep->bus_type = V4L2_MBUS_CSI2;
107 
108 	return 0;
109 }
110 
111 static void v4l2_fwnode_endpoint_parse_parallel_bus(
112 	struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep)
113 {
114 	struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel;
115 	unsigned int flags = 0;
116 	u32 v;
117 
118 	if (!fwnode_property_read_u32(fwnode, "hsync-active", &v))
119 		flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH :
120 			V4L2_MBUS_HSYNC_ACTIVE_LOW;
121 
122 	if (!fwnode_property_read_u32(fwnode, "vsync-active", &v))
123 		flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH :
124 			V4L2_MBUS_VSYNC_ACTIVE_LOW;
125 
126 	if (!fwnode_property_read_u32(fwnode, "field-even-active", &v))
127 		flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH :
128 			V4L2_MBUS_FIELD_EVEN_LOW;
129 	if (flags)
130 		vep->bus_type = V4L2_MBUS_PARALLEL;
131 	else
132 		vep->bus_type = V4L2_MBUS_BT656;
133 
134 	if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v))
135 		flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING :
136 			V4L2_MBUS_PCLK_SAMPLE_FALLING;
137 
138 	if (!fwnode_property_read_u32(fwnode, "data-active", &v))
139 		flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH :
140 			V4L2_MBUS_DATA_ACTIVE_LOW;
141 
142 	if (fwnode_property_present(fwnode, "slave-mode"))
143 		flags |= V4L2_MBUS_SLAVE;
144 	else
145 		flags |= V4L2_MBUS_MASTER;
146 
147 	if (!fwnode_property_read_u32(fwnode, "bus-width", &v))
148 		bus->bus_width = v;
149 
150 	if (!fwnode_property_read_u32(fwnode, "data-shift", &v))
151 		bus->data_shift = v;
152 
153 	if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v))
154 		flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH :
155 			V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW;
156 
157 	if (!fwnode_property_read_u32(fwnode, "data-enable-active", &v))
158 		flags |= v ? V4L2_MBUS_DATA_ENABLE_HIGH :
159 			V4L2_MBUS_DATA_ENABLE_LOW;
160 
161 	bus->flags = flags;
162 
163 }
164 
165 static void
166 v4l2_fwnode_endpoint_parse_csi1_bus(struct fwnode_handle *fwnode,
167 				    struct v4l2_fwnode_endpoint *vep,
168 				    u32 bus_type)
169 {
170 	struct v4l2_fwnode_bus_mipi_csi1 *bus = &vep->bus.mipi_csi1;
171 	u32 v;
172 
173 	if (!fwnode_property_read_u32(fwnode, "clock-inv", &v))
174 		bus->clock_inv = v;
175 
176 	if (!fwnode_property_read_u32(fwnode, "strobe", &v))
177 		bus->strobe = v;
178 
179 	if (!fwnode_property_read_u32(fwnode, "data-lanes", &v))
180 		bus->data_lane = v;
181 
182 	if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v))
183 		bus->clock_lane = v;
184 
185 	if (bus_type == V4L2_FWNODE_BUS_TYPE_CCP2)
186 		vep->bus_type = V4L2_MBUS_CCP2;
187 	else
188 		vep->bus_type = V4L2_MBUS_CSI1;
189 }
190 
191 int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
192 			       struct v4l2_fwnode_endpoint *vep)
193 {
194 	u32 bus_type = 0;
195 	int rval;
196 
197 	fwnode_graph_parse_endpoint(fwnode, &vep->base);
198 
199 	/* Zero fields from bus_type to until the end */
200 	memset(&vep->bus_type, 0, sizeof(*vep) -
201 	       offsetof(typeof(*vep), bus_type));
202 
203 	fwnode_property_read_u32(fwnode, "bus-type", &bus_type);
204 
205 	switch (bus_type) {
206 	case V4L2_FWNODE_BUS_TYPE_GUESS:
207 		rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep);
208 		if (rval)
209 			return rval;
210 		/*
211 		 * Parse the parallel video bus properties only if none
212 		 * of the MIPI CSI-2 specific properties were found.
213 		 */
214 		if (vep->bus.mipi_csi2.flags == 0)
215 			v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep);
216 
217 		return 0;
218 	case V4L2_FWNODE_BUS_TYPE_CCP2:
219 	case V4L2_FWNODE_BUS_TYPE_CSI1:
220 		v4l2_fwnode_endpoint_parse_csi1_bus(fwnode, vep, bus_type);
221 
222 		return 0;
223 	default:
224 		pr_warn("unsupported bus type %u\n", bus_type);
225 		return -EINVAL;
226 	}
227 }
228 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_parse);
229 
230 void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep)
231 {
232 	if (IS_ERR_OR_NULL(vep))
233 		return;
234 
235 	kfree(vep->link_frequencies);
236 	kfree(vep);
237 }
238 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_free);
239 
240 struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse(
241 	struct fwnode_handle *fwnode)
242 {
243 	struct v4l2_fwnode_endpoint *vep;
244 	int rval;
245 
246 	vep = kzalloc(sizeof(*vep), GFP_KERNEL);
247 	if (!vep)
248 		return ERR_PTR(-ENOMEM);
249 
250 	rval = v4l2_fwnode_endpoint_parse(fwnode, vep);
251 	if (rval < 0)
252 		goto out_err;
253 
254 	rval = fwnode_property_read_u64_array(fwnode, "link-frequencies",
255 					      NULL, 0);
256 	if (rval > 0) {
257 		vep->link_frequencies =
258 			kmalloc_array(rval, sizeof(*vep->link_frequencies),
259 				      GFP_KERNEL);
260 		if (!vep->link_frequencies) {
261 			rval = -ENOMEM;
262 			goto out_err;
263 		}
264 
265 		vep->nr_of_link_frequencies = rval;
266 
267 		rval = fwnode_property_read_u64_array(
268 			fwnode, "link-frequencies", vep->link_frequencies,
269 			vep->nr_of_link_frequencies);
270 		if (rval < 0)
271 			goto out_err;
272 	}
273 
274 	return vep;
275 
276 out_err:
277 	v4l2_fwnode_endpoint_free(vep);
278 	return ERR_PTR(rval);
279 }
280 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse);
281 
282 int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode,
283 			   struct v4l2_fwnode_link *link)
284 {
285 	const char *port_prop = is_of_node(__fwnode) ? "reg" : "port";
286 	struct fwnode_handle *fwnode;
287 
288 	memset(link, 0, sizeof(*link));
289 
290 	fwnode = fwnode_get_parent(__fwnode);
291 	fwnode_property_read_u32(fwnode, port_prop, &link->local_port);
292 	fwnode = fwnode_get_next_parent(fwnode);
293 	if (is_of_node(fwnode) &&
294 	    of_node_cmp(to_of_node(fwnode)->name, "ports") == 0)
295 		fwnode = fwnode_get_next_parent(fwnode);
296 	link->local_node = fwnode;
297 
298 	fwnode = fwnode_graph_get_remote_endpoint(__fwnode);
299 	if (!fwnode) {
300 		fwnode_handle_put(fwnode);
301 		return -ENOLINK;
302 	}
303 
304 	fwnode = fwnode_get_parent(fwnode);
305 	fwnode_property_read_u32(fwnode, port_prop, &link->remote_port);
306 	fwnode = fwnode_get_next_parent(fwnode);
307 	if (is_of_node(fwnode) &&
308 	    of_node_cmp(to_of_node(fwnode)->name, "ports") == 0)
309 		fwnode = fwnode_get_next_parent(fwnode);
310 	link->remote_node = fwnode;
311 
312 	return 0;
313 }
314 EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_link);
315 
316 void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link)
317 {
318 	fwnode_handle_put(link->local_node);
319 	fwnode_handle_put(link->remote_node);
320 }
321 EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
322 
323 static int v4l2_async_notifier_realloc(struct v4l2_async_notifier *notifier,
324 				       unsigned int max_subdevs)
325 {
326 	struct v4l2_async_subdev **subdevs;
327 
328 	if (max_subdevs <= notifier->max_subdevs)
329 		return 0;
330 
331 	subdevs = kvmalloc_array(
332 		max_subdevs, sizeof(*notifier->subdevs),
333 		GFP_KERNEL | __GFP_ZERO);
334 	if (!subdevs)
335 		return -ENOMEM;
336 
337 	if (notifier->subdevs) {
338 		memcpy(subdevs, notifier->subdevs,
339 		       sizeof(*subdevs) * notifier->num_subdevs);
340 
341 		kvfree(notifier->subdevs);
342 	}
343 
344 	notifier->subdevs = subdevs;
345 	notifier->max_subdevs = max_subdevs;
346 
347 	return 0;
348 }
349 
350 static int v4l2_async_notifier_fwnode_parse_endpoint(
351 	struct device *dev, struct v4l2_async_notifier *notifier,
352 	struct fwnode_handle *endpoint, unsigned int asd_struct_size,
353 	int (*parse_endpoint)(struct device *dev,
354 			    struct v4l2_fwnode_endpoint *vep,
355 			    struct v4l2_async_subdev *asd))
356 {
357 	struct v4l2_async_subdev *asd;
358 	struct v4l2_fwnode_endpoint *vep;
359 	int ret = 0;
360 
361 	asd = kzalloc(asd_struct_size, GFP_KERNEL);
362 	if (!asd)
363 		return -ENOMEM;
364 
365 	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
366 	asd->match.fwnode =
367 		fwnode_graph_get_remote_port_parent(endpoint);
368 	if (!asd->match.fwnode) {
369 		dev_warn(dev, "bad remote port parent\n");
370 		ret = -EINVAL;
371 		goto out_err;
372 	}
373 
374 	vep = v4l2_fwnode_endpoint_alloc_parse(endpoint);
375 	if (IS_ERR(vep)) {
376 		ret = PTR_ERR(vep);
377 		dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n",
378 			 ret);
379 		goto out_err;
380 	}
381 
382 	ret = parse_endpoint ? parse_endpoint(dev, vep, asd) : 0;
383 	if (ret == -ENOTCONN)
384 		dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep->base.port,
385 			vep->base.id);
386 	else if (ret < 0)
387 		dev_warn(dev,
388 			 "driver could not parse port@%u/endpoint@%u (%d)\n",
389 			 vep->base.port, vep->base.id, ret);
390 	v4l2_fwnode_endpoint_free(vep);
391 	if (ret < 0)
392 		goto out_err;
393 
394 	notifier->subdevs[notifier->num_subdevs] = asd;
395 	notifier->num_subdevs++;
396 
397 	return 0;
398 
399 out_err:
400 	fwnode_handle_put(asd->match.fwnode);
401 	kfree(asd);
402 
403 	return ret == -ENOTCONN ? 0 : ret;
404 }
405 
406 static int __v4l2_async_notifier_parse_fwnode_endpoints(
407 	struct device *dev, struct v4l2_async_notifier *notifier,
408 	size_t asd_struct_size, unsigned int port, bool has_port,
409 	int (*parse_endpoint)(struct device *dev,
410 			    struct v4l2_fwnode_endpoint *vep,
411 			    struct v4l2_async_subdev *asd))
412 {
413 	struct fwnode_handle *fwnode;
414 	unsigned int max_subdevs = notifier->max_subdevs;
415 	int ret;
416 
417 	if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
418 		return -EINVAL;
419 
420 	for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
421 				     dev_fwnode(dev), fwnode)); ) {
422 		struct fwnode_handle *dev_fwnode;
423 		bool is_available;
424 
425 		dev_fwnode = fwnode_graph_get_port_parent(fwnode);
426 		is_available = fwnode_device_is_available(dev_fwnode);
427 		fwnode_handle_put(dev_fwnode);
428 		if (!is_available)
429 			continue;
430 
431 		if (has_port) {
432 			struct fwnode_endpoint ep;
433 
434 			ret = fwnode_graph_parse_endpoint(fwnode, &ep);
435 			if (ret) {
436 				fwnode_handle_put(fwnode);
437 				return ret;
438 			}
439 
440 			if (ep.port != port)
441 				continue;
442 		}
443 		max_subdevs++;
444 	}
445 
446 	/* No subdevs to add? Return here. */
447 	if (max_subdevs == notifier->max_subdevs)
448 		return 0;
449 
450 	ret = v4l2_async_notifier_realloc(notifier, max_subdevs);
451 	if (ret)
452 		return ret;
453 
454 	for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
455 				     dev_fwnode(dev), fwnode)); ) {
456 		struct fwnode_handle *dev_fwnode;
457 		bool is_available;
458 
459 		dev_fwnode = fwnode_graph_get_port_parent(fwnode);
460 		is_available = fwnode_device_is_available(dev_fwnode);
461 		fwnode_handle_put(dev_fwnode);
462 		if (!is_available)
463 			continue;
464 
465 		if (has_port) {
466 			struct fwnode_endpoint ep;
467 
468 			ret = fwnode_graph_parse_endpoint(fwnode, &ep);
469 			if (ret)
470 				break;
471 
472 			if (ep.port != port)
473 				continue;
474 		}
475 
476 		if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
477 			ret = -EINVAL;
478 			break;
479 		}
480 
481 		ret = v4l2_async_notifier_fwnode_parse_endpoint(
482 			dev, notifier, fwnode, asd_struct_size, parse_endpoint);
483 		if (ret < 0)
484 			break;
485 	}
486 
487 	fwnode_handle_put(fwnode);
488 
489 	return ret;
490 }
491 
492 int v4l2_async_notifier_parse_fwnode_endpoints(
493 	struct device *dev, struct v4l2_async_notifier *notifier,
494 	size_t asd_struct_size,
495 	int (*parse_endpoint)(struct device *dev,
496 			    struct v4l2_fwnode_endpoint *vep,
497 			    struct v4l2_async_subdev *asd))
498 {
499 	return __v4l2_async_notifier_parse_fwnode_endpoints(
500 		dev, notifier, asd_struct_size, 0, false, parse_endpoint);
501 }
502 EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints);
503 
504 int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
505 	struct device *dev, struct v4l2_async_notifier *notifier,
506 	size_t asd_struct_size, unsigned int port,
507 	int (*parse_endpoint)(struct device *dev,
508 			    struct v4l2_fwnode_endpoint *vep,
509 			    struct v4l2_async_subdev *asd))
510 {
511 	return __v4l2_async_notifier_parse_fwnode_endpoints(
512 		dev, notifier, asd_struct_size, port, true, parse_endpoint);
513 }
514 EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port);
515 
516 /*
517  * v4l2_fwnode_reference_parse - parse references for async sub-devices
518  * @dev: the device node the properties of which are parsed for references
519  * @notifier: the async notifier where the async subdevs will be added
520  * @prop: the name of the property
521  *
522  * Return: 0 on success
523  *	   -ENOENT if no entries were found
524  *	   -ENOMEM if memory allocation failed
525  *	   -EINVAL if property parsing failed
526  */
527 static int v4l2_fwnode_reference_parse(
528 	struct device *dev, struct v4l2_async_notifier *notifier,
529 	const char *prop)
530 {
531 	struct fwnode_reference_args args;
532 	unsigned int index;
533 	int ret;
534 
535 	for (index = 0;
536 	     !(ret = fwnode_property_get_reference_args(
537 		       dev_fwnode(dev), prop, NULL, 0, index, &args));
538 	     index++)
539 		fwnode_handle_put(args.fwnode);
540 
541 	if (!index)
542 		return -ENOENT;
543 
544 	/*
545 	 * Note that right now both -ENODATA and -ENOENT may signal
546 	 * out-of-bounds access. Return the error in cases other than that.
547 	 */
548 	if (ret != -ENOENT && ret != -ENODATA)
549 		return ret;
550 
551 	ret = v4l2_async_notifier_realloc(notifier,
552 					  notifier->num_subdevs + index);
553 	if (ret)
554 		return ret;
555 
556 	for (index = 0; !fwnode_property_get_reference_args(
557 		     dev_fwnode(dev), prop, NULL, 0, index, &args);
558 	     index++) {
559 		struct v4l2_async_subdev *asd;
560 
561 		if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
562 			ret = -EINVAL;
563 			goto error;
564 		}
565 
566 		asd = kzalloc(sizeof(*asd), GFP_KERNEL);
567 		if (!asd) {
568 			ret = -ENOMEM;
569 			goto error;
570 		}
571 
572 		notifier->subdevs[notifier->num_subdevs] = asd;
573 		asd->match.fwnode = args.fwnode;
574 		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
575 		notifier->num_subdevs++;
576 	}
577 
578 	return 0;
579 
580 error:
581 	fwnode_handle_put(args.fwnode);
582 	return ret;
583 }
584 
585 /*
586  * v4l2_fwnode_reference_get_int_prop - parse a reference with integer
587  *					arguments
588  * @fwnode: fwnode to read @prop from
589  * @notifier: notifier for @dev
590  * @prop: the name of the property
591  * @index: the index of the reference to get
592  * @props: the array of integer property names
593  * @nprops: the number of integer property names in @nprops
594  *
595  * First find an fwnode referred to by the reference at @index in @prop.
596  *
597  * Then under that fwnode, @nprops times, for each property in @props,
598  * iteratively follow child nodes starting from fwnode such that they have the
599  * property in @props array at the index of the child node distance from the
600  * root node and the value of that property matching with the integer argument
601  * of the reference, at the same index.
602  *
603  * The child fwnode reched at the end of the iteration is then returned to the
604  * caller.
605  *
606  * The core reason for this is that you cannot refer to just any node in ACPI.
607  * So to refer to an endpoint (easy in DT) you need to refer to a device, then
608  * provide a list of (property name, property value) tuples where each tuple
609  * uniquely identifies a child node. The first tuple identifies a child directly
610  * underneath the device fwnode, the next tuple identifies a child node
611  * underneath the fwnode identified by the previous tuple, etc. until you
612  * reached the fwnode you need.
613  *
614  * An example with a graph, as defined in Documentation/acpi/dsd/graph.txt:
615  *
616  *	Scope (\_SB.PCI0.I2C2)
617  *	{
618  *		Device (CAM0)
619  *		{
620  *			Name (_DSD, Package () {
621  *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
622  *				Package () {
623  *					Package () {
624  *						"compatible",
625  *						Package () { "nokia,smia" }
626  *					},
627  *				},
628  *				ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
629  *				Package () {
630  *					Package () { "port0", "PRT0" },
631  *				}
632  *			})
633  *			Name (PRT0, Package() {
634  *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
635  *				Package () {
636  *					Package () { "port", 0 },
637  *				},
638  *				ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
639  *				Package () {
640  *					Package () { "endpoint0", "EP00" },
641  *				}
642  *			})
643  *			Name (EP00, Package() {
644  *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
645  *				Package () {
646  *					Package () { "endpoint", 0 },
647  *					Package () {
648  *						"remote-endpoint",
649  *						Package() {
650  *							\_SB.PCI0.ISP, 4, 0
651  *						}
652  *					},
653  *				}
654  *			})
655  *		}
656  *	}
657  *
658  *	Scope (\_SB.PCI0)
659  *	{
660  *		Device (ISP)
661  *		{
662  *			Name (_DSD, Package () {
663  *				ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
664  *				Package () {
665  *					Package () { "port4", "PRT4" },
666  *				}
667  *			})
668  *
669  *			Name (PRT4, Package() {
670  *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
671  *				Package () {
672  *					Package () { "port", 4 },
673  *				},
674  *				ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
675  *				Package () {
676  *					Package () { "endpoint0", "EP40" },
677  *				}
678  *			})
679  *
680  *			Name (EP40, Package() {
681  *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
682  *				Package () {
683  *					Package () { "endpoint", 0 },
684  *					Package () {
685  *						"remote-endpoint",
686  *						Package () {
687  *							\_SB.PCI0.I2C2.CAM0,
688  *							0, 0
689  *						}
690  *					},
691  *				}
692  *			})
693  *		}
694  *	}
695  *
696  * From the EP40 node under ISP device, you could parse the graph remote
697  * endpoint using v4l2_fwnode_reference_get_int_prop with these arguments:
698  *
699  *  @fwnode: fwnode referring to EP40 under ISP.
700  *  @prop: "remote-endpoint"
701  *  @index: 0
702  *  @props: "port", "endpoint"
703  *  @nprops: 2
704  *
705  * And you'd get back fwnode referring to EP00 under CAM0.
706  *
707  * The same works the other way around: if you use EP00 under CAM0 as the
708  * fwnode, you'll get fwnode referring to EP40 under ISP.
709  *
710  * The same example in DT syntax would look like this:
711  *
712  * cam: cam0 {
713  *	compatible = "nokia,smia";
714  *
715  *	port {
716  *		port = <0>;
717  *		endpoint {
718  *			endpoint = <0>;
719  *			remote-endpoint = <&isp 4 0>;
720  *		};
721  *	};
722  * };
723  *
724  * isp: isp {
725  *	ports {
726  *		port@4 {
727  *			port = <4>;
728  *			endpoint {
729  *				endpoint = <0>;
730  *				remote-endpoint = <&cam 0 0>;
731  *			};
732  *		};
733  *	};
734  * };
735  *
736  * Return: 0 on success
737  *	   -ENOENT if no entries (or the property itself) were found
738  *	   -EINVAL if property parsing otherwise failed
739  *	   -ENOMEM if memory allocation failed
740  */
741 static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop(
742 	struct fwnode_handle *fwnode, const char *prop, unsigned int index,
743 	const char * const *props, unsigned int nprops)
744 {
745 	struct fwnode_reference_args fwnode_args;
746 	u64 *args = fwnode_args.args;
747 	struct fwnode_handle *child;
748 	int ret;
749 
750 	/*
751 	 * Obtain remote fwnode as well as the integer arguments.
752 	 *
753 	 * Note that right now both -ENODATA and -ENOENT may signal
754 	 * out-of-bounds access. Return -ENOENT in that case.
755 	 */
756 	ret = fwnode_property_get_reference_args(fwnode, prop, NULL, nprops,
757 						 index, &fwnode_args);
758 	if (ret)
759 		return ERR_PTR(ret == -ENODATA ? -ENOENT : ret);
760 
761 	/*
762 	 * Find a node in the tree under the referred fwnode corresponding to
763 	 * the integer arguments.
764 	 */
765 	fwnode = fwnode_args.fwnode;
766 	while (nprops--) {
767 		u32 val;
768 
769 		/* Loop over all child nodes under fwnode. */
770 		fwnode_for_each_child_node(fwnode, child) {
771 			if (fwnode_property_read_u32(child, *props, &val))
772 				continue;
773 
774 			/* Found property, see if its value matches. */
775 			if (val == *args)
776 				break;
777 		}
778 
779 		fwnode_handle_put(fwnode);
780 
781 		/* No property found; return an error here. */
782 		if (!child) {
783 			fwnode = ERR_PTR(-ENOENT);
784 			break;
785 		}
786 
787 		props++;
788 		args++;
789 		fwnode = child;
790 	}
791 
792 	return fwnode;
793 }
794 
795 /*
796  * v4l2_fwnode_reference_parse_int_props - parse references for async
797  *					   sub-devices
798  * @dev: struct device pointer
799  * @notifier: notifier for @dev
800  * @prop: the name of the property
801  * @props: the array of integer property names
802  * @nprops: the number of integer properties
803  *
804  * Use v4l2_fwnode_reference_get_int_prop to find fwnodes through reference in
805  * property @prop with integer arguments with child nodes matching in properties
806  * @props. Then, set up V4L2 async sub-devices for those fwnodes in the notifier
807  * accordingly.
808  *
809  * While it is technically possible to use this function on DT, it is only
810  * meaningful on ACPI. On Device tree you can refer to any node in the tree but
811  * on ACPI the references are limited to devices.
812  *
813  * Return: 0 on success
814  *	   -ENOENT if no entries (or the property itself) were found
815  *	   -EINVAL if property parsing otherwisefailed
816  *	   -ENOMEM if memory allocation failed
817  */
818 static int v4l2_fwnode_reference_parse_int_props(
819 	struct device *dev, struct v4l2_async_notifier *notifier,
820 	const char *prop, const char * const *props, unsigned int nprops)
821 {
822 	struct fwnode_handle *fwnode;
823 	unsigned int index;
824 	int ret;
825 
826 	index = 0;
827 	do {
828 		fwnode = v4l2_fwnode_reference_get_int_prop(dev_fwnode(dev),
829 							    prop, index,
830 							    props, nprops);
831 		if (IS_ERR(fwnode)) {
832 			/*
833 			 * Note that right now both -ENODATA and -ENOENT may
834 			 * signal out-of-bounds access. Return the error in
835 			 * cases other than that.
836 			 */
837 			if (PTR_ERR(fwnode) != -ENOENT &&
838 			    PTR_ERR(fwnode) != -ENODATA)
839 				return PTR_ERR(fwnode);
840 			break;
841 		}
842 		fwnode_handle_put(fwnode);
843 		index++;
844 	} while (1);
845 
846 	ret = v4l2_async_notifier_realloc(notifier,
847 					  notifier->num_subdevs + index);
848 	if (ret)
849 		return -ENOMEM;
850 
851 	for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(
852 					 dev_fwnode(dev), prop, index, props,
853 					 nprops))); index++) {
854 		struct v4l2_async_subdev *asd;
855 
856 		if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
857 			ret = -EINVAL;
858 			goto error;
859 		}
860 
861 		asd = kzalloc(sizeof(struct v4l2_async_subdev), GFP_KERNEL);
862 		if (!asd) {
863 			ret = -ENOMEM;
864 			goto error;
865 		}
866 
867 		notifier->subdevs[notifier->num_subdevs] = asd;
868 		asd->match.fwnode = fwnode;
869 		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
870 		notifier->num_subdevs++;
871 	}
872 
873 	return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
874 
875 error:
876 	fwnode_handle_put(fwnode);
877 	return ret;
878 }
879 
880 int v4l2_async_notifier_parse_fwnode_sensor_common(
881 	struct device *dev, struct v4l2_async_notifier *notifier)
882 {
883 	static const char * const led_props[] = { "led" };
884 	static const struct {
885 		const char *name;
886 		const char * const *props;
887 		unsigned int nprops;
888 	} props[] = {
889 		{ "flash-leds", led_props, ARRAY_SIZE(led_props) },
890 		{ "lens-focus", NULL, 0 },
891 	};
892 	unsigned int i;
893 
894 	for (i = 0; i < ARRAY_SIZE(props); i++) {
895 		int ret;
896 
897 		if (props[i].props && is_acpi_node(dev_fwnode(dev)))
898 			ret = v4l2_fwnode_reference_parse_int_props(
899 				dev, notifier, props[i].name,
900 				props[i].props, props[i].nprops);
901 		else
902 			ret = v4l2_fwnode_reference_parse(
903 				dev, notifier, props[i].name);
904 		if (ret && ret != -ENOENT) {
905 			dev_warn(dev, "parsing property \"%s\" failed (%d)\n",
906 				 props[i].name, ret);
907 			return ret;
908 		}
909 	}
910 
911 	return 0;
912 }
913 EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_sensor_common);
914 
915 int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
916 {
917 	struct v4l2_async_notifier *notifier;
918 	int ret;
919 
920 	if (WARN_ON(!sd->dev))
921 		return -ENODEV;
922 
923 	notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
924 	if (!notifier)
925 		return -ENOMEM;
926 
927 	ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev,
928 							     notifier);
929 	if (ret < 0)
930 		goto out_cleanup;
931 
932 	ret = v4l2_async_subdev_notifier_register(sd, notifier);
933 	if (ret < 0)
934 		goto out_cleanup;
935 
936 	ret = v4l2_async_register_subdev(sd);
937 	if (ret < 0)
938 		goto out_unregister;
939 
940 	sd->subdev_notifier = notifier;
941 
942 	return 0;
943 
944 out_unregister:
945 	v4l2_async_notifier_unregister(notifier);
946 
947 out_cleanup:
948 	v4l2_async_notifier_cleanup(notifier);
949 	kfree(notifier);
950 
951 	return ret;
952 }
953 EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
954 
955 MODULE_LICENSE("GPL");
956 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
957 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
958 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
959