Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /* * V4L2 OF binding parsing library * * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> * * Copyright (C) 2012 Renesas Electronics Corp. * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> * * 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/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/string.h> #include <linux/types.h> #include <media/v4l2-of.h> static void v4l2_of_parse_csi_bus(const struct device_node *node, struct v4l2_of_endpoint *endpoint) { struct v4l2_of_bus_mipi_csi2 *bus = &endpoint->bus.mipi_csi2; u32 data_lanes[ARRAY_SIZE(bus->data_lanes)]; struct property *prop; bool have_clk_lane = false; unsigned int flags = 0; u32 v; prop = of_find_property(node, "data-lanes", NULL); if (prop) { const __be32 *lane = NULL; int i; for (i = 0; i < ARRAY_SIZE(data_lanes); i++) { lane = of_prop_next_u32(prop, lane, &data_lanes[i]); if (!lane) break; } bus->num_data_lanes = i; while (i--) bus->data_lanes[i] = data_lanes[i]; } if (!of_property_read_u32(node, "clock-lanes", &v)) { bus->clock_lane = v; have_clk_lane = true; } if (of_get_property(node, "clock-noncontinuous", &v)) 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; endpoint->bus_type = V4L2_MBUS_CSI2; } static void v4l2_of_parse_parallel_bus(const struct device_node *node, struct v4l2_of_endpoint *endpoint) { struct v4l2_of_bus_parallel *bus = &endpoint->bus.parallel; unsigned int flags = 0; u32 v; if (!of_property_read_u32(node, "hsync-active", &v)) flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH : V4L2_MBUS_HSYNC_ACTIVE_LOW; if (!of_property_read_u32(node, "vsync-active", &v)) flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH : V4L2_MBUS_VSYNC_ACTIVE_LOW; if (!of_property_read_u32(node, "pclk-sample", &v)) flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING : V4L2_MBUS_PCLK_SAMPLE_FALLING; if (!of_property_read_u32(node, "field-even-active", &v)) flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH : V4L2_MBUS_FIELD_EVEN_LOW; if (flags) endpoint->bus_type = V4L2_MBUS_PARALLEL; else endpoint->bus_type = V4L2_MBUS_BT656; if (!of_property_read_u32(node, "data-active", &v)) flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH : V4L2_MBUS_DATA_ACTIVE_LOW; if (of_get_property(node, "slave-mode", &v)) flags |= V4L2_MBUS_SLAVE; else flags |= V4L2_MBUS_MASTER; if (!of_property_read_u32(node, "bus-width", &v)) bus->bus_width = v; if (!of_property_read_u32(node, "data-shift", &v)) bus->data_shift = v; if (!of_property_read_u32(node, "sync-on-green-active", &v)) flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH : V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW; bus->flags = flags; } /** * v4l2_of_parse_endpoint() - parse all endpoint node properties * @node: pointer to endpoint device_node * @endpoint: pointer to the V4L2 OF endpoint 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. * * Return: 0. */ int v4l2_of_parse_endpoint(const struct device_node *node, struct v4l2_of_endpoint *endpoint) { of_graph_parse_endpoint(node, &endpoint->base); endpoint->bus_type = 0; memset(&endpoint->bus, 0, sizeof(endpoint->bus)); v4l2_of_parse_csi_bus(node, endpoint); /* * Parse the parallel video bus properties only if none * of the MIPI CSI-2 specific properties were found. */ if (endpoint->bus.mipi_csi2.flags == 0) v4l2_of_parse_parallel_bus(node, endpoint); return 0; } EXPORT_SYMBOL(v4l2_of_parse_endpoint); |