Hi Laurent, On Fri, Apr 07, 2017 at 12:44:27PM +0300, Laurent Pinchart wrote: > Hi Sakari, > > Thank you for the patch. > > On Thursday 06 Apr 2017 16:12:04 Sakari Ailus wrote: > > The fwnode_handle is a more generic way than OF device_node to describe > > firmware nodes. Instead of the OF API, use more generic fwnode API to > > obtain the same information. > > I would mention that this is a copy of v4l2-of.c with the OF API replaced with > the fwnode API. I'll add that to the description. > > > As the V4L2 fwnode support will be required by a small minority of e.g. > > ACPI based systems (the same might actually go for OF), make this a module > > instead of embedding it in the videodev module. > > > > Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> > > --- > > drivers/media/v4l2-core/Kconfig | 3 + > > drivers/media/v4l2-core/Makefile | 1 + > > drivers/media/v4l2-core/v4l2-fwnode.c | 353 +++++++++++++++++++++++++++++++ > > include/media/v4l2-fwnode.h | 104 ++++++++++ > > 4 files changed, 461 insertions(+) > > create mode 100644 drivers/media/v4l2-core/v4l2-fwnode.c > > create mode 100644 include/media/v4l2-fwnode.h > > > > diff --git a/drivers/media/v4l2-core/Kconfig > > b/drivers/media/v4l2-core/Kconfig index 6b1b78f..a35c336 100644 > > --- a/drivers/media/v4l2-core/Kconfig > > +++ b/drivers/media/v4l2-core/Kconfig > > @@ -55,6 +55,9 @@ config V4L2_FLASH_LED_CLASS > > > > When in doubt, say N. > > > > +config V4L2_FWNODE > > + tristate > > + > > # Used by drivers that need Videobuf modules > > config VIDEOBUF_GEN > > tristate > > diff --git a/drivers/media/v4l2-core/Makefile > > b/drivers/media/v4l2-core/Makefile index 795a535..cf77a63 100644 > > --- a/drivers/media/v4l2-core/Makefile > > +++ b/drivers/media/v4l2-core/Makefile > > @@ -13,6 +13,7 @@ endif > > ifeq ($(CONFIG_OF),y) > > videodev-objs += v4l2-of.o > > endif > > +obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o > > ifeq ($(CONFIG_TRACEPOINTS),y) > > videodev-objs += vb2-trace.o v4l2-trace.o > > endif > > diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c > > b/drivers/media/v4l2-core/v4l2-fwnode.c new file mode 100644 > > index 0000000..4f69b11 > > --- /dev/null > > +++ b/drivers/media/v4l2-core/v4l2-fwnode.c > > @@ -0,0 +1,353 @@ > > +/* > > + * V4L2 fwnode binding parsing library > > + * > > + * Copyright (c) 2016 Intel Corporation. > > + * Author: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> > > + * > > + * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. > > + * Author: Sylwester Nawrocki <s.nawrocki@xxxxxxxxxxx> > > + * > > + * Copyright (C) 2012 Renesas Electronics Corp. > > + * Author: Guennadi Liakhovetski <g.liakhovetski@xxxxxx> > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of version 2 of the GNU General Public License as > > + * published by the Free Software Foundation. > > + */ > > +#include <linux/acpi.h> > > +#include <linux/kernel.h> > > +#include <linux/module.h> > > +#include <linux/of.h> > > +#include <linux/property.h> > > +#include <linux/slab.h> > > +#include <linux/string.h> > > +#include <linux/types.h> > > + > > +#include <media/v4l2-fwnode.h> > > + > > +static int v4l2_fwnode_endpoint_parse_csi_bus(struct fwnode_handle *fwn, > > + struct v4l2_fwnode_endpoint > *vfwn) > > +{ > > + struct v4l2_fwnode_bus_mipi_csi2 *bus = &vfwn->bus.mipi_csi2; > > + bool have_clk_lane = false; > > + unsigned int flags = 0, lanes_used = 0; > > + unsigned int i; > > + u32 v; > > + int rval; > > I would have used "ret" instead of "rval" ;-) I know. But 1) there's no established convention in the file and 2) "rval" has the benefit is easier to look up; one doesn't find a plethora of "return something". Therefore it is better than "ret" for the purpose. > > > + rval = fwnode_property_read_u32_array(fwn, "data-lanes", NULL, 0); > > + if (rval > 0) { > > + u32 array[ARRAY_SIZE(bus->data_lanes)]; > > + > > + bus->num_data_lanes = > > + min_t(int, ARRAY_SIZE(bus->data_lanes), rval); > > + > > + fwnode_property_read_u32_array( > > + fwn, "data-lanes", array, bus->num_data_lanes); > > Is there anything wrong with the usual way to wrap code ? > > fwnode_property_read_u32_array(fwn, "data-lanes", array, > bus->num_data_lanes); I'll change the occurrences of that whenever feasible. > > > + > > + for (i = 0; i < bus->num_data_lanes; i++) { > > + if (lanes_used & BIT(array[i])) > > + pr_warn("duplicated lane %u in data-lanes\n", > > + array[i]); > > + lanes_used |= BIT(array[i]); > > + > > + bus->data_lanes[i] = array[i]; > > + } > > + } > > + > > + rval = fwnode_property_read_u32_array(fwn, "lane-polarities", NULL, > 0); > > + if (rval > 0) { > > + u32 array[ARRAY_SIZE(bus->lane_polarities)]; > > + > > + if (rval < 1 + bus->num_data_lanes /* clock + data */) { > > + pr_warn("too few lane-polarities entries (need %u, got > %u)\n", > > + 1 + bus->num_data_lanes, rval); > > + return -EINVAL; > > + } > > + > > + fwnode_property_read_u32_array( > > + fwn, "lane-polarities", array, 1 + bus- > >num_data_lanes); > > Ditto with > > fwnode_property_read_u32_array(fwn, "lane-polarities", array, > 1 + bus->num_data_lanes); > > > + for (i = 0; i < 1 + bus->num_data_lanes; i++) > > + bus->lane_polarities[i] = array[i]; > > + } > > + > > + if (!fwnode_property_read_u32(fwn, "clock-lanes", &v)) { > > + if (lanes_used & BIT(v)) > > + pr_warn("duplicated lane %u in clock-lanes\n", v); > > + lanes_used |= BIT(v); > > + > > + bus->clock_lane = v; > > + have_clk_lane = true; > > + } > > + > > + if (fwnode_property_present(fwn, "clock-noncontinuous")) > > + flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK; > > + else if (have_clk_lane || bus->num_data_lanes > 0) > > + flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; > > + > > + bus->flags = flags; > > + vfwn->bus_type = V4L2_MBUS_CSI2; > > + > > + return 0; > > +} > > + > > +static void v4l2_fwnode_endpoint_parse_parallel_bus( > > + struct fwnode_handle *fwn, struct v4l2_fwnode_endpoint *vfwn) > > +{ > > + struct v4l2_fwnode_bus_parallel *bus = &vfwn->bus.parallel; > > + unsigned int flags = 0; > > + u32 v; > > + > > + if (!fwnode_property_read_u32(fwn, "hsync-active", &v)) > > + flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH : > > + V4L2_MBUS_HSYNC_ACTIVE_LOW; > > + > > + if (!fwnode_property_read_u32(fwn, "vsync-active", &v)) > > + flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH : > > + V4L2_MBUS_VSYNC_ACTIVE_LOW; > > + > > + if (!fwnode_property_read_u32(fwn, "field-even-active", &v)) > > + flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH : > > + V4L2_MBUS_FIELD_EVEN_LOW; > > + if (flags) > > + vfwn->bus_type = V4L2_MBUS_PARALLEL; > > + else > > + vfwn->bus_type = V4L2_MBUS_BT656; > > + > > + if (!fwnode_property_read_u32(fwn, "pclk-sample", &v)) > > + flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING : > > + V4L2_MBUS_PCLK_SAMPLE_FALLING; > > + > > + if (!fwnode_property_read_u32(fwn, "data-active", &v)) > > + flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH : > > + V4L2_MBUS_DATA_ACTIVE_LOW; > > + > > + if (fwnode_property_present(fwn, "slave-mode")) > > + flags |= V4L2_MBUS_SLAVE; > > + else > > + flags |= V4L2_MBUS_MASTER; > > + > > + if (!fwnode_property_read_u32(fwn, "bus-width", &v)) > > + bus->bus_width = v; > > + > > + if (!fwnode_property_read_u32(fwn, "data-shift", &v)) > > + bus->data_shift = v; > > + > > + if (!fwnode_property_read_u32(fwn, "sync-on-green-active", &v)) > > + flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH : > > + V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW; > > + > > + bus->flags = flags; > > + > > +} > > + > > +/** > > + * v4l2_fwnode_endpoint_parse() - parse all fwnode node properties > > + * @fwn: pointer to fwnode_handle > > I would say "the endpoint's fwnode handle", or "pointer to the endpoint's > fwnode handle". Otherwise which fwnode handle should be passed won't be clear. I prefer the latter. > > > + * @vfwn: pointer to the V4L2 fwnode data structure > > + * > > + * All properties are optional. If none are found, we don't set any flags. > > + * This means the port has a static configuration and no properties have > > + * to be specified explicitly. > > + * If any properties that identify the bus as parallel are found and > > + * slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if we > > recognise > > + * the bus as serial CSI-2 and clock-noncontinuous isn't set, we set the > > + * V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. > > + * The caller should hold a reference to @node. > > s/@node/@fwn/ > > By the way, have you tried to compile the documentation ? I have, but I may have made changes since that. I'll test that again before submitting the next version. > > > + * > > + * NOTE: This function does not parse properties the size of which is > > + * variable without a low fixed limit. Please use > > + * v4l2_fwnode_endpoint_alloc_parse() in new drivers instead. > > + * > > + * Return: 0 on success or a negative error code on failure. > > + */ > > +int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwn, > > + struct v4l2_fwnode_endpoint *vfwn) > > Is there a specific reason not to keep the original parameter name "endpoint" > ? vfwn seems to stand for v4l2_fwnode, not v4l2_fwnode_endpoint. Same comment > for all other locations in this patch. I'm ok with keeping endpoint. > > > +{ > > + int rval; > > + > > + fwnode_graph_parse_endpoint(fwn, &vfwn->base); > > + > > + /* Zero fields from bus_type to until the end */ > > + memset(&vfwn->bus_type, 0, sizeof(*vfwn) - > > + offsetof(typeof(*vfwn), bus_type)); > > + > > + rval = v4l2_fwnode_endpoint_parse_csi_bus(fwn, vfwn); > > + if (rval) > > + return rval; > > + /* > > + * Parse the parallel video bus properties only if none > > + * of the MIPI CSI-2 specific properties were found. > > + */ > > + if (vfwn->bus.mipi_csi2.flags == 0) > > + v4l2_fwnode_endpoint_parse_parallel_bus(fwn, vfwn); > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(v4l2_fwnode_endpoint_parse); > > According to Mauro in http://www.mail-archive.com/linux-media@xxxxxxxxxxxxxxx/msg110809.html you should use EXPORT_SYMBOL_GPL. EXPORT_SYMBOL() was used by v4l2-of.c; I'll switch here. > > > + > > +/* > > + * v4l2_fwnode_endpoint_free() - free the V4L2 fwnode acquired by > > + * v4l2_fwnode_endpoint_alloc_parse() > > + * @fwn - the V4L2 fwnode the resources of which are to be released > > Mayeb "the V4L2 fwnode whose resources are to be released" ? > > > + * > > + * It is safe to call this function with NULL argument or on an > > s/on an/on a/ Yes. > > > + * V4L2 fwnode the parsing of which failed. > > "whose parsing failed" ? Any particular reason? Do you like "whose"? :-) > > > + */ > > +void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vfwn) > > +{ > > + if (IS_ERR_OR_NULL(vfwn)) > > + return; > > + > > + kfree(vfwn->link_frequencies); > > + kfree(vfwn); > > +} > > +EXPORT_SYMBOL(v4l2_fwnode_endpoint_free); > > + > > +/** > > + * v4l2_fwnode_endpoint_alloc_parse() - parse all fwnode node properties > > + * @node: pointer to fwnode_handle > > s/@node/@fwn/ > > Here too, I would say "the endpoint's fwnode handle", or "pointer to the > endpoint's fwnode handle". I'll use the latter. > > > + * > > + * All properties are optional. If none are found, we don't set any flags. > > + * This means the port has a static configuration and no properties have > > + * to be specified explicitly. > > + * If any properties that identify the bus as parallel are found and > > + * slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if we > > recognise > > + * the bus as serial CSI-2 and clock-noncontinuous isn't set, we set the > > + * V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. > > + * The caller should hold a reference to @node. > > s/@node/@fwn/ Will fix. > > > + * > > + * v4l2_fwnode_endpoint_alloc_parse() has two important differences to > > + * v4l2_fwnode_endpoint_parse(): > > + * > > + * 1. It also parses variable size data and > > Nitpicking, a valid sentence doesn't end with "and$". You could write > > 1. It also parses variable size data. > 2. The memory it has allocated to store the variable size data must > be freed using v4l2_fwnode_endpoint_free() when no longer needed. I prefer this one, will change. > > or > > 1. it also parses variable size data; and > 2. the memory it has allocated to store the variable size data must > be freed using v4l2_fwnode_endpoint_free() when no longer needed. > > > + * > > + * 2. The memory it has allocated to store the variable size data must > > + * be freed using v4l2_fwnode_endpoint_free() when no longer needed. > > + * > > + * Return: Pointer to v4l2_fwnode_endpoint if successful, on error a > > + * negative error code. > > The function returns an error pointer on error. Yes, I'll improve the documentation. > > > + */ > > +struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse( > > + struct fwnode_handle *fwn) > > +{ > > + struct v4l2_fwnode_endpoint *vfwn; > > + int rval; > > ret ? :-) > > > + > > + vfwn = kzalloc(sizeof(*vfwn), GFP_KERNEL); > > + if (!vfwn) > > + return ERR_PTR(-ENOMEM); > > + > > + rval = v4l2_fwnode_endpoint_parse(fwn, vfwn); > > + if (rval < 0) > > + goto out_err; > > + > > + rval = fwnode_property_read_u64_array(fwn, "link-frequencies", > > + NULL, 0); > > + > > No need for a blank line. Indeed. > > > + if (rval < 0) > > + goto out_err; > > + > > + vfwn->link_frequencies = > > + kmalloc_array(rval, sizeof(*vfwn->link_frequencies), > > + GFP_KERNEL); > > + if (!vfwn->link_frequencies) { > > + rval = -ENOMEM; > > + goto out_err; > > + } > > + > > + vfwn->nr_of_link_frequencies = rval; > > + > > + rval = fwnode_property_read_u64_array( > > + fwn, "link-frequencies", vfwn->link_frequencies, > > + vfwn->nr_of_link_frequencies); > > rval = fwnode_property_read_u64_array(fwn, "link-frequencies", > vfwn->link_frequencies, > vfwn->nr_of_link_frequencies); > > > + if (rval < 0) > > + goto out_err; > > + > > + return vfwn; > > + > > +out_err: > > + v4l2_fwnode_endpoint_free(vfwn); > > + return ERR_PTR(rval); > > +} > > +EXPORT_SYMBOL(v4l2_fwnode_endpoint_alloc_parse); > > + > > +/** > > + * v4l2_fwnode_endpoint_parse_link() - parse a link between two endpoints > > + * @node: pointer to the fwnode at the local end of the link > > The parameter is called __fwn. I believe you should rename it to fwn, > otherwise the documentation will look weird. > > As explained before, you should mention that this is an endpoint fwnode > handle. Agreed. > > > + * @link: pointer to the V4L2 fwnode link data structure > > + * > > + * Fill the link structure with the local and remote nodes and port > > numbers. > > + * The local_node and remote_node fields are set to point to the local and > > + * remote port's parent nodes respectively (the port parent node being the > > + * parent node of the port node if that node isn't a 'ports' node, or the > > + * grand-parent node of the port node otherwise). > > + * > > + * A reference is taken to both the local and remote nodes, the caller > > + * must use v4l2_fwnode_endpoint_put_link() to drop the references > > + * when done with the link. > > Just curious, is there a reason to wrap earlier than the 80 columns limit ? > > * A reference is taken to both the local and remote nodes, the caller must > use > * v4l2_fwnode_endpoint_put_link() to drop the references when done with the > * link. > > would work. It is like a speed limit, you can perfectly legally drive slower than 80 characters per line, right? :-) Albeit the conditions seem pretty good in this file, I can try pushing it closer to the limit. > > > + * Return: 0 on success, or -ENOLINK if the remote fwnode can't be found. > > Here too you should mention remote endpoint. Oh yes. > > > + */ > > +int v4l2_fwnode_parse_link(struct fwnode_handle *__fwn, > > + struct v4l2_fwnode_link *link) > > +{ > > + struct fwnode_handle *fwn; > > + const char *port_prop = is_of_node(__fwn) ? "reg" : "port"; > > + > > + memset(link, 0, sizeof(*link)); > > + > > + fwn = fwnode_get_parent(__fwn); > > + fwnode_property_read_u32(fwn, port_prop, &link->local_port); > > + fwn = fwnode_get_next_parent(fwn); > > + if (is_of_node(fwn)) { > > + if (of_node_cmp(to_of_node(fwn)->name, "ports") == 0) > > + fwn = fwnode_get_next_parent(fwn); > > + } else { > > + /* The "ports" node is always there in ACPI. */ > > + fwn = fwnode_get_next_parent(fwn); > > + } > > To avoid duplicating the fwnode_get_next_parent(fwn) call, you could write > > if (!is_of_node(fwn) || > of_node_cmp(to_of_node(fwn)->name, "ports") == 0) { > /* The "ports" node is always there in ACPI. */ > fwn = fwnode_get_next_parent(fwn); > } Will change. > > > + link->local_node = fwn; > > + > > + fwn = fwnode_graph_get_remote_endpoint(fwn); > > + if (!fwn) { > > + fwnode_handle_put(fwn); > > + return -ENOLINK; > > + } > > + > > + fwn = fwnode_get_parent(fwn); > > + fwnode_property_read_u32(fwn, port_prop, &link->remote_port); > > + fwn = fwnode_get_next_parent(fwn); > > + if (is_of_node(fwn)) { > > + if (of_node_cmp(to_of_node(fwn)->name, "ports") == 0) > > + fwn = fwnode_get_next_parent(fwn); > > + } else { > > + /* The "ports" node is always there in ACPI. */ > > + fwn = fwnode_get_next_parent(fwn); > > + } > > Same comment here. > > > + link->remote_node = fwn; > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(v4l2_fwnode_parse_link); > > + > > +/** > > + * v4l2_fwnode_put_link() - drop references to nodes in a link > > + * @link: pointer to the V4L2 fwnode link data structure > > + * > > + * Drop references to the local and remote nodes in the link. This > > + * function must be called on every link parsed with > > + * v4l2_fwnode_parse_link(). > > + */ > > +void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link) > > +{ > > + fwnode_handle_put(link->local_node); > > + fwnode_handle_put(link->remote_node); > > +} > > +EXPORT_SYMBOL(v4l2_fwnode_put_link); > > + > > +MODULE_LICENSE("GPL"); > > +MODULE_AUTHOR("Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx>"); > > +MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@xxxxxxxxxxx>"); > > +MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@xxxxxx>"); > > diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h > > new file mode 100644 > > index 0000000..a675d8a > > --- /dev/null > > +++ b/include/media/v4l2-fwnode.h > > @@ -0,0 +1,104 @@ > > +/* > > + * V4L2 fwnode binding parsing library > > + * > > + * Copyright (c) 2016 Intel Corporation. > > + * Author: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> > > + * > > + * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. > > + * Author: Sylwester Nawrocki <s.nawrocki@xxxxxxxxxxx> > > + * > > + * Copyright (C) 2012 Renesas Electronics Corp. > > + * Author: Guennadi Liakhovetski <g.liakhovetski@xxxxxx> > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of version 2 of the GNU General Public License as > > + * published by the Free Software Foundation. > > + */ > > +#ifndef _V4L2_FWNODE_H > > +#define _V4L2_FWNODE_H > > + > > +#include <linux/list.h> > > +#include <linux/types.h> > > +#include <linux/errno.h> > > +#include <linux/of_graph.h> > > Alphabetical order please. Yes. > > > +#include <media/v4l2-mediabus.h> > > + > > +struct fwnode_handle; > > + > > +/** > > + * struct v4l2_fwnode_bus_mipi_csi2 - MIPI CSI-2 bus data structure > > + * @flags: media bus (V4L2_MBUS_*) flags > > + * @data_lanes: an array of physical data lane indexes > > + * @clock_lane: physical lane index of the clock lane > > + * @num_data_lanes: number of data lanes > > + * @lane_polarities: polarity of the lanes. The order is the same of > > + * the physical lanes. > > + */ > > +struct v4l2_fwnode_bus_mipi_csi2 { > > + unsigned int flags; > > + unsigned char data_lanes[4]; > > + unsigned char clock_lane; > > + unsigned short num_data_lanes; > > + bool lane_polarities[5]; > > +}; > > + > > +/** > > + * struct v4l2_fwnode_bus_parallel - parallel data bus data structure > > + * @flags: media bus (V4L2_MBUS_*) flags > > + * @bus_width: bus width in bits > > + * @data_shift: data shift in bits > > + */ > > +struct v4l2_fwnode_bus_parallel { > > + unsigned int flags; > > + unsigned char bus_width; > > + unsigned char data_shift; > > +}; > > + > > +/** > > + * struct v4l2_fwnode_endpoint - the endpoint data structure > > + * @base: fwnode endpoint of the v4l2_fwnode > > + * @bus_type: bus type > > + * @bus: bus configuration data structure > > + * @link_frequencies: array of supported link frequencies > > + * @nr_of_link_frequencies: number of elements in link_frequenccies array > > + */ > > +struct v4l2_fwnode_endpoint { > > + struct fwnode_endpoint base; > > + /* > > + * Fields below this line will be zeroed by > > + * v4l2_fwnode_parse_endpoint() > > + */ > > + enum v4l2_mbus_type bus_type; > > + union { > > + struct v4l2_fwnode_bus_parallel parallel; > > + struct v4l2_fwnode_bus_mipi_csi2 mipi_csi2; > > + } bus; > > + u64 *link_frequencies; > > + unsigned int nr_of_link_frequencies; > > +}; > > + > > +/** > > + * struct v4l2_fwnode_link - a link between two endpoints > > + * @local_node: pointer to device_node of this endpoint > > + * @local_port: identifier of the port this endpoint belongs to > > + * @remote_node: pointer to device_node of the remote endpoint > > + * @remote_port: identifier of the port the remote endpoint belongs to > > + */ > > +struct v4l2_fwnode_link { > > + struct fwnode_handle *local_node; > > + unsigned int local_port; > > + struct fwnode_handle *remote_node; > > + unsigned int remote_port; > > +}; > > + > > +int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwn, > > + struct v4l2_fwnode_endpoint *vfwn); > > +struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse( > > + struct fwnode_handle *fwn); > > +void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vfwn); > > +int v4l2_fwnode_parse_link(struct fwnode_handle *fwn, > > + struct v4l2_fwnode_link *link); > > +void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link); > > + > > +#endif /* _V4L2_FWNODE_H */ > -- Regards, Sakari Ailus e-mail: sakari.ailus@xxxxxx XMPP: sailus@xxxxxxxxxxxxxx