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/module.h> 23 #include <linux/of.h> 24 #include <linux/property.h> 25 #include <linux/slab.h> 26 #include <linux/string.h> 27 #include <linux/types.h> 28 29 #include <media/v4l2-fwnode.h> 30 31 static int v4l2_fwnode_endpoint_parse_csi_bus(struct fwnode_handle *fwnode, 32 struct v4l2_fwnode_endpoint *vep) 33 { 34 struct v4l2_fwnode_bus_mipi_csi2 *bus = &vep->bus.mipi_csi2; 35 bool have_clk_lane = false; 36 unsigned int flags = 0, lanes_used = 0; 37 unsigned int i; 38 u32 v; 39 int rval; 40 41 rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0); 42 if (rval > 0) { 43 u32 array[ARRAY_SIZE(bus->data_lanes)]; 44 45 bus->num_data_lanes = 46 min_t(int, ARRAY_SIZE(bus->data_lanes), rval); 47 48 fwnode_property_read_u32_array(fwnode, "data-lanes", array, 49 bus->num_data_lanes); 50 51 for (i = 0; i < bus->num_data_lanes; i++) { 52 if (lanes_used & BIT(array[i])) 53 pr_warn("duplicated lane %u in data-lanes\n", 54 array[i]); 55 lanes_used |= BIT(array[i]); 56 57 bus->data_lanes[i] = array[i]; 58 } 59 } 60 61 rval = fwnode_property_read_u32_array(fwnode, "lane-polarities", NULL, 62 0); 63 if (rval > 0) { 64 u32 array[ARRAY_SIZE(bus->lane_polarities)]; 65 66 if (rval < 1 + bus->num_data_lanes /* clock + data */) { 67 pr_warn("too few lane-polarities entries (need %u, got %u)\n", 68 1 + bus->num_data_lanes, rval); 69 return -EINVAL; 70 } 71 72 fwnode_property_read_u32_array(fwnode, "lane-polarities", array, 73 1 + bus->num_data_lanes); 74 75 for (i = 0; i < 1 + bus->num_data_lanes; i++) 76 bus->lane_polarities[i] = array[i]; 77 } 78 79 if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) { 80 if (lanes_used & BIT(v)) 81 pr_warn("duplicated lane %u in clock-lanes\n", v); 82 lanes_used |= BIT(v); 83 84 bus->clock_lane = v; 85 have_clk_lane = true; 86 } 87 88 if (fwnode_property_present(fwnode, "clock-noncontinuous")) 89 flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK; 90 else if (have_clk_lane || bus->num_data_lanes > 0) 91 flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; 92 93 bus->flags = flags; 94 vep->bus_type = V4L2_MBUS_CSI2; 95 96 return 0; 97 } 98 99 static void v4l2_fwnode_endpoint_parse_parallel_bus( 100 struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep) 101 { 102 struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel; 103 unsigned int flags = 0; 104 u32 v; 105 106 if (!fwnode_property_read_u32(fwnode, "hsync-active", &v)) 107 flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH : 108 V4L2_MBUS_HSYNC_ACTIVE_LOW; 109 110 if (!fwnode_property_read_u32(fwnode, "vsync-active", &v)) 111 flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH : 112 V4L2_MBUS_VSYNC_ACTIVE_LOW; 113 114 if (!fwnode_property_read_u32(fwnode, "field-even-active", &v)) 115 flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH : 116 V4L2_MBUS_FIELD_EVEN_LOW; 117 if (flags) 118 vep->bus_type = V4L2_MBUS_PARALLEL; 119 else 120 vep->bus_type = V4L2_MBUS_BT656; 121 122 if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v)) 123 flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING : 124 V4L2_MBUS_PCLK_SAMPLE_FALLING; 125 126 if (!fwnode_property_read_u32(fwnode, "data-active", &v)) 127 flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH : 128 V4L2_MBUS_DATA_ACTIVE_LOW; 129 130 if (fwnode_property_present(fwnode, "slave-mode")) 131 flags |= V4L2_MBUS_SLAVE; 132 else 133 flags |= V4L2_MBUS_MASTER; 134 135 if (!fwnode_property_read_u32(fwnode, "bus-width", &v)) 136 bus->bus_width = v; 137 138 if (!fwnode_property_read_u32(fwnode, "data-shift", &v)) 139 bus->data_shift = v; 140 141 if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v)) 142 flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH : 143 V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW; 144 145 bus->flags = flags; 146 147 } 148 149 /** 150 * v4l2_fwnode_endpoint_parse() - parse all fwnode node properties 151 * @fwnode: pointer to the endpoint's fwnode handle 152 * @vep: pointer to the V4L2 fwnode data structure 153 * 154 * All properties are optional. If none are found, we don't set any flags. This 155 * means the port has a static configuration and no properties have to be 156 * specified explicitly. If any properties that identify the bus as parallel 157 * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if 158 * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we 159 * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a 160 * reference to @fwnode. 161 * 162 * NOTE: This function does not parse properties the size of which is variable 163 * without a low fixed limit. Please use v4l2_fwnode_endpoint_alloc_parse() in 164 * new drivers instead. 165 * 166 * Return: 0 on success or a negative error code on failure. 167 */ 168 int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, 169 struct v4l2_fwnode_endpoint *vep) 170 { 171 int rval; 172 173 fwnode_graph_parse_endpoint(fwnode, &vep->base); 174 175 /* Zero fields from bus_type to until the end */ 176 memset(&vep->bus_type, 0, sizeof(*vep) - 177 offsetof(typeof(*vep), bus_type)); 178 179 rval = v4l2_fwnode_endpoint_parse_csi_bus(fwnode, vep); 180 if (rval) 181 return rval; 182 /* 183 * Parse the parallel video bus properties only if none 184 * of the MIPI CSI-2 specific properties were found. 185 */ 186 if (vep->bus.mipi_csi2.flags == 0) 187 v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep); 188 189 return 0; 190 } 191 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_parse); 192 193 /* 194 * v4l2_fwnode_endpoint_free() - free the V4L2 fwnode acquired by 195 * v4l2_fwnode_endpoint_alloc_parse() 196 * @vep - the V4L2 fwnode the resources of which are to be released 197 * 198 * It is safe to call this function with NULL argument or on a V4L2 fwnode the 199 * parsing of which failed. 200 */ 201 void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep) 202 { 203 if (IS_ERR_OR_NULL(vep)) 204 return; 205 206 kfree(vep->link_frequencies); 207 kfree(vep); 208 } 209 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_free); 210 211 /** 212 * v4l2_fwnode_endpoint_alloc_parse() - parse all fwnode node properties 213 * @fwnode: pointer to the endpoint's fwnode handle 214 * 215 * All properties are optional. If none are found, we don't set any flags. This 216 * means the port has a static configuration and no properties have to be 217 * specified explicitly. If any properties that identify the bus as parallel 218 * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if 219 * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we 220 * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a 221 * reference to @fwnode. 222 * 223 * v4l2_fwnode_endpoint_alloc_parse() has two important differences to 224 * v4l2_fwnode_endpoint_parse(): 225 * 226 * 1. It also parses variable size data. 227 * 228 * 2. The memory it has allocated to store the variable size data must be freed 229 * using v4l2_fwnode_endpoint_free() when no longer needed. 230 * 231 * Return: Pointer to v4l2_fwnode_endpoint if successful, on an error pointer 232 * on error. 233 */ 234 struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse( 235 struct fwnode_handle *fwnode) 236 { 237 struct v4l2_fwnode_endpoint *vep; 238 int rval; 239 240 vep = kzalloc(sizeof(*vep), GFP_KERNEL); 241 if (!vep) 242 return ERR_PTR(-ENOMEM); 243 244 rval = v4l2_fwnode_endpoint_parse(fwnode, vep); 245 if (rval < 0) 246 goto out_err; 247 248 rval = fwnode_property_read_u64_array(fwnode, "link-frequencies", 249 NULL, 0); 250 if (rval < 0) 251 goto out_err; 252 253 vep->link_frequencies = 254 kmalloc_array(rval, sizeof(*vep->link_frequencies), GFP_KERNEL); 255 if (!vep->link_frequencies) { 256 rval = -ENOMEM; 257 goto out_err; 258 } 259 260 vep->nr_of_link_frequencies = rval; 261 262 rval = fwnode_property_read_u64_array(fwnode, "link-frequencies", 263 vep->link_frequencies, 264 vep->nr_of_link_frequencies); 265 if (rval < 0) 266 goto out_err; 267 268 return vep; 269 270 out_err: 271 v4l2_fwnode_endpoint_free(vep); 272 return ERR_PTR(rval); 273 } 274 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse); 275 276 /** 277 * v4l2_fwnode_endpoint_parse_link() - parse a link between two endpoints 278 * @__fwnode: pointer to the endpoint's fwnode at the local end of the link 279 * @link: pointer to the V4L2 fwnode link data structure 280 * 281 * Fill the link structure with the local and remote nodes and port numbers. 282 * The local_node and remote_node fields are set to point to the local and 283 * remote port's parent nodes respectively (the port parent node being the 284 * parent node of the port node if that node isn't a 'ports' node, or the 285 * grand-parent node of the port node otherwise). 286 * 287 * A reference is taken to both the local and remote nodes, the caller must use 288 * v4l2_fwnode_endpoint_put_link() to drop the references when done with the 289 * link. 290 * 291 * Return: 0 on success, or -ENOLINK if the remote endpoint fwnode can't be 292 * found. 293 */ 294 int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode, 295 struct v4l2_fwnode_link *link) 296 { 297 const char *port_prop = is_of_node(__fwnode) ? "reg" : "port"; 298 struct fwnode_handle *fwnode; 299 300 memset(link, 0, sizeof(*link)); 301 302 fwnode = fwnode_get_parent(__fwnode); 303 fwnode_property_read_u32(fwnode, port_prop, &link->local_port); 304 fwnode = fwnode_get_next_parent(fwnode); 305 if (is_of_node(fwnode) && 306 of_node_cmp(to_of_node(fwnode)->name, "ports") == 0) 307 fwnode = fwnode_get_next_parent(fwnode); 308 link->local_node = fwnode; 309 310 fwnode = fwnode_graph_get_remote_endpoint(__fwnode); 311 if (!fwnode) { 312 fwnode_handle_put(fwnode); 313 return -ENOLINK; 314 } 315 316 fwnode = fwnode_get_parent(fwnode); 317 fwnode_property_read_u32(fwnode, port_prop, &link->remote_port); 318 fwnode = fwnode_get_next_parent(fwnode); 319 if (is_of_node(fwnode) && 320 of_node_cmp(to_of_node(fwnode)->name, "ports") == 0) 321 fwnode = fwnode_get_next_parent(fwnode); 322 link->remote_node = fwnode; 323 324 return 0; 325 } 326 EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_link); 327 328 /** 329 * v4l2_fwnode_put_link() - drop references to nodes in a link 330 * @link: pointer to the V4L2 fwnode link data structure 331 * 332 * Drop references to the local and remote nodes in the link. This function 333 * must be called on every link parsed with v4l2_fwnode_parse_link(). 334 */ 335 void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link) 336 { 337 fwnode_handle_put(link->local_node); 338 fwnode_handle_put(link->remote_node); 339 } 340 EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link); 341 342 MODULE_LICENSE("GPL"); 343 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); 344 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); 345 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); 346