1/* 2 * V4L2 OF binding parsing library 3 * 4 * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. 5 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> 6 * 7 * Copyright (C) 2012 Renesas Electronics Corp. 8 * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of version 2 of the GNU General Public License as 12 * published by the Free Software Foundation. 13 */ 14#include <linux/kernel.h> 15#include <linux/module.h> 16#include <linux/of.h> 17#include <linux/string.h> 18#include <linux/types.h> 19 20#include <media/v4l2-of.h> 21 22static int v4l2_of_parse_csi_bus(const struct device_node *node, 23 struct v4l2_of_endpoint *endpoint) 24{ 25 struct v4l2_of_bus_mipi_csi2 *bus = &endpoint->bus.mipi_csi2; 26 struct property *prop; 27 bool have_clk_lane = false; 28 unsigned int flags = 0; 29 u32 v; 30 31 prop = of_find_property(node, "data-lanes", NULL); 32 if (prop) { 33 const __be32 *lane = NULL; 34 unsigned int i; 35 36 for (i = 0; i < ARRAY_SIZE(bus->data_lanes); i++) { 37 lane = of_prop_next_u32(prop, lane, &v); 38 if (!lane) 39 break; 40 bus->data_lanes[i] = v; 41 } 42 bus->num_data_lanes = i; 43 } 44 45 prop = of_find_property(node, "lane-polarities", NULL); 46 if (prop) { 47 const __be32 *polarity = NULL; 48 unsigned int i; 49 50 for (i = 0; i < ARRAY_SIZE(bus->lane_polarities); i++) { 51 polarity = of_prop_next_u32(prop, polarity, &v); 52 if (!polarity) 53 break; 54 bus->lane_polarities[i] = v; 55 } 56 57 if (i < 1 + bus->num_data_lanes /* clock + data */) { 58 pr_warn("%s: too few lane-polarities entries (need %u, got %u)\n", 59 node->full_name, 1 + bus->num_data_lanes, i); 60 return -EINVAL; 61 } 62 } 63 64 if (!of_property_read_u32(node, "clock-lanes", &v)) { 65 bus->clock_lane = v; 66 have_clk_lane = true; 67 } 68 69 if (of_get_property(node, "clock-noncontinuous", &v)) 70 flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK; 71 else if (have_clk_lane || bus->num_data_lanes > 0) 72 flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; 73 74 bus->flags = flags; 75 endpoint->bus_type = V4L2_MBUS_CSI2; 76 77 return 0; 78} 79 80static void v4l2_of_parse_parallel_bus(const struct device_node *node, 81 struct v4l2_of_endpoint *endpoint) 82{ 83 struct v4l2_of_bus_parallel *bus = &endpoint->bus.parallel; 84 unsigned int flags = 0; 85 u32 v; 86 87 if (!of_property_read_u32(node, "hsync-active", &v)) 88 flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH : 89 V4L2_MBUS_HSYNC_ACTIVE_LOW; 90 91 if (!of_property_read_u32(node, "vsync-active", &v)) 92 flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH : 93 V4L2_MBUS_VSYNC_ACTIVE_LOW; 94 95 if (!of_property_read_u32(node, "pclk-sample", &v)) 96 flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING : 97 V4L2_MBUS_PCLK_SAMPLE_FALLING; 98 99 if (!of_property_read_u32(node, "field-even-active", &v)) 100 flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH : 101 V4L2_MBUS_FIELD_EVEN_LOW; 102 if (flags) 103 endpoint->bus_type = V4L2_MBUS_PARALLEL; 104 else 105 endpoint->bus_type = V4L2_MBUS_BT656; 106 107 if (!of_property_read_u32(node, "data-active", &v)) 108 flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH : 109 V4L2_MBUS_DATA_ACTIVE_LOW; 110 111 if (of_get_property(node, "slave-mode", &v)) 112 flags |= V4L2_MBUS_SLAVE; 113 else 114 flags |= V4L2_MBUS_MASTER; 115 116 if (!of_property_read_u32(node, "bus-width", &v)) 117 bus->bus_width = v; 118 119 if (!of_property_read_u32(node, "data-shift", &v)) 120 bus->data_shift = v; 121 122 if (!of_property_read_u32(node, "sync-on-green-active", &v)) 123 flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH : 124 V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW; 125 126 bus->flags = flags; 127 128} 129 130/** 131 * v4l2_of_parse_endpoint() - parse all endpoint node properties 132 * @node: pointer to endpoint device_node 133 * @endpoint: pointer to the V4L2 OF endpoint data structure 134 * 135 * All properties are optional. If none are found, we don't set any flags. 136 * This means the port has a static configuration and no properties have 137 * to be specified explicitly. 138 * If any properties that identify the bus as parallel are found and 139 * slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if we recognise 140 * the bus as serial CSI-2 and clock-noncontinuous isn't set, we set the 141 * V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. 142 * The caller should hold a reference to @node. 143 * 144 * Return: 0. 145 */ 146int v4l2_of_parse_endpoint(const struct device_node *node, 147 struct v4l2_of_endpoint *endpoint) 148{ 149 int rval; 150 151 of_graph_parse_endpoint(node, &endpoint->base); 152 endpoint->bus_type = 0; 153 memset(&endpoint->bus, 0, sizeof(endpoint->bus)); 154 155 rval = v4l2_of_parse_csi_bus(node, endpoint); 156 if (rval) 157 return rval; 158 /* 159 * Parse the parallel video bus properties only if none 160 * of the MIPI CSI-2 specific properties were found. 161 */ 162 if (endpoint->bus.mipi_csi2.flags == 0) 163 v4l2_of_parse_parallel_bus(node, endpoint); 164 165 return 0; 166} 167EXPORT_SYMBOL(v4l2_of_parse_endpoint); 168 169/** 170 * v4l2_of_parse_link() - parse a link between two endpoints 171 * @node: pointer to the endpoint at the local end of the link 172 * @link: pointer to the V4L2 OF link data structure 173 * 174 * Fill the link structure with the local and remote nodes and port numbers. 175 * The local_node and remote_node fields are set to point to the local and 176 * remote port's parent nodes respectively (the port parent node being the 177 * parent node of the port node if that node isn't a 'ports' node, or the 178 * grand-parent node of the port node otherwise). 179 * 180 * A reference is taken to both the local and remote nodes, the caller must use 181 * v4l2_of_put_link() to drop the references when done with the link. 182 * 183 * Return: 0 on success, or -ENOLINK if the remote endpoint can't be found. 184 */ 185int v4l2_of_parse_link(const struct device_node *node, 186 struct v4l2_of_link *link) 187{ 188 struct device_node *np; 189 190 memset(link, 0, sizeof(*link)); 191 192 np = of_get_parent(node); 193 of_property_read_u32(np, "reg", &link->local_port); 194 np = of_get_next_parent(np); 195 if (of_node_cmp(np->name, "ports") == 0) 196 np = of_get_next_parent(np); 197 link->local_node = np; 198 199 np = of_parse_phandle(node, "remote-endpoint", 0); 200 if (!np) { 201 of_node_put(link->local_node); 202 return -ENOLINK; 203 } 204 205 np = of_get_parent(np); 206 of_property_read_u32(np, "reg", &link->remote_port); 207 np = of_get_next_parent(np); 208 if (of_node_cmp(np->name, "ports") == 0) 209 np = of_get_next_parent(np); 210 link->remote_node = np; 211 212 return 0; 213} 214EXPORT_SYMBOL(v4l2_of_parse_link); 215 216/** 217 * v4l2_of_put_link() - drop references to nodes in a link 218 * @link: pointer to the V4L2 OF link data structure 219 * 220 * Drop references to the local and remote nodes in the link. This function must 221 * be called on every link parsed with v4l2_of_parse_link(). 222 */ 223void v4l2_of_put_link(struct v4l2_of_link *link) 224{ 225 of_node_put(link->local_node); 226 of_node_put(link->remote_node); 227} 228EXPORT_SYMBOL(v4l2_of_put_link); 229