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