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