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