hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/media/v4l2-core/v4l2-fwnode.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * V4L2 fwnode binding parsing library
34 *
....@@ -12,10 +13,6 @@
1213 *
1314 * Copyright (C) 2012 Renesas Electronics Corp.
1415 * 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.
1916 */
2017 #include <linux/acpi.h>
2118 #include <linux/kernel.h>
....@@ -36,194 +33,480 @@
3633 V4L2_FWNODE_BUS_TYPE_CSI2_CPHY,
3734 V4L2_FWNODE_BUS_TYPE_CSI1,
3835 V4L2_FWNODE_BUS_TYPE_CCP2,
36
+ V4L2_FWNODE_BUS_TYPE_CSI2_DPHY,
37
+ V4L2_FWNODE_BUS_TYPE_PARALLEL,
38
+ V4L2_FWNODE_BUS_TYPE_BT656,
3939 NR_OF_V4L2_FWNODE_BUS_TYPE,
4040 };
4141
42
+static const struct v4l2_fwnode_bus_conv {
43
+ enum v4l2_fwnode_bus_type fwnode_bus_type;
44
+ enum v4l2_mbus_type mbus_type;
45
+ const char *name;
46
+} buses[] = {
47
+ {
48
+ V4L2_FWNODE_BUS_TYPE_GUESS,
49
+ V4L2_MBUS_UNKNOWN,
50
+ "not specified",
51
+ }, {
52
+ V4L2_FWNODE_BUS_TYPE_CSI2_CPHY,
53
+ V4L2_MBUS_CSI2_CPHY,
54
+ "MIPI CSI-2 C-PHY",
55
+ }, {
56
+ V4L2_FWNODE_BUS_TYPE_CSI1,
57
+ V4L2_MBUS_CSI1,
58
+ "MIPI CSI-1",
59
+ }, {
60
+ V4L2_FWNODE_BUS_TYPE_CCP2,
61
+ V4L2_MBUS_CCP2,
62
+ "compact camera port 2",
63
+ }, {
64
+ V4L2_FWNODE_BUS_TYPE_CSI2_DPHY,
65
+ V4L2_MBUS_CSI2_DPHY,
66
+ "MIPI CSI-2 D-PHY",
67
+ }, {
68
+ V4L2_FWNODE_BUS_TYPE_PARALLEL,
69
+ V4L2_MBUS_PARALLEL,
70
+ "parallel",
71
+ }, {
72
+ V4L2_FWNODE_BUS_TYPE_BT656,
73
+ V4L2_MBUS_BT656,
74
+ "Bt.656",
75
+ }
76
+};
77
+
78
+static const struct v4l2_fwnode_bus_conv *
79
+get_v4l2_fwnode_bus_conv_by_fwnode_bus(enum v4l2_fwnode_bus_type type)
80
+{
81
+ unsigned int i;
82
+
83
+ for (i = 0; i < ARRAY_SIZE(buses); i++)
84
+ if (buses[i].fwnode_bus_type == type)
85
+ return &buses[i];
86
+
87
+ return NULL;
88
+}
89
+
90
+static enum v4l2_mbus_type
91
+v4l2_fwnode_bus_type_to_mbus(enum v4l2_fwnode_bus_type type)
92
+{
93
+ const struct v4l2_fwnode_bus_conv *conv =
94
+ get_v4l2_fwnode_bus_conv_by_fwnode_bus(type);
95
+
96
+ return conv ? conv->mbus_type : V4L2_MBUS_INVALID;
97
+}
98
+
99
+static const char *
100
+v4l2_fwnode_bus_type_to_string(enum v4l2_fwnode_bus_type type)
101
+{
102
+ const struct v4l2_fwnode_bus_conv *conv =
103
+ get_v4l2_fwnode_bus_conv_by_fwnode_bus(type);
104
+
105
+ return conv ? conv->name : "not found";
106
+}
107
+
108
+static const struct v4l2_fwnode_bus_conv *
109
+get_v4l2_fwnode_bus_conv_by_mbus(enum v4l2_mbus_type type)
110
+{
111
+ unsigned int i;
112
+
113
+ for (i = 0; i < ARRAY_SIZE(buses); i++)
114
+ if (buses[i].mbus_type == type)
115
+ return &buses[i];
116
+
117
+ return NULL;
118
+}
119
+
120
+static const char *
121
+v4l2_fwnode_mbus_type_to_string(enum v4l2_mbus_type type)
122
+{
123
+ const struct v4l2_fwnode_bus_conv *conv =
124
+ get_v4l2_fwnode_bus_conv_by_mbus(type);
125
+
126
+ return conv ? conv->name : "not found";
127
+}
128
+
42129 static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode,
43
- struct v4l2_fwnode_endpoint *vep)
130
+ struct v4l2_fwnode_endpoint *vep,
131
+ enum v4l2_mbus_type bus_type)
44132 {
45133 struct v4l2_fwnode_bus_mipi_csi2 *bus = &vep->bus.mipi_csi2;
46
- bool have_clk_lane = false;
134
+ bool have_clk_lane = false, have_data_lanes = false,
135
+ have_lane_polarities = false;
47136 unsigned int flags = 0, lanes_used = 0;
137
+ u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES];
138
+ u32 clock_lane = 0;
139
+ unsigned int num_data_lanes = 0;
140
+ bool use_default_lane_mapping = false;
48141 unsigned int i;
49142 u32 v;
50143 int rval;
51144
52
- rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0);
53
- if (rval > 0) {
54
- u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES];
145
+ if (bus_type == V4L2_MBUS_CSI2_DPHY ||
146
+ bus_type == V4L2_MBUS_CSI2_CPHY) {
147
+ use_default_lane_mapping = true;
55148
56
- bus->num_data_lanes =
149
+ num_data_lanes = min_t(u32, bus->num_data_lanes,
150
+ V4L2_FWNODE_CSI2_MAX_DATA_LANES);
151
+
152
+ clock_lane = bus->clock_lane;
153
+ if (clock_lane)
154
+ use_default_lane_mapping = false;
155
+
156
+ for (i = 0; i < num_data_lanes; i++) {
157
+ array[i] = bus->data_lanes[i];
158
+ if (array[i])
159
+ use_default_lane_mapping = false;
160
+ }
161
+
162
+ if (use_default_lane_mapping)
163
+ pr_debug("no lane mapping given, using defaults\n");
164
+ }
165
+
166
+ rval = fwnode_property_count_u32(fwnode, "data-lanes");
167
+ if (rval > 0) {
168
+ num_data_lanes =
57169 min_t(int, V4L2_FWNODE_CSI2_MAX_DATA_LANES, rval);
58170
59171 fwnode_property_read_u32_array(fwnode, "data-lanes", array,
60
- bus->num_data_lanes);
172
+ num_data_lanes);
61173
62
- for (i = 0; i < bus->num_data_lanes; i++) {
63
- if (lanes_used & BIT(array[i]))
64
- pr_warn("duplicated lane %u in data-lanes\n",
174
+ have_data_lanes = true;
175
+ if (use_default_lane_mapping) {
176
+ pr_debug("data-lanes property exists; disabling default mapping\n");
177
+ use_default_lane_mapping = false;
178
+ }
179
+ }
180
+
181
+ for (i = 0; i < num_data_lanes; i++) {
182
+ if (lanes_used & BIT(array[i])) {
183
+ if (have_data_lanes || !use_default_lane_mapping)
184
+ pr_warn("duplicated lane %u in data-lanes, using defaults\n",
65185 array[i]);
66
- lanes_used |= BIT(array[i]);
186
+ use_default_lane_mapping = true;
187
+ }
188
+ lanes_used |= BIT(array[i]);
67189
68
- bus->data_lanes[i] = array[i];
190
+ if (have_data_lanes)
191
+ pr_debug("lane %u position %u\n", i, array[i]);
192
+ }
193
+
194
+ rval = fwnode_property_count_u32(fwnode, "lane-polarities");
195
+ if (rval > 0) {
196
+ if (rval != 1 + num_data_lanes /* clock+data */) {
197
+ pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n",
198
+ 1 + num_data_lanes, rval);
199
+ return -EINVAL;
69200 }
70201
71
- rval = fwnode_property_read_u32_array(fwnode,
72
- "lane-polarities", NULL,
73
- 0);
74
- if (rval > 0) {
75
- if (rval != 1 + bus->num_data_lanes /* clock+data */) {
76
- pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n",
77
- 1 + bus->num_data_lanes, rval);
78
- return -EINVAL;
79
- }
80
-
81
- fwnode_property_read_u32_array(fwnode,
82
- "lane-polarities", array,
83
- 1 + bus->num_data_lanes);
84
-
85
- for (i = 0; i < 1 + bus->num_data_lanes; i++)
86
- bus->lane_polarities[i] = array[i];
87
- }
88
-
202
+ have_lane_polarities = true;
89203 }
90204
91205 if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) {
92
- if (lanes_used & BIT(v))
93
- pr_warn("duplicated lane %u in clock-lanes\n", v);
94
- lanes_used |= BIT(v);
95
-
96
- bus->clock_lane = v;
206
+ clock_lane = v;
207
+ pr_debug("clock lane position %u\n", v);
97208 have_clk_lane = true;
98209 }
99210
100
- if (fwnode_property_present(fwnode, "clock-noncontinuous"))
101
- flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
102
- else if (have_clk_lane || bus->num_data_lanes > 0)
103
- flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
211
+ if (have_clk_lane && lanes_used & BIT(clock_lane) &&
212
+ !use_default_lane_mapping) {
213
+ pr_warn("duplicated lane %u in clock-lanes, using defaults\n",
214
+ v);
215
+ use_default_lane_mapping = true;
216
+ }
104217
105
- bus->flags = flags;
106
- vep->bus_type = V4L2_MBUS_CSI2;
218
+ if (fwnode_property_present(fwnode, "clock-noncontinuous")) {
219
+ flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
220
+ pr_debug("non-continuous clock\n");
221
+ } else {
222
+ flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
223
+ }
224
+
225
+ if (bus_type == V4L2_MBUS_CSI2_DPHY ||
226
+ bus_type == V4L2_MBUS_CSI2_CPHY || lanes_used ||
227
+ have_clk_lane || (flags & ~V4L2_MBUS_CSI2_CONTINUOUS_CLOCK)) {
228
+ /* Only D-PHY has a clock lane. */
229
+ unsigned int dfl_data_lane_index =
230
+ bus_type == V4L2_MBUS_CSI2_DPHY;
231
+
232
+ bus->flags = flags;
233
+ if (bus_type == V4L2_MBUS_UNKNOWN)
234
+ vep->bus_type = V4L2_MBUS_CSI2_DPHY;
235
+ bus->num_data_lanes = num_data_lanes;
236
+
237
+ if (use_default_lane_mapping) {
238
+ bus->clock_lane = 0;
239
+ for (i = 0; i < num_data_lanes; i++)
240
+ bus->data_lanes[i] = dfl_data_lane_index + i;
241
+ } else {
242
+ bus->clock_lane = clock_lane;
243
+ for (i = 0; i < num_data_lanes; i++)
244
+ bus->data_lanes[i] = array[i];
245
+ }
246
+
247
+ if (have_lane_polarities) {
248
+ fwnode_property_read_u32_array(fwnode,
249
+ "lane-polarities", array,
250
+ 1 + num_data_lanes);
251
+
252
+ for (i = 0; i < 1 + num_data_lanes; i++) {
253
+ bus->lane_polarities[i] = array[i];
254
+ pr_debug("lane %u polarity %sinverted",
255
+ i, array[i] ? "" : "not ");
256
+ }
257
+ } else {
258
+ pr_debug("no lane polarities defined, assuming not inverted\n");
259
+ }
260
+ }
107261
108262 return 0;
109263 }
110264
111
-static void v4l2_fwnode_endpoint_parse_parallel_bus(
112
- struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep)
265
+#define PARALLEL_MBUS_FLAGS (V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
266
+ V4L2_MBUS_HSYNC_ACTIVE_LOW | \
267
+ V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
268
+ V4L2_MBUS_VSYNC_ACTIVE_LOW | \
269
+ V4L2_MBUS_FIELD_EVEN_HIGH | \
270
+ V4L2_MBUS_FIELD_EVEN_LOW)
271
+
272
+static void
273
+v4l2_fwnode_endpoint_parse_parallel_bus(struct fwnode_handle *fwnode,
274
+ struct v4l2_fwnode_endpoint *vep,
275
+ enum v4l2_mbus_type bus_type)
113276 {
114277 struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel;
115278 unsigned int flags = 0;
116279 u32 v;
117280
118
- if (!fwnode_property_read_u32(fwnode, "hsync-active", &v))
281
+ if (bus_type == V4L2_MBUS_PARALLEL || bus_type == V4L2_MBUS_BT656)
282
+ flags = bus->flags;
283
+
284
+ if (!fwnode_property_read_u32(fwnode, "hsync-active", &v)) {
285
+ flags &= ~(V4L2_MBUS_HSYNC_ACTIVE_HIGH |
286
+ V4L2_MBUS_HSYNC_ACTIVE_LOW);
119287 flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH :
120288 V4L2_MBUS_HSYNC_ACTIVE_LOW;
289
+ pr_debug("hsync-active %s\n", v ? "high" : "low");
290
+ }
121291
122
- if (!fwnode_property_read_u32(fwnode, "vsync-active", &v))
292
+ if (!fwnode_property_read_u32(fwnode, "vsync-active", &v)) {
293
+ flags &= ~(V4L2_MBUS_VSYNC_ACTIVE_HIGH |
294
+ V4L2_MBUS_VSYNC_ACTIVE_LOW);
123295 flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH :
124296 V4L2_MBUS_VSYNC_ACTIVE_LOW;
297
+ pr_debug("vsync-active %s\n", v ? "high" : "low");
298
+ }
125299
126
- if (!fwnode_property_read_u32(fwnode, "field-even-active", &v))
300
+ if (!fwnode_property_read_u32(fwnode, "field-even-active", &v)) {
301
+ flags &= ~(V4L2_MBUS_FIELD_EVEN_HIGH |
302
+ V4L2_MBUS_FIELD_EVEN_LOW);
127303 flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH :
128304 V4L2_MBUS_FIELD_EVEN_LOW;
129
- if (flags)
130
- vep->bus_type = V4L2_MBUS_PARALLEL;
131
- else
132
- vep->bus_type = V4L2_MBUS_BT656;
305
+ pr_debug("field-even-active %s\n", v ? "high" : "low");
306
+ }
133307
134
- if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v))
308
+ if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v)) {
309
+ flags &= ~(V4L2_MBUS_PCLK_SAMPLE_RISING |
310
+ V4L2_MBUS_PCLK_SAMPLE_FALLING);
135311 flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING :
136312 V4L2_MBUS_PCLK_SAMPLE_FALLING;
313
+ pr_debug("pclk-sample %s\n", v ? "high" : "low");
314
+ }
137315
138
- if (!fwnode_property_read_u32(fwnode, "data-active", &v))
316
+ if (!fwnode_property_read_u32(fwnode, "data-active", &v)) {
317
+ flags &= ~(V4L2_MBUS_DATA_ACTIVE_HIGH |
318
+ V4L2_MBUS_DATA_ACTIVE_LOW);
139319 flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH :
140320 V4L2_MBUS_DATA_ACTIVE_LOW;
321
+ pr_debug("data-active %s\n", v ? "high" : "low");
322
+ }
141323
142
- if (fwnode_property_present(fwnode, "slave-mode"))
324
+ if (fwnode_property_present(fwnode, "slave-mode")) {
325
+ pr_debug("slave mode\n");
326
+ flags &= ~V4L2_MBUS_MASTER;
143327 flags |= V4L2_MBUS_SLAVE;
144
- else
328
+ } else {
329
+ flags &= ~V4L2_MBUS_SLAVE;
145330 flags |= V4L2_MBUS_MASTER;
331
+ }
146332
147
- if (!fwnode_property_read_u32(fwnode, "bus-width", &v))
333
+ if (!fwnode_property_read_u32(fwnode, "bus-width", &v)) {
148334 bus->bus_width = v;
335
+ pr_debug("bus-width %u\n", v);
336
+ }
149337
150
- if (!fwnode_property_read_u32(fwnode, "data-shift", &v))
338
+ if (!fwnode_property_read_u32(fwnode, "data-shift", &v)) {
151339 bus->data_shift = v;
340
+ pr_debug("data-shift %u\n", v);
341
+ }
152342
153
- if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v))
343
+ if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v)) {
344
+ flags &= ~(V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH |
345
+ V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW);
154346 flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH :
155347 V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW;
348
+ pr_debug("sync-on-green-active %s\n", v ? "high" : "low");
349
+ }
156350
157
- if (!fwnode_property_read_u32(fwnode, "data-enable-active", &v))
351
+ if (!fwnode_property_read_u32(fwnode, "data-enable-active", &v)) {
352
+ flags &= ~(V4L2_MBUS_DATA_ENABLE_HIGH |
353
+ V4L2_MBUS_DATA_ENABLE_LOW);
158354 flags |= v ? V4L2_MBUS_DATA_ENABLE_HIGH :
159355 V4L2_MBUS_DATA_ENABLE_LOW;
356
+ pr_debug("data-enable-active %s\n", v ? "high" : "low");
357
+ }
160358
161
- bus->flags = flags;
162
-
359
+ switch (bus_type) {
360
+ default:
361
+ bus->flags = flags;
362
+ if (flags & PARALLEL_MBUS_FLAGS)
363
+ vep->bus_type = V4L2_MBUS_PARALLEL;
364
+ else
365
+ vep->bus_type = V4L2_MBUS_BT656;
366
+ break;
367
+ case V4L2_MBUS_PARALLEL:
368
+ vep->bus_type = V4L2_MBUS_PARALLEL;
369
+ bus->flags = flags;
370
+ break;
371
+ case V4L2_MBUS_BT656:
372
+ vep->bus_type = V4L2_MBUS_BT656;
373
+ bus->flags = flags & ~PARALLEL_MBUS_FLAGS;
374
+ break;
375
+ }
163376 }
164377
165378 static void
166379 v4l2_fwnode_endpoint_parse_csi1_bus(struct fwnode_handle *fwnode,
167380 struct v4l2_fwnode_endpoint *vep,
168
- u32 bus_type)
381
+ enum v4l2_mbus_type bus_type)
169382 {
170383 struct v4l2_fwnode_bus_mipi_csi1 *bus = &vep->bus.mipi_csi1;
171384 u32 v;
172385
173
- if (!fwnode_property_read_u32(fwnode, "clock-inv", &v))
386
+ if (!fwnode_property_read_u32(fwnode, "clock-inv", &v)) {
174387 bus->clock_inv = v;
388
+ pr_debug("clock-inv %u\n", v);
389
+ }
175390
176
- if (!fwnode_property_read_u32(fwnode, "strobe", &v))
391
+ if (!fwnode_property_read_u32(fwnode, "strobe", &v)) {
177392 bus->strobe = v;
393
+ pr_debug("strobe %u\n", v);
394
+ }
178395
179
- if (!fwnode_property_read_u32(fwnode, "data-lanes", &v))
396
+ if (!fwnode_property_read_u32(fwnode, "data-lanes", &v)) {
180397 bus->data_lane = v;
398
+ pr_debug("data-lanes %u\n", v);
399
+ }
181400
182
- if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v))
401
+ if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) {
183402 bus->clock_lane = v;
403
+ pr_debug("clock-lanes %u\n", v);
404
+ }
184405
185
- if (bus_type == V4L2_FWNODE_BUS_TYPE_CCP2)
406
+ if (bus_type == V4L2_MBUS_CCP2)
186407 vep->bus_type = V4L2_MBUS_CCP2;
187408 else
188409 vep->bus_type = V4L2_MBUS_CSI1;
189410 }
190411
191
-int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
192
- struct v4l2_fwnode_endpoint *vep)
412
+static int __v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
413
+ struct v4l2_fwnode_endpoint *vep)
193414 {
194
- u32 bus_type = 0;
415
+ u32 bus_type = V4L2_FWNODE_BUS_TYPE_GUESS;
416
+ enum v4l2_mbus_type mbus_type;
195417 int rval;
418
+
419
+ if (vep->bus_type == V4L2_MBUS_UNKNOWN) {
420
+ /* Zero fields from bus union to until the end */
421
+ memset(&vep->bus, 0,
422
+ sizeof(*vep) - offsetof(typeof(*vep), bus));
423
+ }
424
+
425
+ pr_debug("===== begin parsing endpoint %pfw\n", fwnode);
426
+
427
+ /*
428
+ * Zero the fwnode graph endpoint memory in case we don't end up parsing
429
+ * the endpoint.
430
+ */
431
+ memset(&vep->base, 0, sizeof(vep->base));
432
+
433
+ fwnode_property_read_u32(fwnode, "bus-type", &bus_type);
434
+ pr_debug("fwnode video bus type %s (%u), mbus type %s (%u)\n",
435
+ v4l2_fwnode_bus_type_to_string(bus_type), bus_type,
436
+ v4l2_fwnode_mbus_type_to_string(vep->bus_type),
437
+ vep->bus_type);
438
+ mbus_type = v4l2_fwnode_bus_type_to_mbus(bus_type);
439
+ if (mbus_type == V4L2_MBUS_INVALID) {
440
+ pr_debug("unsupported bus type %u\n", bus_type);
441
+ return -EINVAL;
442
+ }
443
+
444
+ if (vep->bus_type != V4L2_MBUS_UNKNOWN) {
445
+ if (mbus_type != V4L2_MBUS_UNKNOWN &&
446
+ vep->bus_type != mbus_type) {
447
+ pr_debug("expecting bus type %s\n",
448
+ v4l2_fwnode_mbus_type_to_string(vep->bus_type));
449
+ return -ENXIO;
450
+ }
451
+ } else {
452
+ vep->bus_type = mbus_type;
453
+ }
454
+
455
+ switch (vep->bus_type) {
456
+ case V4L2_MBUS_UNKNOWN:
457
+ rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep,
458
+ V4L2_MBUS_UNKNOWN);
459
+ if (rval)
460
+ return rval;
461
+
462
+ if (vep->bus_type == V4L2_MBUS_UNKNOWN)
463
+ v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep,
464
+ V4L2_MBUS_UNKNOWN);
465
+
466
+ pr_debug("assuming media bus type %s (%u)\n",
467
+ v4l2_fwnode_mbus_type_to_string(vep->bus_type),
468
+ vep->bus_type);
469
+
470
+ break;
471
+ case V4L2_MBUS_CCP2:
472
+ case V4L2_MBUS_CSI1:
473
+ v4l2_fwnode_endpoint_parse_csi1_bus(fwnode, vep, vep->bus_type);
474
+
475
+ break;
476
+ case V4L2_MBUS_CSI2_DPHY:
477
+ case V4L2_MBUS_CSI2_CPHY:
478
+ rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep,
479
+ vep->bus_type);
480
+ if (rval)
481
+ return rval;
482
+
483
+ break;
484
+ case V4L2_MBUS_PARALLEL:
485
+ case V4L2_MBUS_BT656:
486
+ v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep,
487
+ vep->bus_type);
488
+
489
+ break;
490
+ default:
491
+ pr_warn("unsupported bus type %u\n", mbus_type);
492
+ return -EINVAL;
493
+ }
196494
197495 fwnode_graph_parse_endpoint(fwnode, &vep->base);
198496
199
- /* Zero fields from bus_type to until the end */
200
- memset(&vep->bus_type, 0, sizeof(*vep) -
201
- offsetof(typeof(*vep), bus_type));
497
+ return 0;
498
+}
202499
203
- fwnode_property_read_u32(fwnode, "bus-type", &bus_type);
500
+int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
501
+ struct v4l2_fwnode_endpoint *vep)
502
+{
503
+ int ret;
204504
205
- switch (bus_type) {
206
- case V4L2_FWNODE_BUS_TYPE_GUESS:
207
- rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep);
208
- if (rval)
209
- return rval;
210
- /*
211
- * Parse the parallel video bus properties only if none
212
- * of the MIPI CSI-2 specific properties were found.
213
- */
214
- if (vep->bus.mipi_csi2.flags == 0)
215
- v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep);
505
+ ret = __v4l2_fwnode_endpoint_parse(fwnode, vep);
216506
217
- return 0;
218
- case V4L2_FWNODE_BUS_TYPE_CCP2:
219
- case V4L2_FWNODE_BUS_TYPE_CSI1:
220
- v4l2_fwnode_endpoint_parse_csi1_bus(fwnode, vep, bus_type);
507
+ pr_debug("===== end parsing endpoint %pfw\n", fwnode);
221508
222
- return 0;
223
- default:
224
- pr_warn("unsupported bus type %u\n", bus_type);
225
- return -EINVAL;
226
- }
509
+ return ret;
227510 }
228511 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_parse);
229512
....@@ -233,83 +516,85 @@
233516 return;
234517
235518 kfree(vep->link_frequencies);
236
- kfree(vep);
519
+ vep->link_frequencies = NULL;
237520 }
238521 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_free);
239522
240
-struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse(
241
- struct fwnode_handle *fwnode)
523
+int v4l2_fwnode_endpoint_alloc_parse(struct fwnode_handle *fwnode,
524
+ struct v4l2_fwnode_endpoint *vep)
242525 {
243
- struct v4l2_fwnode_endpoint *vep;
244526 int rval;
245527
246
- vep = kzalloc(sizeof(*vep), GFP_KERNEL);
247
- if (!vep)
248
- return ERR_PTR(-ENOMEM);
249
-
250
- rval = v4l2_fwnode_endpoint_parse(fwnode, vep);
528
+ rval = __v4l2_fwnode_endpoint_parse(fwnode, vep);
251529 if (rval < 0)
252
- goto out_err;
530
+ return rval;
253531
254
- rval = fwnode_property_read_u64_array(fwnode, "link-frequencies",
255
- NULL, 0);
532
+ rval = fwnode_property_count_u64(fwnode, "link-frequencies");
256533 if (rval > 0) {
534
+ unsigned int i;
535
+
257536 vep->link_frequencies =
258537 kmalloc_array(rval, sizeof(*vep->link_frequencies),
259538 GFP_KERNEL);
260
- if (!vep->link_frequencies) {
261
- rval = -ENOMEM;
262
- goto out_err;
263
- }
539
+ if (!vep->link_frequencies)
540
+ return -ENOMEM;
264541
265542 vep->nr_of_link_frequencies = rval;
266543
267
- rval = fwnode_property_read_u64_array(
268
- fwnode, "link-frequencies", vep->link_frequencies,
269
- vep->nr_of_link_frequencies);
270
- if (rval < 0)
271
- goto out_err;
544
+ rval = fwnode_property_read_u64_array(fwnode,
545
+ "link-frequencies",
546
+ vep->link_frequencies,
547
+ vep->nr_of_link_frequencies);
548
+ if (rval < 0) {
549
+ v4l2_fwnode_endpoint_free(vep);
550
+ return rval;
551
+ }
552
+
553
+ for (i = 0; i < vep->nr_of_link_frequencies; i++)
554
+ pr_debug("link-frequencies %u value %llu\n", i,
555
+ vep->link_frequencies[i]);
272556 }
273557
274
- return vep;
558
+ pr_debug("===== end parsing endpoint %pfw\n", fwnode);
275559
276
-out_err:
277
- v4l2_fwnode_endpoint_free(vep);
278
- return ERR_PTR(rval);
560
+ return 0;
279561 }
280562 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse);
281563
282
-int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode,
564
+int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode,
283565 struct v4l2_fwnode_link *link)
284566 {
285
- const char *port_prop = is_of_node(__fwnode) ? "reg" : "port";
286
- struct fwnode_handle *fwnode;
567
+ struct fwnode_endpoint fwep;
287568
288569 memset(link, 0, sizeof(*link));
289570
290
- fwnode = fwnode_get_parent(__fwnode);
291
- fwnode_property_read_u32(fwnode, port_prop, &link->local_port);
292
- fwnode = fwnode_get_next_parent(fwnode);
293
- if (is_of_node(fwnode) &&
294
- of_node_cmp(to_of_node(fwnode)->name, "ports") == 0)
295
- fwnode = fwnode_get_next_parent(fwnode);
296
- link->local_node = fwnode;
297
-
298
- fwnode = fwnode_graph_get_remote_endpoint(__fwnode);
299
- if (!fwnode) {
300
- fwnode_handle_put(fwnode);
571
+ fwnode_graph_parse_endpoint(fwnode, &fwep);
572
+ link->local_id = fwep.id;
573
+ link->local_port = fwep.port;
574
+ link->local_node = fwnode_graph_get_port_parent(fwnode);
575
+ if (!link->local_node)
301576 return -ENOLINK;
302
- }
303577
304
- fwnode = fwnode_get_parent(fwnode);
305
- fwnode_property_read_u32(fwnode, port_prop, &link->remote_port);
306
- fwnode = fwnode_get_next_parent(fwnode);
307
- if (is_of_node(fwnode) &&
308
- of_node_cmp(to_of_node(fwnode)->name, "ports") == 0)
309
- fwnode = fwnode_get_next_parent(fwnode);
310
- link->remote_node = fwnode;
578
+ fwnode = fwnode_graph_get_remote_endpoint(fwnode);
579
+ if (!fwnode)
580
+ goto err_put_local_node;
581
+
582
+ fwnode_graph_parse_endpoint(fwnode, &fwep);
583
+ link->remote_id = fwep.id;
584
+ link->remote_port = fwep.port;
585
+ link->remote_node = fwnode_graph_get_port_parent(fwnode);
586
+ if (!link->remote_node)
587
+ goto err_put_remote_endpoint;
311588
312589 return 0;
590
+
591
+err_put_remote_endpoint:
592
+ fwnode_handle_put(fwnode);
593
+
594
+err_put_local_node:
595
+ fwnode_handle_put(link->local_node);
596
+
597
+ return -ENOLINK;
313598 }
314599 EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_link);
315600
....@@ -320,43 +605,223 @@
320605 }
321606 EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
322607
323
-static int v4l2_async_notifier_realloc(struct v4l2_async_notifier *notifier,
324
- unsigned int max_subdevs)
608
+static const struct v4l2_fwnode_connector_conv {
609
+ enum v4l2_connector_type type;
610
+ const char *compatible;
611
+} connectors[] = {
612
+ {
613
+ .type = V4L2_CONN_COMPOSITE,
614
+ .compatible = "composite-video-connector",
615
+ }, {
616
+ .type = V4L2_CONN_SVIDEO,
617
+ .compatible = "svideo-connector",
618
+ },
619
+};
620
+
621
+static enum v4l2_connector_type
622
+v4l2_fwnode_string_to_connector_type(const char *con_str)
325623 {
326
- struct v4l2_async_subdev **subdevs;
624
+ unsigned int i;
327625
328
- if (max_subdevs <= notifier->max_subdevs)
329
- return 0;
626
+ for (i = 0; i < ARRAY_SIZE(connectors); i++)
627
+ if (!strcmp(con_str, connectors[i].compatible))
628
+ return connectors[i].type;
330629
331
- subdevs = kvmalloc_array(
332
- max_subdevs, sizeof(*notifier->subdevs),
333
- GFP_KERNEL | __GFP_ZERO);
334
- if (!subdevs)
335
- return -ENOMEM;
630
+ return V4L2_CONN_UNKNOWN;
631
+}
336632
337
- if (notifier->subdevs) {
338
- memcpy(subdevs, notifier->subdevs,
339
- sizeof(*subdevs) * notifier->num_subdevs);
633
+static void
634
+v4l2_fwnode_connector_parse_analog(struct fwnode_handle *fwnode,
635
+ struct v4l2_fwnode_connector *vc)
636
+{
637
+ u32 stds;
638
+ int ret;
340639
341
- kvfree(notifier->subdevs);
640
+ ret = fwnode_property_read_u32(fwnode, "sdtv-standards", &stds);
641
+
642
+ /* The property is optional. */
643
+ vc->connector.analog.sdtv_stds = ret ? V4L2_STD_ALL : stds;
644
+}
645
+
646
+void v4l2_fwnode_connector_free(struct v4l2_fwnode_connector *connector)
647
+{
648
+ struct v4l2_connector_link *link, *tmp;
649
+
650
+ if (IS_ERR_OR_NULL(connector) || connector->type == V4L2_CONN_UNKNOWN)
651
+ return;
652
+
653
+ list_for_each_entry_safe(link, tmp, &connector->links, head) {
654
+ v4l2_fwnode_put_link(&link->fwnode_link);
655
+ list_del(&link->head);
656
+ kfree(link);
342657 }
343658
344
- notifier->subdevs = subdevs;
345
- notifier->max_subdevs = max_subdevs;
659
+ kfree(connector->label);
660
+ connector->label = NULL;
661
+ connector->type = V4L2_CONN_UNKNOWN;
662
+}
663
+EXPORT_SYMBOL_GPL(v4l2_fwnode_connector_free);
664
+
665
+static enum v4l2_connector_type
666
+v4l2_fwnode_get_connector_type(struct fwnode_handle *fwnode)
667
+{
668
+ const char *type_name;
669
+ int err;
670
+
671
+ if (!fwnode)
672
+ return V4L2_CONN_UNKNOWN;
673
+
674
+ /* The connector-type is stored within the compatible string. */
675
+ err = fwnode_property_read_string(fwnode, "compatible", &type_name);
676
+ if (err)
677
+ return V4L2_CONN_UNKNOWN;
678
+
679
+ return v4l2_fwnode_string_to_connector_type(type_name);
680
+}
681
+
682
+int v4l2_fwnode_connector_parse(struct fwnode_handle *fwnode,
683
+ struct v4l2_fwnode_connector *connector)
684
+{
685
+ struct fwnode_handle *connector_node;
686
+ enum v4l2_connector_type connector_type;
687
+ const char *label;
688
+ int err;
689
+
690
+ if (!fwnode)
691
+ return -EINVAL;
692
+
693
+ memset(connector, 0, sizeof(*connector));
694
+
695
+ INIT_LIST_HEAD(&connector->links);
696
+
697
+ connector_node = fwnode_graph_get_port_parent(fwnode);
698
+ connector_type = v4l2_fwnode_get_connector_type(connector_node);
699
+ if (connector_type == V4L2_CONN_UNKNOWN) {
700
+ fwnode_handle_put(connector_node);
701
+ connector_node = fwnode_graph_get_remote_port_parent(fwnode);
702
+ connector_type = v4l2_fwnode_get_connector_type(connector_node);
703
+ }
704
+
705
+ if (connector_type == V4L2_CONN_UNKNOWN) {
706
+ pr_err("Unknown connector type\n");
707
+ err = -ENOTCONN;
708
+ goto out;
709
+ }
710
+
711
+ connector->type = connector_type;
712
+ connector->name = fwnode_get_name(connector_node);
713
+ err = fwnode_property_read_string(connector_node, "label", &label);
714
+ connector->label = err ? NULL : kstrdup_const(label, GFP_KERNEL);
715
+
716
+ /* Parse the connector specific properties. */
717
+ switch (connector->type) {
718
+ case V4L2_CONN_COMPOSITE:
719
+ case V4L2_CONN_SVIDEO:
720
+ v4l2_fwnode_connector_parse_analog(connector_node, connector);
721
+ break;
722
+ /* Avoid compiler warnings */
723
+ case V4L2_CONN_UNKNOWN:
724
+ break;
725
+ }
726
+
727
+out:
728
+ fwnode_handle_put(connector_node);
729
+
730
+ return err;
731
+}
732
+EXPORT_SYMBOL_GPL(v4l2_fwnode_connector_parse);
733
+
734
+int v4l2_fwnode_connector_add_link(struct fwnode_handle *fwnode,
735
+ struct v4l2_fwnode_connector *connector)
736
+{
737
+ struct fwnode_handle *connector_ep;
738
+ struct v4l2_connector_link *link;
739
+ int err;
740
+
741
+ if (!fwnode || !connector || connector->type == V4L2_CONN_UNKNOWN)
742
+ return -EINVAL;
743
+
744
+ connector_ep = fwnode_graph_get_remote_endpoint(fwnode);
745
+ if (!connector_ep)
746
+ return -ENOTCONN;
747
+
748
+ link = kzalloc(sizeof(*link), GFP_KERNEL);
749
+ if (!link) {
750
+ err = -ENOMEM;
751
+ goto err;
752
+ }
753
+
754
+ err = v4l2_fwnode_parse_link(connector_ep, &link->fwnode_link);
755
+ if (err)
756
+ goto err;
757
+
758
+ fwnode_handle_put(connector_ep);
759
+
760
+ list_add(&link->head, &connector->links);
761
+ connector->nr_of_links++;
762
+
763
+ return 0;
764
+
765
+err:
766
+ kfree(link);
767
+ fwnode_handle_put(connector_ep);
768
+
769
+ return err;
770
+}
771
+EXPORT_SYMBOL_GPL(v4l2_fwnode_connector_add_link);
772
+
773
+int v4l2_fwnode_device_parse(struct device *dev,
774
+ struct v4l2_fwnode_device_properties *props)
775
+{
776
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
777
+ u32 val;
778
+ int ret;
779
+
780
+ memset(props, 0, sizeof(*props));
781
+
782
+ props->orientation = V4L2_FWNODE_PROPERTY_UNSET;
783
+ ret = fwnode_property_read_u32(fwnode, "orientation", &val);
784
+ if (!ret) {
785
+ switch (val) {
786
+ case V4L2_FWNODE_ORIENTATION_FRONT:
787
+ case V4L2_FWNODE_ORIENTATION_BACK:
788
+ case V4L2_FWNODE_ORIENTATION_EXTERNAL:
789
+ break;
790
+ default:
791
+ dev_warn(dev, "Unsupported device orientation: %u\n", val);
792
+ return -EINVAL;
793
+ }
794
+
795
+ props->orientation = val;
796
+ dev_dbg(dev, "device orientation: %u\n", val);
797
+ }
798
+
799
+ props->rotation = V4L2_FWNODE_PROPERTY_UNSET;
800
+ ret = fwnode_property_read_u32(fwnode, "rotation", &val);
801
+ if (!ret) {
802
+ if (val >= 360) {
803
+ dev_warn(dev, "Unsupported device rotation: %u\n", val);
804
+ return -EINVAL;
805
+ }
806
+
807
+ props->rotation = val;
808
+ dev_dbg(dev, "device rotation: %u\n", val);
809
+ }
346810
347811 return 0;
348812 }
813
+EXPORT_SYMBOL_GPL(v4l2_fwnode_device_parse);
349814
350
-static int v4l2_async_notifier_fwnode_parse_endpoint(
351
- struct device *dev, struct v4l2_async_notifier *notifier,
352
- struct fwnode_handle *endpoint, unsigned int asd_struct_size,
353
- int (*parse_endpoint)(struct device *dev,
354
- struct v4l2_fwnode_endpoint *vep,
355
- struct v4l2_async_subdev *asd))
815
+static int
816
+v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
817
+ struct v4l2_async_notifier *notifier,
818
+ struct fwnode_handle *endpoint,
819
+ unsigned int asd_struct_size,
820
+ parse_endpoint_func parse_endpoint)
356821 {
822
+ struct v4l2_fwnode_endpoint vep = { .bus_type = 0 };
357823 struct v4l2_async_subdev *asd;
358
- struct v4l2_fwnode_endpoint *vep;
359
- int ret = 0;
824
+ int ret;
360825
361826 asd = kzalloc(asd_struct_size, GFP_KERNEL);
362827 if (!asd)
....@@ -366,33 +831,37 @@
366831 asd->match.fwnode =
367832 fwnode_graph_get_remote_port_parent(endpoint);
368833 if (!asd->match.fwnode) {
369
- dev_warn(dev, "bad remote port parent\n");
370
- ret = -EINVAL;
834
+ dev_dbg(dev, "no remote endpoint found\n");
835
+ ret = -ENOTCONN;
371836 goto out_err;
372837 }
373838
374
- vep = v4l2_fwnode_endpoint_alloc_parse(endpoint);
375
- if (IS_ERR(vep)) {
376
- ret = PTR_ERR(vep);
839
+ ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &vep);
840
+ if (ret) {
377841 dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n",
378842 ret);
379843 goto out_err;
380844 }
381845
382
- ret = parse_endpoint ? parse_endpoint(dev, vep, asd) : 0;
846
+ ret = parse_endpoint ? parse_endpoint(dev, &vep, asd) : 0;
383847 if (ret == -ENOTCONN)
384
- dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep->base.port,
385
- vep->base.id);
848
+ dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep.base.port,
849
+ vep.base.id);
386850 else if (ret < 0)
387851 dev_warn(dev,
388852 "driver could not parse port@%u/endpoint@%u (%d)\n",
389
- vep->base.port, vep->base.id, ret);
390
- v4l2_fwnode_endpoint_free(vep);
853
+ vep.base.port, vep.base.id, ret);
854
+ v4l2_fwnode_endpoint_free(&vep);
391855 if (ret < 0)
392856 goto out_err;
393857
394
- notifier->subdevs[notifier->num_subdevs] = asd;
395
- notifier->num_subdevs++;
858
+ ret = v4l2_async_notifier_add_subdev(notifier, asd);
859
+ if (ret < 0) {
860
+ /* not an error if asd already exists */
861
+ if (ret == -EEXIST)
862
+ ret = 0;
863
+ goto out_err;
864
+ }
396865
397866 return 0;
398867
....@@ -403,56 +872,21 @@
403872 return ret == -ENOTCONN ? 0 : ret;
404873 }
405874
406
-static int __v4l2_async_notifier_parse_fwnode_endpoints(
407
- struct device *dev, struct v4l2_async_notifier *notifier,
408
- size_t asd_struct_size, unsigned int port, bool has_port,
409
- int (*parse_endpoint)(struct device *dev,
410
- struct v4l2_fwnode_endpoint *vep,
411
- struct v4l2_async_subdev *asd))
875
+static int
876
+__v4l2_async_notifier_parse_fwnode_ep(struct device *dev,
877
+ struct v4l2_async_notifier *notifier,
878
+ size_t asd_struct_size,
879
+ unsigned int port,
880
+ bool has_port,
881
+ parse_endpoint_func parse_endpoint)
412882 {
413883 struct fwnode_handle *fwnode;
414
- unsigned int max_subdevs = notifier->max_subdevs;
415
- int ret;
884
+ int ret = 0;
416885
417886 if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
418887 return -EINVAL;
419888
420
- for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
421
- dev_fwnode(dev), fwnode)); ) {
422
- struct fwnode_handle *dev_fwnode;
423
- bool is_available;
424
-
425
- dev_fwnode = fwnode_graph_get_port_parent(fwnode);
426
- is_available = fwnode_device_is_available(dev_fwnode);
427
- fwnode_handle_put(dev_fwnode);
428
- if (!is_available)
429
- continue;
430
-
431
- if (has_port) {
432
- struct fwnode_endpoint ep;
433
-
434
- ret = fwnode_graph_parse_endpoint(fwnode, &ep);
435
- if (ret) {
436
- fwnode_handle_put(fwnode);
437
- return ret;
438
- }
439
-
440
- if (ep.port != port)
441
- continue;
442
- }
443
- max_subdevs++;
444
- }
445
-
446
- /* No subdevs to add? Return here. */
447
- if (max_subdevs == notifier->max_subdevs)
448
- return 0;
449
-
450
- ret = v4l2_async_notifier_realloc(notifier, max_subdevs);
451
- if (ret)
452
- return ret;
453
-
454
- for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
455
- dev_fwnode(dev), fwnode)); ) {
889
+ fwnode_graph_for_each_endpoint(dev_fwnode(dev), fwnode) {
456890 struct fwnode_handle *dev_fwnode;
457891 bool is_available;
458892
....@@ -473,13 +907,11 @@
473907 continue;
474908 }
475909
476
- if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
477
- ret = -EINVAL;
478
- break;
479
- }
480
-
481
- ret = v4l2_async_notifier_fwnode_parse_endpoint(
482
- dev, notifier, fwnode, asd_struct_size, parse_endpoint);
910
+ ret = v4l2_async_notifier_fwnode_parse_endpoint(dev,
911
+ notifier,
912
+ fwnode,
913
+ asd_struct_size,
914
+ parse_endpoint);
483915 if (ret < 0)
484916 break;
485917 }
....@@ -489,27 +921,29 @@
489921 return ret;
490922 }
491923
492
-int v4l2_async_notifier_parse_fwnode_endpoints(
493
- struct device *dev, struct v4l2_async_notifier *notifier,
494
- size_t asd_struct_size,
495
- int (*parse_endpoint)(struct device *dev,
496
- struct v4l2_fwnode_endpoint *vep,
497
- struct v4l2_async_subdev *asd))
924
+int
925
+v4l2_async_notifier_parse_fwnode_endpoints(struct device *dev,
926
+ struct v4l2_async_notifier *notifier,
927
+ size_t asd_struct_size,
928
+ parse_endpoint_func parse_endpoint)
498929 {
499
- return __v4l2_async_notifier_parse_fwnode_endpoints(
500
- dev, notifier, asd_struct_size, 0, false, parse_endpoint);
930
+ return __v4l2_async_notifier_parse_fwnode_ep(dev, notifier,
931
+ asd_struct_size, 0,
932
+ false, parse_endpoint);
501933 }
502934 EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints);
503935
504
-int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
505
- struct device *dev, struct v4l2_async_notifier *notifier,
506
- size_t asd_struct_size, unsigned int port,
507
- int (*parse_endpoint)(struct device *dev,
508
- struct v4l2_fwnode_endpoint *vep,
509
- struct v4l2_async_subdev *asd))
936
+int
937
+v4l2_async_notifier_parse_fwnode_endpoints_by_port(struct device *dev,
938
+ struct v4l2_async_notifier *notifier,
939
+ size_t asd_struct_size,
940
+ unsigned int port,
941
+ parse_endpoint_func parse_endpoint)
510942 {
511
- return __v4l2_async_notifier_parse_fwnode_endpoints(
512
- dev, notifier, asd_struct_size, port, true, parse_endpoint);
943
+ return __v4l2_async_notifier_parse_fwnode_ep(dev, notifier,
944
+ asd_struct_size,
945
+ port, true,
946
+ parse_endpoint);
513947 }
514948 EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port);
515949
....@@ -524,17 +958,18 @@
524958 * -ENOMEM if memory allocation failed
525959 * -EINVAL if property parsing failed
526960 */
527
-static int v4l2_fwnode_reference_parse(
528
- struct device *dev, struct v4l2_async_notifier *notifier,
529
- const char *prop)
961
+static int v4l2_fwnode_reference_parse(struct device *dev,
962
+ struct v4l2_async_notifier *notifier,
963
+ const char *prop)
530964 {
531965 struct fwnode_reference_args args;
532966 unsigned int index;
533967 int ret;
534968
535969 for (index = 0;
536
- !(ret = fwnode_property_get_reference_args(
537
- dev_fwnode(dev), prop, NULL, 0, index, &args));
970
+ !(ret = fwnode_property_get_reference_args(dev_fwnode(dev),
971
+ prop, NULL, 0,
972
+ index, &args));
538973 index++)
539974 fwnode_handle_put(args.fwnode);
540975
....@@ -548,38 +983,26 @@
548983 if (ret != -ENOENT && ret != -ENODATA)
549984 return ret;
550985
551
- ret = v4l2_async_notifier_realloc(notifier,
552
- notifier->num_subdevs + index);
553
- if (ret)
554
- return ret;
555
-
556
- for (index = 0; !fwnode_property_get_reference_args(
557
- dev_fwnode(dev), prop, NULL, 0, index, &args);
986
+ for (index = 0;
987
+ !fwnode_property_get_reference_args(dev_fwnode(dev), prop, NULL,
988
+ 0, index, &args);
558989 index++) {
559990 struct v4l2_async_subdev *asd;
560991
561
- if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
562
- ret = -EINVAL;
563
- goto error;
564
- }
992
+ asd = v4l2_async_notifier_add_fwnode_subdev(notifier,
993
+ args.fwnode,
994
+ sizeof(*asd));
995
+ fwnode_handle_put(args.fwnode);
996
+ if (IS_ERR(asd)) {
997
+ /* not an error if asd already exists */
998
+ if (PTR_ERR(asd) == -EEXIST)
999
+ continue;
5651000
566
- asd = kzalloc(sizeof(*asd), GFP_KERNEL);
567
- if (!asd) {
568
- ret = -ENOMEM;
569
- goto error;
1001
+ return PTR_ERR(asd);
5701002 }
571
-
572
- notifier->subdevs[notifier->num_subdevs] = asd;
573
- asd->match.fwnode = args.fwnode;
574
- asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
575
- notifier->num_subdevs++;
5761003 }
5771004
5781005 return 0;
579
-
580
-error:
581
- fwnode_handle_put(args.fwnode);
582
- return ret;
5831006 }
5841007
5851008 /*
....@@ -600,7 +1023,7 @@
6001023 * root node and the value of that property matching with the integer argument
6011024 * of the reference, at the same index.
6021025 *
603
- * The child fwnode reched at the end of the iteration is then returned to the
1026
+ * The child fwnode reached at the end of the iteration is then returned to the
6041027 * caller.
6051028 *
6061029 * The core reason for this is that you cannot refer to just any node in ACPI.
....@@ -611,7 +1034,10 @@
6111034 * underneath the fwnode identified by the previous tuple, etc. until you
6121035 * reached the fwnode you need.
6131036 *
614
- * An example with a graph, as defined in Documentation/acpi/dsd/graph.txt:
1037
+ * THIS EXAMPLE EXISTS MERELY TO DOCUMENT THIS FUNCTION. DO NOT USE IT AS A
1038
+ * REFERENCE IN HOW ACPI TABLES SHOULD BE WRITTEN!! See documentation under
1039
+ * Documentation/firmware-guide/acpi/dsd/ instead and especially graph.txt,
1040
+ * data-node-references.txt and leds.txt .
6151041 *
6161042 * Scope (\_SB.PCI0.I2C2)
6171043 * {
....@@ -738,9 +1164,12 @@
7381164 * -EINVAL if property parsing otherwise failed
7391165 * -ENOMEM if memory allocation failed
7401166 */
741
-static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop(
742
- struct fwnode_handle *fwnode, const char *prop, unsigned int index,
743
- const char * const *props, unsigned int nprops)
1167
+static struct fwnode_handle *
1168
+v4l2_fwnode_reference_get_int_prop(struct fwnode_handle *fwnode,
1169
+ const char *prop,
1170
+ unsigned int index,
1171
+ const char * const *props,
1172
+ unsigned int nprops)
7441173 {
7451174 struct fwnode_reference_args fwnode_args;
7461175 u64 *args = fwnode_args.args;
....@@ -792,6 +1221,12 @@
7921221 return fwnode;
7931222 }
7941223
1224
+struct v4l2_fwnode_int_props {
1225
+ const char *name;
1226
+ const char * const *props;
1227
+ unsigned int nprops;
1228
+};
1229
+
7951230 /*
7961231 * v4l2_fwnode_reference_parse_int_props - parse references for async
7971232 * sub-devices
....@@ -815,13 +1250,17 @@
8151250 * -EINVAL if property parsing otherwisefailed
8161251 * -ENOMEM if memory allocation failed
8171252 */
818
-static int v4l2_fwnode_reference_parse_int_props(
819
- struct device *dev, struct v4l2_async_notifier *notifier,
820
- const char *prop, const char * const *props, unsigned int nprops)
1253
+static int
1254
+v4l2_fwnode_reference_parse_int_props(struct device *dev,
1255
+ struct v4l2_async_notifier *notifier,
1256
+ const struct v4l2_fwnode_int_props *p)
8211257 {
8221258 struct fwnode_handle *fwnode;
8231259 unsigned int index;
8241260 int ret;
1261
+ const char *prop = p->name;
1262
+ const char * const *props = p->props;
1263
+ unsigned int nprops = p->nprops;
8251264
8261265 index = 0;
8271266 do {
....@@ -843,52 +1282,37 @@
8431282 index++;
8441283 } while (1);
8451284
846
- ret = v4l2_async_notifier_realloc(notifier,
847
- notifier->num_subdevs + index);
848
- if (ret)
849
- return -ENOMEM;
850
-
851
- for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(
852
- dev_fwnode(dev), prop, index, props,
853
- nprops))); index++) {
1285
+ for (index = 0;
1286
+ !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(dev_fwnode(dev),
1287
+ prop, index,
1288
+ props,
1289
+ nprops)));
1290
+ index++) {
8541291 struct v4l2_async_subdev *asd;
8551292
856
- if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
857
- ret = -EINVAL;
858
- goto error;
859
- }
1293
+ asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode,
1294
+ sizeof(*asd));
1295
+ fwnode_handle_put(fwnode);
1296
+ if (IS_ERR(asd)) {
1297
+ ret = PTR_ERR(asd);
1298
+ /* not an error if asd already exists */
1299
+ if (ret == -EEXIST)
1300
+ continue;
8601301
861
- asd = kzalloc(sizeof(struct v4l2_async_subdev), GFP_KERNEL);
862
- if (!asd) {
863
- ret = -ENOMEM;
864
- goto error;
1302
+ return PTR_ERR(asd);
8651303 }
866
-
867
- notifier->subdevs[notifier->num_subdevs] = asd;
868
- asd->match.fwnode = fwnode;
869
- asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
870
- notifier->num_subdevs++;
8711304 }
8721305
873
- return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
874
-
875
-error:
876
- fwnode_handle_put(fwnode);
877
- return ret;
1306
+ return !fwnode || PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
8781307 }
8791308
880
-int v4l2_async_notifier_parse_fwnode_sensor_common(
881
- struct device *dev, struct v4l2_async_notifier *notifier)
1309
+int v4l2_async_notifier_parse_fwnode_sensor_common(struct device *dev,
1310
+ struct v4l2_async_notifier *notifier)
8821311 {
8831312 static const char * const led_props[] = { "led" };
884
- static const struct {
885
- const char *name;
886
- const char * const *props;
887
- unsigned int nprops;
888
- } props[] = {
1313
+ static const struct v4l2_fwnode_int_props props[] = {
8891314 { "flash-leds", led_props, ARRAY_SIZE(led_props) },
8901315 { "lens-focus", NULL, 0 },
891
- { "ir-cut", NULL, 0 },
8921316 };
8931317 unsigned int i;
8941318
....@@ -896,12 +1320,12 @@
8961320 int ret;
8971321
8981322 if (props[i].props && is_acpi_node(dev_fwnode(dev)))
899
- ret = v4l2_fwnode_reference_parse_int_props(
900
- dev, notifier, props[i].name,
901
- props[i].props, props[i].nprops);
1323
+ ret = v4l2_fwnode_reference_parse_int_props(dev,
1324
+ notifier,
1325
+ &props[i]);
9021326 else
903
- ret = v4l2_fwnode_reference_parse(
904
- dev, notifier, props[i].name);
1327
+ ret = v4l2_fwnode_reference_parse(dev, notifier,
1328
+ props[i].name);
9051329 if (ret && ret != -ENOENT) {
9061330 dev_warn(dev, "parsing property \"%s\" failed (%d)\n",
9071331 props[i].name, ret);
....@@ -925,6 +1349,8 @@
9251349 if (!notifier)
9261350 return -ENOMEM;
9271351
1352
+ v4l2_async_notifier_init(notifier);
1353
+
9281354 ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev,
9291355 notifier);
9301356 if (ret < 0)