Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * V4L2 fwnode binding parsing library
   4 *
   5 * The origins of the V4L2 fwnode library are in V4L2 OF library that
   6 * formerly was located in v4l2-of.c.
   7 *
   8 * Copyright (c) 2016 Intel Corporation.
   9 * Author: Sakari Ailus <sakari.ailus@linux.intel.com>
  10 *
  11 * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
  12 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
  13 *
  14 * Copyright (C) 2012 Renesas Electronics Corp.
  15 * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
  16 */
  17#include <linux/acpi.h>
  18#include <linux/kernel.h>
  19#include <linux/mm.h>
  20#include <linux/module.h>
  21#include <linux/of.h>
  22#include <linux/property.h>
  23#include <linux/slab.h>
  24#include <linux/string.h>
  25#include <linux/types.h>
  26
  27#include <media/v4l2-async.h>
  28#include <media/v4l2-fwnode.h>
  29#include <media/v4l2-subdev.h>
  30
  31#include "v4l2-subdev-priv.h"
  32
  33static const struct v4l2_fwnode_bus_conv {
  34	enum v4l2_fwnode_bus_type fwnode_bus_type;
  35	enum v4l2_mbus_type mbus_type;
  36	const char *name;
  37} buses[] = {
  38	{
  39		V4L2_FWNODE_BUS_TYPE_GUESS,
  40		V4L2_MBUS_UNKNOWN,
  41		"not specified",
  42	}, {
  43		V4L2_FWNODE_BUS_TYPE_CSI2_CPHY,
  44		V4L2_MBUS_CSI2_CPHY,
  45		"MIPI CSI-2 C-PHY",
  46	}, {
  47		V4L2_FWNODE_BUS_TYPE_CSI1,
  48		V4L2_MBUS_CSI1,
  49		"MIPI CSI-1",
  50	}, {
  51		V4L2_FWNODE_BUS_TYPE_CCP2,
  52		V4L2_MBUS_CCP2,
  53		"compact camera port 2",
  54	}, {
  55		V4L2_FWNODE_BUS_TYPE_CSI2_DPHY,
  56		V4L2_MBUS_CSI2_DPHY,
  57		"MIPI CSI-2 D-PHY",
  58	}, {
  59		V4L2_FWNODE_BUS_TYPE_PARALLEL,
  60		V4L2_MBUS_PARALLEL,
  61		"parallel",
  62	}, {
  63		V4L2_FWNODE_BUS_TYPE_BT656,
  64		V4L2_MBUS_BT656,
  65		"Bt.656",
  66	}, {
  67		V4L2_FWNODE_BUS_TYPE_DPI,
  68		V4L2_MBUS_DPI,
  69		"DPI",
  70	}
  71};
  72
  73static const struct v4l2_fwnode_bus_conv *
  74get_v4l2_fwnode_bus_conv_by_fwnode_bus(enum v4l2_fwnode_bus_type type)
  75{
  76	unsigned int i;
  77
  78	for (i = 0; i < ARRAY_SIZE(buses); i++)
  79		if (buses[i].fwnode_bus_type == type)
  80			return &buses[i];
  81
  82	return NULL;
  83}
  84
  85static enum v4l2_mbus_type
  86v4l2_fwnode_bus_type_to_mbus(enum v4l2_fwnode_bus_type type)
  87{
  88	const struct v4l2_fwnode_bus_conv *conv =
  89		get_v4l2_fwnode_bus_conv_by_fwnode_bus(type);
  90
  91	return conv ? conv->mbus_type : V4L2_MBUS_INVALID;
  92}
  93
  94static const char *
  95v4l2_fwnode_bus_type_to_string(enum v4l2_fwnode_bus_type type)
  96{
  97	const struct v4l2_fwnode_bus_conv *conv =
  98		get_v4l2_fwnode_bus_conv_by_fwnode_bus(type);
  99
 100	return conv ? conv->name : "not found";
 101}
 102
 103static const struct v4l2_fwnode_bus_conv *
 104get_v4l2_fwnode_bus_conv_by_mbus(enum v4l2_mbus_type type)
 105{
 106	unsigned int i;
 107
 108	for (i = 0; i < ARRAY_SIZE(buses); i++)
 109		if (buses[i].mbus_type == type)
 110			return &buses[i];
 111
 112	return NULL;
 113}
 114
 115static const char *
 116v4l2_fwnode_mbus_type_to_string(enum v4l2_mbus_type type)
 117{
 118	const struct v4l2_fwnode_bus_conv *conv =
 119		get_v4l2_fwnode_bus_conv_by_mbus(type);
 120
 121	return conv ? conv->name : "not found";
 122}
 123
 124static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode,
 125					       struct v4l2_fwnode_endpoint *vep,
 126					       enum v4l2_mbus_type bus_type)
 127{
 128	struct v4l2_mbus_config_mipi_csi2 *bus = &vep->bus.mipi_csi2;
 129	bool have_clk_lane = false, have_data_lanes = false,
 130		have_lane_polarities = false;
 131	unsigned int flags = 0, lanes_used = 0;
 132	u32 array[1 + V4L2_MBUS_CSI2_MAX_DATA_LANES];
 133	u32 clock_lane = 0;
 134	unsigned int num_data_lanes = 0;
 135	bool use_default_lane_mapping = false;
 136	unsigned int i;
 137	u32 v;
 138	int rval;
 139
 140	if (bus_type == V4L2_MBUS_CSI2_DPHY ||
 141	    bus_type == V4L2_MBUS_CSI2_CPHY) {
 142		use_default_lane_mapping = true;
 143
 144		num_data_lanes = min_t(u32, bus->num_data_lanes,
 145				       V4L2_MBUS_CSI2_MAX_DATA_LANES);
 146
 147		clock_lane = bus->clock_lane;
 148		if (clock_lane)
 149			use_default_lane_mapping = false;
 150
 151		for (i = 0; i < num_data_lanes; i++) {
 152			array[i] = bus->data_lanes[i];
 153			if (array[i])
 154				use_default_lane_mapping = false;
 155		}
 156
 157		if (use_default_lane_mapping)
 158			pr_debug("no lane mapping given, using defaults\n");
 159	}
 160
 161	rval = fwnode_property_count_u32(fwnode, "data-lanes");
 162	if (rval > 0) {
 163		num_data_lanes =
 164			min_t(int, V4L2_MBUS_CSI2_MAX_DATA_LANES, rval);
 165
 166		fwnode_property_read_u32_array(fwnode, "data-lanes", array,
 167					       num_data_lanes);
 168
 169		have_data_lanes = true;
 170		if (use_default_lane_mapping) {
 171			pr_debug("data-lanes property exists; disabling default mapping\n");
 172			use_default_lane_mapping = false;
 173		}
 174	}
 175
 176	for (i = 0; i < num_data_lanes; i++) {
 177		if (lanes_used & BIT(array[i])) {
 178			if (have_data_lanes || !use_default_lane_mapping)
 179				pr_warn("duplicated lane %u in data-lanes, using defaults\n",
 180					array[i]);
 181			use_default_lane_mapping = true;
 182		}
 183		lanes_used |= BIT(array[i]);
 184
 185		if (have_data_lanes)
 186			pr_debug("lane %u position %u\n", i, array[i]);
 187	}
 188
 189	rval = fwnode_property_count_u32(fwnode, "lane-polarities");
 190	if (rval > 0) {
 191		if (rval != 1 + num_data_lanes /* clock+data */) {
 192			pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n",
 193				1 + num_data_lanes, rval);
 194			return -EINVAL;
 195		}
 196
 197		have_lane_polarities = true;
 198	}
 199
 200	if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) {
 201		clock_lane = v;
 202		pr_debug("clock lane position %u\n", v);
 203		have_clk_lane = true;
 204	}
 205
 206	if (have_clk_lane && lanes_used & BIT(clock_lane) &&
 207	    !use_default_lane_mapping) {
 208		pr_warn("duplicated lane %u in clock-lanes, using defaults\n",
 209			v);
 210		use_default_lane_mapping = true;
 211	}
 212
 213	if (fwnode_property_present(fwnode, "clock-noncontinuous")) {
 214		flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
 215		pr_debug("non-continuous clock\n");
 216	}
 217
 218	if (bus_type == V4L2_MBUS_CSI2_DPHY ||
 219	    bus_type == V4L2_MBUS_CSI2_CPHY ||
 220	    lanes_used || have_clk_lane || flags) {
 221		/* Only D-PHY has a clock lane. */
 222		unsigned int dfl_data_lane_index =
 223			bus_type == V4L2_MBUS_CSI2_DPHY;
 224
 225		bus->flags = flags;
 226		if (bus_type == V4L2_MBUS_UNKNOWN)
 227			vep->bus_type = V4L2_MBUS_CSI2_DPHY;
 228		bus->num_data_lanes = num_data_lanes;
 229
 230		if (use_default_lane_mapping) {
 231			bus->clock_lane = 0;
 232			for (i = 0; i < num_data_lanes; i++)
 233				bus->data_lanes[i] = dfl_data_lane_index + i;
 234		} else {
 235			bus->clock_lane = clock_lane;
 236			for (i = 0; i < num_data_lanes; i++)
 237				bus->data_lanes[i] = array[i];
 238		}
 239
 240		if (have_lane_polarities) {
 241			fwnode_property_read_u32_array(fwnode,
 242						       "lane-polarities", array,
 243						       1 + num_data_lanes);
 244
 245			for (i = 0; i < 1 + num_data_lanes; i++) {
 246				bus->lane_polarities[i] = array[i];
 247				pr_debug("lane %u polarity %sinverted",
 248					 i, array[i] ? "" : "not ");
 249			}
 250		} else {
 251			pr_debug("no lane polarities defined, assuming not inverted\n");
 252		}
 253	}
 254
 255	return 0;
 256}
 257
 258#define PARALLEL_MBUS_FLAGS (V4L2_MBUS_HSYNC_ACTIVE_HIGH |	\
 259			     V4L2_MBUS_HSYNC_ACTIVE_LOW |	\
 260			     V4L2_MBUS_VSYNC_ACTIVE_HIGH |	\
 261			     V4L2_MBUS_VSYNC_ACTIVE_LOW |	\
 262			     V4L2_MBUS_FIELD_EVEN_HIGH |	\
 263			     V4L2_MBUS_FIELD_EVEN_LOW)
 264
 265static void
 266v4l2_fwnode_endpoint_parse_parallel_bus(struct fwnode_handle *fwnode,
 267					struct v4l2_fwnode_endpoint *vep,
 268					enum v4l2_mbus_type bus_type)
 269{
 270	struct v4l2_mbus_config_parallel *bus = &vep->bus.parallel;
 271	unsigned int flags = 0;
 272	u32 v;
 273
 274	if (bus_type == V4L2_MBUS_PARALLEL || bus_type == V4L2_MBUS_BT656)
 275		flags = bus->flags;
 276
 277	if (!fwnode_property_read_u32(fwnode, "hsync-active", &v)) {
 278		flags &= ~(V4L2_MBUS_HSYNC_ACTIVE_HIGH |
 279			   V4L2_MBUS_HSYNC_ACTIVE_LOW);
 280		flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH :
 281			V4L2_MBUS_HSYNC_ACTIVE_LOW;
 282		pr_debug("hsync-active %s\n", v ? "high" : "low");
 283	}
 284
 285	if (!fwnode_property_read_u32(fwnode, "vsync-active", &v)) {
 286		flags &= ~(V4L2_MBUS_VSYNC_ACTIVE_HIGH |
 287			   V4L2_MBUS_VSYNC_ACTIVE_LOW);
 288		flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH :
 289			V4L2_MBUS_VSYNC_ACTIVE_LOW;
 290		pr_debug("vsync-active %s\n", v ? "high" : "low");
 291	}
 292
 293	if (!fwnode_property_read_u32(fwnode, "field-even-active", &v)) {
 294		flags &= ~(V4L2_MBUS_FIELD_EVEN_HIGH |
 295			   V4L2_MBUS_FIELD_EVEN_LOW);
 296		flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH :
 297			V4L2_MBUS_FIELD_EVEN_LOW;
 298		pr_debug("field-even-active %s\n", v ? "high" : "low");
 299	}
 300
 301	if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v)) {
 302		flags &= ~(V4L2_MBUS_PCLK_SAMPLE_RISING |
 303			   V4L2_MBUS_PCLK_SAMPLE_FALLING |
 304			   V4L2_MBUS_PCLK_SAMPLE_DUALEDGE);
 305		switch (v) {
 306		case 0:
 307			flags |= V4L2_MBUS_PCLK_SAMPLE_FALLING;
 308			pr_debug("pclk-sample low\n");
 309			break;
 310		case 1:
 311			flags |= V4L2_MBUS_PCLK_SAMPLE_RISING;
 312			pr_debug("pclk-sample high\n");
 313			break;
 314		case 2:
 315			flags |= V4L2_MBUS_PCLK_SAMPLE_DUALEDGE;
 316			pr_debug("pclk-sample dual edge\n");
 317			break;
 318		default:
 319			pr_warn("invalid argument for pclk-sample");
 320			break;
 321		}
 322	}
 323
 324	if (!fwnode_property_read_u32(fwnode, "data-active", &v)) {
 325		flags &= ~(V4L2_MBUS_DATA_ACTIVE_HIGH |
 326			   V4L2_MBUS_DATA_ACTIVE_LOW);
 327		flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH :
 328			V4L2_MBUS_DATA_ACTIVE_LOW;
 329		pr_debug("data-active %s\n", v ? "high" : "low");
 330	}
 331
 332	if (fwnode_property_present(fwnode, "slave-mode")) {
 333		pr_debug("slave mode\n");
 334		flags &= ~V4L2_MBUS_MASTER;
 335		flags |= V4L2_MBUS_SLAVE;
 336	} else {
 337		flags &= ~V4L2_MBUS_SLAVE;
 338		flags |= V4L2_MBUS_MASTER;
 339	}
 340
 341	if (!fwnode_property_read_u32(fwnode, "bus-width", &v)) {
 342		bus->bus_width = v;
 343		pr_debug("bus-width %u\n", v);
 344	}
 345
 346	if (!fwnode_property_read_u32(fwnode, "data-shift", &v)) {
 347		bus->data_shift = v;
 348		pr_debug("data-shift %u\n", v);
 349	}
 350
 351	if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v)) {
 352		flags &= ~(V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH |
 353			   V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW);
 354		flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH :
 355			V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW;
 356		pr_debug("sync-on-green-active %s\n", v ? "high" : "low");
 357	}
 358
 359	if (!fwnode_property_read_u32(fwnode, "data-enable-active", &v)) {
 360		flags &= ~(V4L2_MBUS_DATA_ENABLE_HIGH |
 361			   V4L2_MBUS_DATA_ENABLE_LOW);
 362		flags |= v ? V4L2_MBUS_DATA_ENABLE_HIGH :
 363			V4L2_MBUS_DATA_ENABLE_LOW;
 364		pr_debug("data-enable-active %s\n", v ? "high" : "low");
 365	}
 366
 367	switch (bus_type) {
 368	default:
 369		bus->flags = flags;
 370		if (flags & PARALLEL_MBUS_FLAGS)
 371			vep->bus_type = V4L2_MBUS_PARALLEL;
 372		else
 373			vep->bus_type = V4L2_MBUS_BT656;
 374		break;
 375	case V4L2_MBUS_PARALLEL:
 376		vep->bus_type = V4L2_MBUS_PARALLEL;
 377		bus->flags = flags;
 378		break;
 379	case V4L2_MBUS_BT656:
 380		vep->bus_type = V4L2_MBUS_BT656;
 381		bus->flags = flags & ~PARALLEL_MBUS_FLAGS;
 382		break;
 383	}
 384}
 385
 386static void
 387v4l2_fwnode_endpoint_parse_csi1_bus(struct fwnode_handle *fwnode,
 388				    struct v4l2_fwnode_endpoint *vep,
 389				    enum v4l2_mbus_type bus_type)
 390{
 391	struct v4l2_mbus_config_mipi_csi1 *bus = &vep->bus.mipi_csi1;
 392	u32 v;
 393
 394	if (!fwnode_property_read_u32(fwnode, "clock-inv", &v)) {
 395		bus->clock_inv = v;
 396		pr_debug("clock-inv %u\n", v);
 397	}
 398
 399	if (!fwnode_property_read_u32(fwnode, "strobe", &v)) {
 400		bus->strobe = v;
 401		pr_debug("strobe %u\n", v);
 402	}
 403
 404	if (!fwnode_property_read_u32(fwnode, "data-lanes", &v)) {
 405		bus->data_lane = v;
 406		pr_debug("data-lanes %u\n", v);
 407	}
 408
 409	if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) {
 410		bus->clock_lane = v;
 411		pr_debug("clock-lanes %u\n", v);
 412	}
 413
 414	if (bus_type == V4L2_MBUS_CCP2)
 415		vep->bus_type = V4L2_MBUS_CCP2;
 416	else
 417		vep->bus_type = V4L2_MBUS_CSI1;
 418}
 419
 420static int __v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
 421					struct v4l2_fwnode_endpoint *vep)
 422{
 423	u32 bus_type = V4L2_FWNODE_BUS_TYPE_GUESS;
 424	enum v4l2_mbus_type mbus_type;
 425	int rval;
 426
 427	pr_debug("===== begin parsing endpoint %pfw\n", fwnode);
 428
 429	fwnode_property_read_u32(fwnode, "bus-type", &bus_type);
 430	pr_debug("fwnode video bus type %s (%u), mbus type %s (%u)\n",
 431		 v4l2_fwnode_bus_type_to_string(bus_type), bus_type,
 432		 v4l2_fwnode_mbus_type_to_string(vep->bus_type),
 433		 vep->bus_type);
 434	mbus_type = v4l2_fwnode_bus_type_to_mbus(bus_type);
 435	if (mbus_type == V4L2_MBUS_INVALID) {
 436		pr_debug("unsupported bus type %u\n", bus_type);
 437		return -EINVAL;
 438	}
 439
 440	if (vep->bus_type != V4L2_MBUS_UNKNOWN) {
 441		if (mbus_type != V4L2_MBUS_UNKNOWN &&
 442		    vep->bus_type != mbus_type) {
 443			pr_debug("expecting bus type %s\n",
 444				 v4l2_fwnode_mbus_type_to_string(vep->bus_type));
 445			return -ENXIO;
 446		}
 447	} else {
 448		vep->bus_type = mbus_type;
 449	}
 450
 451	switch (vep->bus_type) {
 452	case V4L2_MBUS_UNKNOWN:
 453		rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep,
 454							   V4L2_MBUS_UNKNOWN);
 455		if (rval)
 456			return rval;
 457
 458		if (vep->bus_type == V4L2_MBUS_UNKNOWN)
 459			v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep,
 460								V4L2_MBUS_UNKNOWN);
 461
 462		pr_debug("assuming media bus type %s (%u)\n",
 463			 v4l2_fwnode_mbus_type_to_string(vep->bus_type),
 464			 vep->bus_type);
 465
 466		break;
 467	case V4L2_MBUS_CCP2:
 468	case V4L2_MBUS_CSI1:
 469		v4l2_fwnode_endpoint_parse_csi1_bus(fwnode, vep, vep->bus_type);
 470
 471		break;
 472	case V4L2_MBUS_CSI2_DPHY:
 473	case V4L2_MBUS_CSI2_CPHY:
 474		rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep,
 475							   vep->bus_type);
 476		if (rval)
 477			return rval;
 478
 479		break;
 480	case V4L2_MBUS_PARALLEL:
 481	case V4L2_MBUS_BT656:
 482		v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep,
 483							vep->bus_type);
 484
 485		break;
 486	default:
 487		pr_warn("unsupported bus type %u\n", mbus_type);
 488		return -EINVAL;
 489	}
 490
 491	fwnode_graph_parse_endpoint(fwnode, &vep->base);
 492
 493	return 0;
 494}
 495
 496int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
 497			       struct v4l2_fwnode_endpoint *vep)
 498{
 499	int ret;
 500
 501	ret = __v4l2_fwnode_endpoint_parse(fwnode, vep);
 502
 503	pr_debug("===== end parsing endpoint %pfw\n", fwnode);
 504
 505	return ret;
 506}
 507EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_parse);
 508
 509void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep)
 510{
 511	if (IS_ERR_OR_NULL(vep))
 512		return;
 513
 514	kfree(vep->link_frequencies);
 515	vep->link_frequencies = NULL;
 516}
 517EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_free);
 518
 519int v4l2_fwnode_endpoint_alloc_parse(struct fwnode_handle *fwnode,
 520				     struct v4l2_fwnode_endpoint *vep)
 521{
 522	int rval;
 523
 524	rval = __v4l2_fwnode_endpoint_parse(fwnode, vep);
 525	if (rval < 0)
 526		return rval;
 527
 528	rval = fwnode_property_count_u64(fwnode, "link-frequencies");
 529	if (rval > 0) {
 530		unsigned int i;
 531
 532		vep->link_frequencies =
 533			kmalloc_array(rval, sizeof(*vep->link_frequencies),
 534				      GFP_KERNEL);
 535		if (!vep->link_frequencies)
 536			return -ENOMEM;
 537
 538		vep->nr_of_link_frequencies = rval;
 539
 540		rval = fwnode_property_read_u64_array(fwnode,
 541						      "link-frequencies",
 542						      vep->link_frequencies,
 543						      vep->nr_of_link_frequencies);
 544		if (rval < 0) {
 545			v4l2_fwnode_endpoint_free(vep);
 546			return rval;
 547		}
 548
 549		for (i = 0; i < vep->nr_of_link_frequencies; i++)
 550			pr_debug("link-frequencies %u value %llu\n", i,
 551				 vep->link_frequencies[i]);
 552	}
 553
 554	pr_debug("===== end parsing endpoint %pfw\n", fwnode);
 555
 556	return 0;
 557}
 558EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse);
 559
 560int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode,
 561			   struct v4l2_fwnode_link *link)
 562{
 563	struct fwnode_endpoint fwep;
 564
 565	memset(link, 0, sizeof(*link));
 566
 567	fwnode_graph_parse_endpoint(fwnode, &fwep);
 568	link->local_id = fwep.id;
 569	link->local_port = fwep.port;
 570	link->local_node = fwnode_graph_get_port_parent(fwnode);
 571	if (!link->local_node)
 572		return -ENOLINK;
 573
 574	fwnode = fwnode_graph_get_remote_endpoint(fwnode);
 575	if (!fwnode)
 576		goto err_put_local_node;
 577
 578	fwnode_graph_parse_endpoint(fwnode, &fwep);
 579	link->remote_id = fwep.id;
 580	link->remote_port = fwep.port;
 581	link->remote_node = fwnode_graph_get_port_parent(fwnode);
 582	if (!link->remote_node)
 583		goto err_put_remote_endpoint;
 584
 585	return 0;
 586
 587err_put_remote_endpoint:
 588	fwnode_handle_put(fwnode);
 589
 590err_put_local_node:
 591	fwnode_handle_put(link->local_node);
 592
 593	return -ENOLINK;
 594}
 595EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_link);
 596
 597void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link)
 598{
 599	fwnode_handle_put(link->local_node);
 600	fwnode_handle_put(link->remote_node);
 601}
 602EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
 603
 604static const struct v4l2_fwnode_connector_conv {
 605	enum v4l2_connector_type type;
 606	const char *compatible;
 607} connectors[] = {
 608	{
 609		.type = V4L2_CONN_COMPOSITE,
 610		.compatible = "composite-video-connector",
 611	}, {
 612		.type = V4L2_CONN_SVIDEO,
 613		.compatible = "svideo-connector",
 614	},
 615};
 616
 617static enum v4l2_connector_type
 618v4l2_fwnode_string_to_connector_type(const char *con_str)
 619{
 620	unsigned int i;
 621
 622	for (i = 0; i < ARRAY_SIZE(connectors); i++)
 623		if (!strcmp(con_str, connectors[i].compatible))
 624			return connectors[i].type;
 625
 626	return V4L2_CONN_UNKNOWN;
 627}
 628
 629static void
 630v4l2_fwnode_connector_parse_analog(struct fwnode_handle *fwnode,
 631				   struct v4l2_fwnode_connector *vc)
 632{
 633	u32 stds;
 634	int ret;
 635
 636	ret = fwnode_property_read_u32(fwnode, "sdtv-standards", &stds);
 637
 638	/* The property is optional. */
 639	vc->connector.analog.sdtv_stds = ret ? V4L2_STD_ALL : stds;
 640}
 641
 642void v4l2_fwnode_connector_free(struct v4l2_fwnode_connector *connector)
 643{
 644	struct v4l2_connector_link *link, *tmp;
 645
 646	if (IS_ERR_OR_NULL(connector) || connector->type == V4L2_CONN_UNKNOWN)
 647		return;
 648
 649	list_for_each_entry_safe(link, tmp, &connector->links, head) {
 650		v4l2_fwnode_put_link(&link->fwnode_link);
 651		list_del(&link->head);
 652		kfree(link);
 653	}
 654
 655	kfree(connector->label);
 656	connector->label = NULL;
 657	connector->type = V4L2_CONN_UNKNOWN;
 658}
 659EXPORT_SYMBOL_GPL(v4l2_fwnode_connector_free);
 660
 661static enum v4l2_connector_type
 662v4l2_fwnode_get_connector_type(struct fwnode_handle *fwnode)
 663{
 664	const char *type_name;
 665	int err;
 666
 667	if (!fwnode)
 668		return V4L2_CONN_UNKNOWN;
 669
 670	/* The connector-type is stored within the compatible string. */
 671	err = fwnode_property_read_string(fwnode, "compatible", &type_name);
 672	if (err)
 673		return V4L2_CONN_UNKNOWN;
 674
 675	return v4l2_fwnode_string_to_connector_type(type_name);
 676}
 677
 678int v4l2_fwnode_connector_parse(struct fwnode_handle *fwnode,
 679				struct v4l2_fwnode_connector *connector)
 680{
 681	struct fwnode_handle *connector_node;
 682	enum v4l2_connector_type connector_type;
 683	const char *label;
 684	int err;
 685
 686	if (!fwnode)
 687		return -EINVAL;
 688
 689	memset(connector, 0, sizeof(*connector));
 690
 691	INIT_LIST_HEAD(&connector->links);
 692
 693	connector_node = fwnode_graph_get_port_parent(fwnode);
 694	connector_type = v4l2_fwnode_get_connector_type(connector_node);
 695	if (connector_type == V4L2_CONN_UNKNOWN) {
 696		fwnode_handle_put(connector_node);
 697		connector_node = fwnode_graph_get_remote_port_parent(fwnode);
 698		connector_type = v4l2_fwnode_get_connector_type(connector_node);
 699	}
 700
 701	if (connector_type == V4L2_CONN_UNKNOWN) {
 702		pr_err("Unknown connector type\n");
 703		err = -ENOTCONN;
 704		goto out;
 705	}
 706
 707	connector->type = connector_type;
 708	connector->name = fwnode_get_name(connector_node);
 709	err = fwnode_property_read_string(connector_node, "label", &label);
 710	connector->label = err ? NULL : kstrdup_const(label, GFP_KERNEL);
 711
 712	/* Parse the connector specific properties. */
 713	switch (connector->type) {
 714	case V4L2_CONN_COMPOSITE:
 715	case V4L2_CONN_SVIDEO:
 716		v4l2_fwnode_connector_parse_analog(connector_node, connector);
 717		break;
 718	/* Avoid compiler warnings */
 719	case V4L2_CONN_UNKNOWN:
 720		break;
 721	}
 722
 723out:
 724	fwnode_handle_put(connector_node);
 725
 726	return err;
 727}
 728EXPORT_SYMBOL_GPL(v4l2_fwnode_connector_parse);
 729
 730int v4l2_fwnode_connector_add_link(struct fwnode_handle *fwnode,
 731				   struct v4l2_fwnode_connector *connector)
 732{
 733	struct fwnode_handle *connector_ep;
 734	struct v4l2_connector_link *link;
 735	int err;
 736
 737	if (!fwnode || !connector || connector->type == V4L2_CONN_UNKNOWN)
 738		return -EINVAL;
 739
 740	connector_ep = fwnode_graph_get_remote_endpoint(fwnode);
 741	if (!connector_ep)
 742		return -ENOTCONN;
 743
 744	link = kzalloc(sizeof(*link), GFP_KERNEL);
 745	if (!link) {
 746		err = -ENOMEM;
 747		goto err;
 748	}
 749
 750	err = v4l2_fwnode_parse_link(connector_ep, &link->fwnode_link);
 751	if (err)
 752		goto err;
 753
 754	fwnode_handle_put(connector_ep);
 755
 756	list_add(&link->head, &connector->links);
 757	connector->nr_of_links++;
 758
 759	return 0;
 760
 761err:
 762	kfree(link);
 763	fwnode_handle_put(connector_ep);
 764
 765	return err;
 766}
 767EXPORT_SYMBOL_GPL(v4l2_fwnode_connector_add_link);
 768
 769int v4l2_fwnode_device_parse(struct device *dev,
 770			     struct v4l2_fwnode_device_properties *props)
 771{
 772	struct fwnode_handle *fwnode = dev_fwnode(dev);
 773	u32 val;
 774	int ret;
 775
 776	memset(props, 0, sizeof(*props));
 777
 778	props->orientation = V4L2_FWNODE_PROPERTY_UNSET;
 779	ret = fwnode_property_read_u32(fwnode, "orientation", &val);
 780	if (!ret) {
 781		switch (val) {
 782		case V4L2_FWNODE_ORIENTATION_FRONT:
 783		case V4L2_FWNODE_ORIENTATION_BACK:
 784		case V4L2_FWNODE_ORIENTATION_EXTERNAL:
 785			break;
 786		default:
 787			dev_warn(dev, "Unsupported device orientation: %u\n", val);
 788			return -EINVAL;
 789		}
 790
 791		props->orientation = val;
 792		dev_dbg(dev, "device orientation: %u\n", val);
 793	}
 794
 795	props->rotation = V4L2_FWNODE_PROPERTY_UNSET;
 796	ret = fwnode_property_read_u32(fwnode, "rotation", &val);
 797	if (!ret) {
 798		if (val >= 360) {
 799			dev_warn(dev, "Unsupported device rotation: %u\n", val);
 800			return -EINVAL;
 801		}
 802
 803		props->rotation = val;
 804		dev_dbg(dev, "device rotation: %u\n", val);
 805	}
 806
 807	return 0;
 808}
 809EXPORT_SYMBOL_GPL(v4l2_fwnode_device_parse);
 810
 811/*
 812 * v4l2_fwnode_reference_parse - parse references for async sub-devices
 813 * @dev: the device node the properties of which are parsed for references
 814 * @notifier: the async notifier where the async subdevs will be added
 815 * @prop: the name of the property
 816 *
 817 * Return: 0 on success
 818 *	   -ENOENT if no entries were found
 819 *	   -ENOMEM if memory allocation failed
 820 *	   -EINVAL if property parsing failed
 821 */
 822static int v4l2_fwnode_reference_parse(struct device *dev,
 823				       struct v4l2_async_notifier *notifier,
 824				       const char *prop)
 825{
 826	struct fwnode_reference_args args;
 827	unsigned int index;
 828	int ret;
 829
 830	for (index = 0;
 831	     !(ret = fwnode_property_get_reference_args(dev_fwnode(dev), prop,
 832							NULL, 0, index, &args));
 833	     index++) {
 834		struct v4l2_async_connection *asd;
 835
 836		asd = v4l2_async_nf_add_fwnode(notifier, args.fwnode,
 837					       struct v4l2_async_connection);
 838		fwnode_handle_put(args.fwnode);
 839		if (IS_ERR(asd)) {
 840			/* not an error if asd already exists */
 841			if (PTR_ERR(asd) == -EEXIST)
 842				continue;
 843
 844			return PTR_ERR(asd);
 845		}
 846	}
 847
 848	/* -ENOENT here means successful parsing */
 849	if (ret != -ENOENT)
 850		return ret;
 851
 852	/* Return -ENOENT if no references were found */
 853	return index ? 0 : -ENOENT;
 854}
 855
 856/*
 857 * v4l2_fwnode_reference_get_int_prop - parse a reference with integer
 858 *					arguments
 859 * @fwnode: fwnode to read @prop from
 860 * @notifier: notifier for @dev
 861 * @prop: the name of the property
 862 * @index: the index of the reference to get
 863 * @props: the array of integer property names
 864 * @nprops: the number of integer property names in @nprops
 865 *
 866 * First find an fwnode referred to by the reference at @index in @prop.
 867 *
 868 * Then under that fwnode, @nprops times, for each property in @props,
 869 * iteratively follow child nodes starting from fwnode such that they have the
 870 * property in @props array at the index of the child node distance from the
 871 * root node and the value of that property matching with the integer argument
 872 * of the reference, at the same index.
 873 *
 874 * The child fwnode reached at the end of the iteration is then returned to the
 875 * caller.
 876 *
 877 * The core reason for this is that you cannot refer to just any node in ACPI.
 878 * So to refer to an endpoint (easy in DT) you need to refer to a device, then
 879 * provide a list of (property name, property value) tuples where each tuple
 880 * uniquely identifies a child node. The first tuple identifies a child directly
 881 * underneath the device fwnode, the next tuple identifies a child node
 882 * underneath the fwnode identified by the previous tuple, etc. until you
 883 * reached the fwnode you need.
 884 *
 885 * THIS EXAMPLE EXISTS MERELY TO DOCUMENT THIS FUNCTION. DO NOT USE IT AS A
 886 * REFERENCE IN HOW ACPI TABLES SHOULD BE WRITTEN!! See documentation under
 887 * Documentation/firmware-guide/acpi/dsd/ instead and especially graph.txt,
 888 * data-node-references.txt and leds.txt .
 889 *
 890 *	Scope (\_SB.PCI0.I2C2)
 891 *	{
 892 *		Device (CAM0)
 893 *		{
 894 *			Name (_DSD, Package () {
 895 *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
 896 *				Package () {
 897 *					Package () {
 898 *						"compatible",
 899 *						Package () { "nokia,smia" }
 900 *					},
 901 *				},
 902 *				ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
 903 *				Package () {
 904 *					Package () { "port0", "PRT0" },
 905 *				}
 906 *			})
 907 *			Name (PRT0, Package() {
 908 *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
 909 *				Package () {
 910 *					Package () { "port", 0 },
 911 *				},
 912 *				ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
 913 *				Package () {
 914 *					Package () { "endpoint0", "EP00" },
 915 *				}
 916 *			})
 917 *			Name (EP00, Package() {
 918 *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
 919 *				Package () {
 920 *					Package () { "endpoint", 0 },
 921 *					Package () {
 922 *						"remote-endpoint",
 923 *						Package() {
 924 *							\_SB.PCI0.ISP, 4, 0
 925 *						}
 926 *					},
 927 *				}
 928 *			})
 929 *		}
 930 *	}
 931 *
 932 *	Scope (\_SB.PCI0)
 933 *	{
 934 *		Device (ISP)
 935 *		{
 936 *			Name (_DSD, Package () {
 937 *				ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
 938 *				Package () {
 939 *					Package () { "port4", "PRT4" },
 940 *				}
 941 *			})
 942 *
 943 *			Name (PRT4, Package() {
 944 *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
 945 *				Package () {
 946 *					Package () { "port", 4 },
 947 *				},
 948 *				ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
 949 *				Package () {
 950 *					Package () { "endpoint0", "EP40" },
 951 *				}
 952 *			})
 953 *
 954 *			Name (EP40, Package() {
 955 *				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
 956 *				Package () {
 957 *					Package () { "endpoint", 0 },
 958 *					Package () {
 959 *						"remote-endpoint",
 960 *						Package () {
 961 *							\_SB.PCI0.I2C2.CAM0,
 962 *							0, 0
 963 *						}
 964 *					},
 965 *				}
 966 *			})
 967 *		}
 968 *	}
 969 *
 970 * From the EP40 node under ISP device, you could parse the graph remote
 971 * endpoint using v4l2_fwnode_reference_get_int_prop with these arguments:
 972 *
 973 *  @fwnode: fwnode referring to EP40 under ISP.
 974 *  @prop: "remote-endpoint"
 975 *  @index: 0
 976 *  @props: "port", "endpoint"
 977 *  @nprops: 2
 978 *
 979 * And you'd get back fwnode referring to EP00 under CAM0.
 980 *
 981 * The same works the other way around: if you use EP00 under CAM0 as the
 982 * fwnode, you'll get fwnode referring to EP40 under ISP.
 983 *
 984 * The same example in DT syntax would look like this:
 985 *
 986 * cam: cam0 {
 987 *	compatible = "nokia,smia";
 988 *
 989 *	port {
 990 *		port = <0>;
 991 *		endpoint {
 992 *			endpoint = <0>;
 993 *			remote-endpoint = <&isp 4 0>;
 994 *		};
 995 *	};
 996 * };
 997 *
 998 * isp: isp {
 999 *	ports {
1000 *		port@4 {
1001 *			port = <4>;
1002 *			endpoint {
1003 *				endpoint = <0>;
1004 *				remote-endpoint = <&cam 0 0>;
1005 *			};
1006 *		};
1007 *	};
1008 * };
1009 *
1010 * Return: 0 on success
1011 *	   -ENOENT if no entries (or the property itself) were found
1012 *	   -EINVAL if property parsing otherwise failed
1013 *	   -ENOMEM if memory allocation failed
1014 */
1015static struct fwnode_handle *
1016v4l2_fwnode_reference_get_int_prop(struct fwnode_handle *fwnode,
1017				   const char *prop,
1018				   unsigned int index,
1019				   const char * const *props,
1020				   unsigned int nprops)
1021{
1022	struct fwnode_reference_args fwnode_args;
1023	u64 *args = fwnode_args.args;
1024	struct fwnode_handle *child;
1025	int ret;
1026
1027	/*
1028	 * Obtain remote fwnode as well as the integer arguments.
1029	 *
1030	 * Note that right now both -ENODATA and -ENOENT may signal
1031	 * out-of-bounds access. Return -ENOENT in that case.
1032	 */
1033	ret = fwnode_property_get_reference_args(fwnode, prop, NULL, nprops,
1034						 index, &fwnode_args);
1035	if (ret)
1036		return ERR_PTR(ret == -ENODATA ? -ENOENT : ret);
1037
1038	/*
1039	 * Find a node in the tree under the referred fwnode corresponding to
1040	 * the integer arguments.
1041	 */
1042	fwnode = fwnode_args.fwnode;
1043	while (nprops--) {
1044		u32 val;
1045
1046		/* Loop over all child nodes under fwnode. */
1047		fwnode_for_each_child_node(fwnode, child) {
1048			if (fwnode_property_read_u32(child, *props, &val))
1049				continue;
1050
1051			/* Found property, see if its value matches. */
1052			if (val == *args)
1053				break;
1054		}
1055
1056		fwnode_handle_put(fwnode);
1057
1058		/* No property found; return an error here. */
1059		if (!child) {
1060			fwnode = ERR_PTR(-ENOENT);
1061			break;
1062		}
1063
1064		props++;
1065		args++;
1066		fwnode = child;
1067	}
1068
1069	return fwnode;
1070}
1071
1072struct v4l2_fwnode_int_props {
1073	const char *name;
1074	const char * const *props;
1075	unsigned int nprops;
1076};
1077
1078/*
1079 * v4l2_fwnode_reference_parse_int_props - parse references for async
1080 *					   sub-devices
1081 * @dev: struct device pointer
1082 * @notifier: notifier for @dev
1083 * @prop: the name of the property
1084 * @props: the array of integer property names
1085 * @nprops: the number of integer properties
1086 *
1087 * Use v4l2_fwnode_reference_get_int_prop to find fwnodes through reference in
1088 * property @prop with integer arguments with child nodes matching in properties
1089 * @props. Then, set up V4L2 async sub-devices for those fwnodes in the notifier
1090 * accordingly.
1091 *
1092 * While it is technically possible to use this function on DT, it is only
1093 * meaningful on ACPI. On Device tree you can refer to any node in the tree but
1094 * on ACPI the references are limited to devices.
1095 *
1096 * Return: 0 on success
1097 *	   -ENOENT if no entries (or the property itself) were found
1098 *	   -EINVAL if property parsing otherwisefailed
1099 *	   -ENOMEM if memory allocation failed
1100 */
1101static int
1102v4l2_fwnode_reference_parse_int_props(struct device *dev,
1103				      struct v4l2_async_notifier *notifier,
1104				      const struct v4l2_fwnode_int_props *p)
1105{
1106	struct fwnode_handle *fwnode;
1107	unsigned int index;
1108	int ret;
1109	const char *prop = p->name;
1110	const char * const *props = p->props;
1111	unsigned int nprops = p->nprops;
1112
1113	index = 0;
1114	do {
1115		fwnode = v4l2_fwnode_reference_get_int_prop(dev_fwnode(dev),
1116							    prop, index,
1117							    props, nprops);
1118		if (IS_ERR(fwnode)) {
1119			/*
1120			 * Note that right now both -ENODATA and -ENOENT may
1121			 * signal out-of-bounds access. Return the error in
1122			 * cases other than that.
1123			 */
1124			if (PTR_ERR(fwnode) != -ENOENT &&
1125			    PTR_ERR(fwnode) != -ENODATA)
1126				return PTR_ERR(fwnode);
1127			break;
1128		}
1129		fwnode_handle_put(fwnode);
1130		index++;
1131	} while (1);
1132
1133	for (index = 0;
1134	     !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(dev_fwnode(dev),
1135								  prop, index,
1136								  props,
1137								  nprops)));
1138	     index++) {
1139		struct v4l2_async_connection *asd;
1140
1141		asd = v4l2_async_nf_add_fwnode(notifier, fwnode,
1142					       struct v4l2_async_connection);
1143		fwnode_handle_put(fwnode);
1144		if (IS_ERR(asd)) {
1145			ret = PTR_ERR(asd);
1146			/* not an error if asd already exists */
1147			if (ret == -EEXIST)
1148				continue;
1149
1150			return PTR_ERR(asd);
1151		}
1152	}
1153
1154	return !fwnode || PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
1155}
1156
1157/**
1158 * v4l2_async_nf_parse_fwnode_sensor - parse common references on
1159 *					     sensors for async sub-devices
1160 * @dev: the device node the properties of which are parsed for references
1161 * @notifier: the async notifier where the async subdevs will be added
1162 *
1163 * Parse common sensor properties for remote devices related to the
1164 * sensor and set up async sub-devices for them.
1165 *
1166 * Any notifier populated using this function must be released with a call to
1167 * v4l2_async_nf_release() after it has been unregistered and the async
1168 * sub-devices are no longer in use, even in the case the function returned an
1169 * error.
1170 *
1171 * Return: 0 on success
1172 *	   -ENOMEM if memory allocation failed
1173 *	   -EINVAL if property parsing failed
1174 */
1175static int
1176v4l2_async_nf_parse_fwnode_sensor(struct device *dev,
1177				  struct v4l2_async_notifier *notifier)
1178{
1179	static const char * const led_props[] = { "led" };
1180	static const struct v4l2_fwnode_int_props props[] = {
1181		{ "flash-leds", led_props, ARRAY_SIZE(led_props) },
1182		{ "mipi-img-flash-leds", },
1183		{ "lens-focus", },
1184		{ "mipi-img-lens-focus", },
1185	};
1186	unsigned int i;
1187
1188	for (i = 0; i < ARRAY_SIZE(props); i++) {
1189		int ret;
1190
1191		if (props[i].props && is_acpi_node(dev_fwnode(dev)))
1192			ret = v4l2_fwnode_reference_parse_int_props(dev,
1193								    notifier,
1194								    &props[i]);
1195		else
1196			ret = v4l2_fwnode_reference_parse(dev, notifier,
1197							  props[i].name);
1198		if (ret && ret != -ENOENT) {
1199			dev_warn(dev, "parsing property \"%s\" failed (%d)\n",
1200				 props[i].name, ret);
1201			return ret;
1202		}
1203	}
1204
1205	return 0;
1206}
1207
1208int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
1209{
1210	struct v4l2_async_notifier *notifier;
1211	int ret;
1212
1213	if (WARN_ON(!sd->dev))
1214		return -ENODEV;
1215
1216	notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
1217	if (!notifier)
1218		return -ENOMEM;
1219
1220	v4l2_async_subdev_nf_init(notifier, sd);
1221
1222	ret = v4l2_subdev_get_privacy_led(sd);
1223	if (ret < 0)
1224		goto out_cleanup;
1225
1226	ret = v4l2_async_nf_parse_fwnode_sensor(sd->dev, notifier);
1227	if (ret < 0)
1228		goto out_cleanup;
1229
1230	ret = v4l2_async_nf_register(notifier);
1231	if (ret < 0)
1232		goto out_cleanup;
1233
1234	ret = v4l2_async_register_subdev(sd);
1235	if (ret < 0)
1236		goto out_unregister;
1237
1238	sd->subdev_notifier = notifier;
1239
1240	return 0;
1241
1242out_unregister:
1243	v4l2_async_nf_unregister(notifier);
1244
1245out_cleanup:
1246	v4l2_subdev_put_privacy_led(sd);
1247	v4l2_async_nf_cleanup(notifier);
1248	kfree(notifier);
1249
1250	return ret;
1251}
1252EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor);
1253
1254MODULE_DESCRIPTION("V4L2 fwnode binding parsing library");
1255MODULE_LICENSE("GPL");
1256MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
1257MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1258MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");