GNU Linux-libre 4.19.304-gnu1
[releases.git] / drivers / media / v4l2-core / v4l2-fwnode.c
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         struct fwnode_endpoint fwep;
286
287         memset(link, 0, sizeof(*link));
288
289         fwnode_graph_parse_endpoint(fwnode, &fwep);
290         link->local_port = fwep.port;
291         link->local_node = fwnode_graph_get_port_parent(fwnode);
292         if (!link->local_node)
293                 return -ENOLINK;
294
295         fwnode = fwnode_graph_get_remote_endpoint(fwnode);
296         if (!fwnode)
297                 goto err_put_local_node;
298
299         fwnode_graph_parse_endpoint(fwnode, &fwep);
300         link->remote_port = fwep.port;
301         link->remote_node = fwnode_graph_get_port_parent(fwnode);
302         if (!link->remote_node)
303                 goto err_put_remote_endpoint;
304
305         return 0;
306
307 err_put_remote_endpoint:
308         fwnode_handle_put(fwnode);
309
310 err_put_local_node:
311         fwnode_handle_put(link->local_node);
312
313         return -ENOLINK;
314 }
315 EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_link);
316
317 void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link)
318 {
319         fwnode_handle_put(link->local_node);
320         fwnode_handle_put(link->remote_node);
321 }
322 EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
323
324 static int v4l2_async_notifier_realloc(struct v4l2_async_notifier *notifier,
325                                        unsigned int max_subdevs)
326 {
327         struct v4l2_async_subdev **subdevs;
328
329         if (max_subdevs <= notifier->max_subdevs)
330                 return 0;
331
332         subdevs = kvmalloc_array(
333                 max_subdevs, sizeof(*notifier->subdevs),
334                 GFP_KERNEL | __GFP_ZERO);
335         if (!subdevs)
336                 return -ENOMEM;
337
338         if (notifier->subdevs) {
339                 memcpy(subdevs, notifier->subdevs,
340                        sizeof(*subdevs) * notifier->num_subdevs);
341
342                 kvfree(notifier->subdevs);
343         }
344
345         notifier->subdevs = subdevs;
346         notifier->max_subdevs = max_subdevs;
347
348         return 0;
349 }
350
351 static int v4l2_async_notifier_fwnode_parse_endpoint(
352         struct device *dev, struct v4l2_async_notifier *notifier,
353         struct fwnode_handle *endpoint, unsigned int asd_struct_size,
354         int (*parse_endpoint)(struct device *dev,
355                             struct v4l2_fwnode_endpoint *vep,
356                             struct v4l2_async_subdev *asd))
357 {
358         struct v4l2_async_subdev *asd;
359         struct v4l2_fwnode_endpoint *vep;
360         int ret = 0;
361
362         asd = kzalloc(asd_struct_size, GFP_KERNEL);
363         if (!asd)
364                 return -ENOMEM;
365
366         asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
367         asd->match.fwnode =
368                 fwnode_graph_get_remote_port_parent(endpoint);
369         if (!asd->match.fwnode) {
370                 dev_warn(dev, "bad remote port parent\n");
371                 ret = -EINVAL;
372                 goto out_err;
373         }
374
375         vep = v4l2_fwnode_endpoint_alloc_parse(endpoint);
376         if (IS_ERR(vep)) {
377                 ret = PTR_ERR(vep);
378                 dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n",
379                          ret);
380                 goto out_err;
381         }
382
383         ret = parse_endpoint ? parse_endpoint(dev, vep, asd) : 0;
384         if (ret == -ENOTCONN)
385                 dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep->base.port,
386                         vep->base.id);
387         else if (ret < 0)
388                 dev_warn(dev,
389                          "driver could not parse port@%u/endpoint@%u (%d)\n",
390                          vep->base.port, vep->base.id, ret);
391         v4l2_fwnode_endpoint_free(vep);
392         if (ret < 0)
393                 goto out_err;
394
395         notifier->subdevs[notifier->num_subdevs] = asd;
396         notifier->num_subdevs++;
397
398         return 0;
399
400 out_err:
401         fwnode_handle_put(asd->match.fwnode);
402         kfree(asd);
403
404         return ret == -ENOTCONN ? 0 : ret;
405 }
406
407 static int __v4l2_async_notifier_parse_fwnode_endpoints(
408         struct device *dev, struct v4l2_async_notifier *notifier,
409         size_t asd_struct_size, unsigned int port, bool has_port,
410         int (*parse_endpoint)(struct device *dev,
411                             struct v4l2_fwnode_endpoint *vep,
412                             struct v4l2_async_subdev *asd))
413 {
414         struct fwnode_handle *fwnode;
415         unsigned int max_subdevs = notifier->max_subdevs;
416         int ret;
417
418         if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
419                 return -EINVAL;
420
421         for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
422                                      dev_fwnode(dev), fwnode)); ) {
423                 struct fwnode_handle *dev_fwnode;
424                 bool is_available;
425
426                 dev_fwnode = fwnode_graph_get_port_parent(fwnode);
427                 is_available = fwnode_device_is_available(dev_fwnode);
428                 fwnode_handle_put(dev_fwnode);
429                 if (!is_available)
430                         continue;
431
432                 if (has_port) {
433                         struct fwnode_endpoint ep;
434
435                         ret = fwnode_graph_parse_endpoint(fwnode, &ep);
436                         if (ret) {
437                                 fwnode_handle_put(fwnode);
438                                 return ret;
439                         }
440
441                         if (ep.port != port)
442                                 continue;
443                 }
444                 max_subdevs++;
445         }
446
447         /* No subdevs to add? Return here. */
448         if (max_subdevs == notifier->max_subdevs)
449                 return 0;
450
451         ret = v4l2_async_notifier_realloc(notifier, max_subdevs);
452         if (ret)
453                 return ret;
454
455         for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
456                                      dev_fwnode(dev), fwnode)); ) {
457                 struct fwnode_handle *dev_fwnode;
458                 bool is_available;
459
460                 dev_fwnode = fwnode_graph_get_port_parent(fwnode);
461                 is_available = fwnode_device_is_available(dev_fwnode);
462                 fwnode_handle_put(dev_fwnode);
463                 if (!is_available)
464                         continue;
465
466                 if (has_port) {
467                         struct fwnode_endpoint ep;
468
469                         ret = fwnode_graph_parse_endpoint(fwnode, &ep);
470                         if (ret)
471                                 break;
472
473                         if (ep.port != port)
474                                 continue;
475                 }
476
477                 if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
478                         ret = -EINVAL;
479                         break;
480                 }
481
482                 ret = v4l2_async_notifier_fwnode_parse_endpoint(
483                         dev, notifier, fwnode, asd_struct_size, parse_endpoint);
484                 if (ret < 0)
485                         break;
486         }
487
488         fwnode_handle_put(fwnode);
489
490         return ret;
491 }
492
493 int v4l2_async_notifier_parse_fwnode_endpoints(
494         struct device *dev, struct v4l2_async_notifier *notifier,
495         size_t asd_struct_size,
496         int (*parse_endpoint)(struct device *dev,
497                             struct v4l2_fwnode_endpoint *vep,
498                             struct v4l2_async_subdev *asd))
499 {
500         return __v4l2_async_notifier_parse_fwnode_endpoints(
501                 dev, notifier, asd_struct_size, 0, false, parse_endpoint);
502 }
503 EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints);
504
505 int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
506         struct device *dev, struct v4l2_async_notifier *notifier,
507         size_t asd_struct_size, unsigned int port,
508         int (*parse_endpoint)(struct device *dev,
509                             struct v4l2_fwnode_endpoint *vep,
510                             struct v4l2_async_subdev *asd))
511 {
512         return __v4l2_async_notifier_parse_fwnode_endpoints(
513                 dev, notifier, asd_struct_size, port, true, parse_endpoint);
514 }
515 EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port);
516
517 /*
518  * v4l2_fwnode_reference_parse - parse references for async sub-devices
519  * @dev: the device node the properties of which are parsed for references
520  * @notifier: the async notifier where the async subdevs will be added
521  * @prop: the name of the property
522  *
523  * Return: 0 on success
524  *         -ENOENT if no entries were found
525  *         -ENOMEM if memory allocation failed
526  *         -EINVAL if property parsing failed
527  */
528 static int v4l2_fwnode_reference_parse(
529         struct device *dev, struct v4l2_async_notifier *notifier,
530         const char *prop)
531 {
532         struct fwnode_reference_args args;
533         unsigned int index;
534         int ret;
535
536         for (index = 0;
537              !(ret = fwnode_property_get_reference_args(
538                        dev_fwnode(dev), prop, NULL, 0, index, &args));
539              index++)
540                 fwnode_handle_put(args.fwnode);
541
542         if (!index)
543                 return -ENOENT;
544
545         /*
546          * Note that right now both -ENODATA and -ENOENT may signal
547          * out-of-bounds access. Return the error in cases other than that.
548          */
549         if (ret != -ENOENT && ret != -ENODATA)
550                 return ret;
551
552         ret = v4l2_async_notifier_realloc(notifier,
553                                           notifier->num_subdevs + index);
554         if (ret)
555                 return ret;
556
557         for (index = 0; !fwnode_property_get_reference_args(
558                      dev_fwnode(dev), prop, NULL, 0, index, &args);
559              index++) {
560                 struct v4l2_async_subdev *asd;
561
562                 if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
563                         ret = -EINVAL;
564                         goto error;
565                 }
566
567                 asd = kzalloc(sizeof(*asd), GFP_KERNEL);
568                 if (!asd) {
569                         ret = -ENOMEM;
570                         goto error;
571                 }
572
573                 notifier->subdevs[notifier->num_subdevs] = asd;
574                 asd->match.fwnode = args.fwnode;
575                 asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
576                 notifier->num_subdevs++;
577         }
578
579         return 0;
580
581 error:
582         fwnode_handle_put(args.fwnode);
583         return ret;
584 }
585
586 /*
587  * v4l2_fwnode_reference_get_int_prop - parse a reference with integer
588  *                                      arguments
589  * @fwnode: fwnode to read @prop from
590  * @notifier: notifier for @dev
591  * @prop: the name of the property
592  * @index: the index of the reference to get
593  * @props: the array of integer property names
594  * @nprops: the number of integer property names in @nprops
595  *
596  * First find an fwnode referred to by the reference at @index in @prop.
597  *
598  * Then under that fwnode, @nprops times, for each property in @props,
599  * iteratively follow child nodes starting from fwnode such that they have the
600  * property in @props array at the index of the child node distance from the
601  * root node and the value of that property matching with the integer argument
602  * of the reference, at the same index.
603  *
604  * The child fwnode reched at the end of the iteration is then returned to the
605  * caller.
606  *
607  * The core reason for this is that you cannot refer to just any node in ACPI.
608  * So to refer to an endpoint (easy in DT) you need to refer to a device, then
609  * provide a list of (property name, property value) tuples where each tuple
610  * uniquely identifies a child node. The first tuple identifies a child directly
611  * underneath the device fwnode, the next tuple identifies a child node
612  * underneath the fwnode identified by the previous tuple, etc. until you
613  * reached the fwnode you need.
614  *
615  * An example with a graph, as defined in Documentation/acpi/dsd/graph.txt:
616  *
617  *      Scope (\_SB.PCI0.I2C2)
618  *      {
619  *              Device (CAM0)
620  *              {
621  *                      Name (_DSD, Package () {
622  *                              ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
623  *                              Package () {
624  *                                      Package () {
625  *                                              "compatible",
626  *                                              Package () { "nokia,smia" }
627  *                                      },
628  *                              },
629  *                              ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
630  *                              Package () {
631  *                                      Package () { "port0", "PRT0" },
632  *                              }
633  *                      })
634  *                      Name (PRT0, Package() {
635  *                              ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
636  *                              Package () {
637  *                                      Package () { "port", 0 },
638  *                              },
639  *                              ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
640  *                              Package () {
641  *                                      Package () { "endpoint0", "EP00" },
642  *                              }
643  *                      })
644  *                      Name (EP00, Package() {
645  *                              ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
646  *                              Package () {
647  *                                      Package () { "endpoint", 0 },
648  *                                      Package () {
649  *                                              "remote-endpoint",
650  *                                              Package() {
651  *                                                      \_SB.PCI0.ISP, 4, 0
652  *                                              }
653  *                                      },
654  *                              }
655  *                      })
656  *              }
657  *      }
658  *
659  *      Scope (\_SB.PCI0)
660  *      {
661  *              Device (ISP)
662  *              {
663  *                      Name (_DSD, Package () {
664  *                              ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
665  *                              Package () {
666  *                                      Package () { "port4", "PRT4" },
667  *                              }
668  *                      })
669  *
670  *                      Name (PRT4, Package() {
671  *                              ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
672  *                              Package () {
673  *                                      Package () { "port", 4 },
674  *                              },
675  *                              ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
676  *                              Package () {
677  *                                      Package () { "endpoint0", "EP40" },
678  *                              }
679  *                      })
680  *
681  *                      Name (EP40, Package() {
682  *                              ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
683  *                              Package () {
684  *                                      Package () { "endpoint", 0 },
685  *                                      Package () {
686  *                                              "remote-endpoint",
687  *                                              Package () {
688  *                                                      \_SB.PCI0.I2C2.CAM0,
689  *                                                      0, 0
690  *                                              }
691  *                                      },
692  *                              }
693  *                      })
694  *              }
695  *      }
696  *
697  * From the EP40 node under ISP device, you could parse the graph remote
698  * endpoint using v4l2_fwnode_reference_get_int_prop with these arguments:
699  *
700  *  @fwnode: fwnode referring to EP40 under ISP.
701  *  @prop: "remote-endpoint"
702  *  @index: 0
703  *  @props: "port", "endpoint"
704  *  @nprops: 2
705  *
706  * And you'd get back fwnode referring to EP00 under CAM0.
707  *
708  * The same works the other way around: if you use EP00 under CAM0 as the
709  * fwnode, you'll get fwnode referring to EP40 under ISP.
710  *
711  * The same example in DT syntax would look like this:
712  *
713  * cam: cam0 {
714  *      compatible = "nokia,smia";
715  *
716  *      port {
717  *              port = <0>;
718  *              endpoint {
719  *                      endpoint = <0>;
720  *                      remote-endpoint = <&isp 4 0>;
721  *              };
722  *      };
723  * };
724  *
725  * isp: isp {
726  *      ports {
727  *              port@4 {
728  *                      port = <4>;
729  *                      endpoint {
730  *                              endpoint = <0>;
731  *                              remote-endpoint = <&cam 0 0>;
732  *                      };
733  *              };
734  *      };
735  * };
736  *
737  * Return: 0 on success
738  *         -ENOENT if no entries (or the property itself) were found
739  *         -EINVAL if property parsing otherwise failed
740  *         -ENOMEM if memory allocation failed
741  */
742 static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop(
743         struct fwnode_handle *fwnode, const char *prop, unsigned int index,
744         const char * const *props, unsigned int nprops)
745 {
746         struct fwnode_reference_args fwnode_args;
747         u64 *args = fwnode_args.args;
748         struct fwnode_handle *child;
749         int ret;
750
751         /*
752          * Obtain remote fwnode as well as the integer arguments.
753          *
754          * Note that right now both -ENODATA and -ENOENT may signal
755          * out-of-bounds access. Return -ENOENT in that case.
756          */
757         ret = fwnode_property_get_reference_args(fwnode, prop, NULL, nprops,
758                                                  index, &fwnode_args);
759         if (ret)
760                 return ERR_PTR(ret == -ENODATA ? -ENOENT : ret);
761
762         /*
763          * Find a node in the tree under the referred fwnode corresponding to
764          * the integer arguments.
765          */
766         fwnode = fwnode_args.fwnode;
767         while (nprops--) {
768                 u32 val;
769
770                 /* Loop over all child nodes under fwnode. */
771                 fwnode_for_each_child_node(fwnode, child) {
772                         if (fwnode_property_read_u32(child, *props, &val))
773                                 continue;
774
775                         /* Found property, see if its value matches. */
776                         if (val == *args)
777                                 break;
778                 }
779
780                 fwnode_handle_put(fwnode);
781
782                 /* No property found; return an error here. */
783                 if (!child) {
784                         fwnode = ERR_PTR(-ENOENT);
785                         break;
786                 }
787
788                 props++;
789                 args++;
790                 fwnode = child;
791         }
792
793         return fwnode;
794 }
795
796 /*
797  * v4l2_fwnode_reference_parse_int_props - parse references for async
798  *                                         sub-devices
799  * @dev: struct device pointer
800  * @notifier: notifier for @dev
801  * @prop: the name of the property
802  * @props: the array of integer property names
803  * @nprops: the number of integer properties
804  *
805  * Use v4l2_fwnode_reference_get_int_prop to find fwnodes through reference in
806  * property @prop with integer arguments with child nodes matching in properties
807  * @props. Then, set up V4L2 async sub-devices for those fwnodes in the notifier
808  * accordingly.
809  *
810  * While it is technically possible to use this function on DT, it is only
811  * meaningful on ACPI. On Device tree you can refer to any node in the tree but
812  * on ACPI the references are limited to devices.
813  *
814  * Return: 0 on success
815  *         -ENOENT if no entries (or the property itself) were found
816  *         -EINVAL if property parsing otherwisefailed
817  *         -ENOMEM if memory allocation failed
818  */
819 static int v4l2_fwnode_reference_parse_int_props(
820         struct device *dev, struct v4l2_async_notifier *notifier,
821         const char *prop, const char * const *props, unsigned int nprops)
822 {
823         struct fwnode_handle *fwnode;
824         unsigned int index;
825         int ret;
826
827         index = 0;
828         do {
829                 fwnode = v4l2_fwnode_reference_get_int_prop(dev_fwnode(dev),
830                                                             prop, index,
831                                                             props, nprops);
832                 if (IS_ERR(fwnode)) {
833                         /*
834                          * Note that right now both -ENODATA and -ENOENT may
835                          * signal out-of-bounds access. Return the error in
836                          * cases other than that.
837                          */
838                         if (PTR_ERR(fwnode) != -ENOENT &&
839                             PTR_ERR(fwnode) != -ENODATA)
840                                 return PTR_ERR(fwnode);
841                         break;
842                 }
843                 fwnode_handle_put(fwnode);
844                 index++;
845         } while (1);
846
847         ret = v4l2_async_notifier_realloc(notifier,
848                                           notifier->num_subdevs + index);
849         if (ret)
850                 return -ENOMEM;
851
852         for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(
853                                          dev_fwnode(dev), prop, index, props,
854                                          nprops))); index++) {
855                 struct v4l2_async_subdev *asd;
856
857                 if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
858                         ret = -EINVAL;
859                         goto error;
860                 }
861
862                 asd = kzalloc(sizeof(struct v4l2_async_subdev), GFP_KERNEL);
863                 if (!asd) {
864                         ret = -ENOMEM;
865                         goto error;
866                 }
867
868                 notifier->subdevs[notifier->num_subdevs] = asd;
869                 asd->match.fwnode = fwnode;
870                 asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
871                 notifier->num_subdevs++;
872         }
873
874         return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
875
876 error:
877         fwnode_handle_put(fwnode);
878         return ret;
879 }
880
881 int v4l2_async_notifier_parse_fwnode_sensor_common(
882         struct device *dev, struct v4l2_async_notifier *notifier)
883 {
884         static const char * const led_props[] = { "led" };
885         static const struct {
886                 const char *name;
887                 const char * const *props;
888                 unsigned int nprops;
889         } props[] = {
890                 { "flash-leds", led_props, ARRAY_SIZE(led_props) },
891                 { "lens-focus", NULL, 0 },
892         };
893         unsigned int i;
894
895         for (i = 0; i < ARRAY_SIZE(props); i++) {
896                 int ret;
897
898                 if (props[i].props && is_acpi_node(dev_fwnode(dev)))
899                         ret = v4l2_fwnode_reference_parse_int_props(
900                                 dev, notifier, props[i].name,
901                                 props[i].props, props[i].nprops);
902                 else
903                         ret = v4l2_fwnode_reference_parse(
904                                 dev, notifier, props[i].name);
905                 if (ret && ret != -ENOENT) {
906                         dev_warn(dev, "parsing property \"%s\" failed (%d)\n",
907                                  props[i].name, ret);
908                         return ret;
909                 }
910         }
911
912         return 0;
913 }
914 EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_sensor_common);
915
916 int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
917 {
918         struct v4l2_async_notifier *notifier;
919         int ret;
920
921         if (WARN_ON(!sd->dev))
922                 return -ENODEV;
923
924         notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
925         if (!notifier)
926                 return -ENOMEM;
927
928         ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev,
929                                                              notifier);
930         if (ret < 0)
931                 goto out_cleanup;
932
933         ret = v4l2_async_subdev_notifier_register(sd, notifier);
934         if (ret < 0)
935                 goto out_cleanup;
936
937         ret = v4l2_async_register_subdev(sd);
938         if (ret < 0)
939                 goto out_unregister;
940
941         sd->subdev_notifier = notifier;
942
943         return 0;
944
945 out_unregister:
946         v4l2_async_notifier_unregister(notifier);
947
948 out_cleanup:
949         v4l2_async_notifier_cleanup(notifier);
950         kfree(notifier);
951
952         return ret;
953 }
954 EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
955
956 MODULE_LICENSE("GPL");
957 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
958 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
959 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");