hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/v4l2-core/v4l2-subdev.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * V4L2 sub-device
34 *
....@@ -5,48 +6,42 @@
56 *
67 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
78 * Sakari Ailus <sakari.ailus@iki.fi>
8
- *
9
- * This program is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License version 2 as
11
- * published by the Free Software Foundation.
12
- *
13
- * This program is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU General Public License for more details.
179 */
1810
1911 #include <linux/ioctl.h>
2012 #include <linux/mm.h>
13
+#include <linux/module.h>
2114 #include <linux/slab.h>
2215 #include <linux/types.h>
2316 #include <linux/videodev2.h>
2417 #include <linux/export.h>
18
+#include <linux/version.h>
2519
2620 #include <media/v4l2-ctrls.h>
2721 #include <media/v4l2-device.h>
2822 #include <media/v4l2-ioctl.h>
2923 #include <media/v4l2-fh.h>
3024 #include <media/v4l2-event.h>
25
+#ifndef __GENKSYMS__
26
+#include <trace/hooks/v4l2core.h>
27
+#endif
3128
29
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
3230 static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
3331 {
34
-#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
3532 if (sd->entity.num_pads) {
3633 fh->pad = v4l2_subdev_alloc_pad_config(sd);
3734 if (fh->pad == NULL)
3835 return -ENOMEM;
3936 }
40
-#endif
37
+
4138 return 0;
4239 }
4340
4441 static void subdev_fh_free(struct v4l2_subdev_fh *fh)
4542 {
46
-#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
4743 v4l2_subdev_free_pad_config(fh->pad);
4844 fh->pad = NULL;
49
-#endif
5045 }
5146
5247 static int subdev_open(struct file *file)
....@@ -54,9 +49,6 @@
5449 struct video_device *vdev = video_devdata(file);
5550 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
5651 struct v4l2_subdev_fh *subdev_fh;
57
-#if defined(CONFIG_MEDIA_CONTROLLER)
58
- struct media_entity *entity = NULL;
59
-#endif
6052 int ret;
6153
6254 subdev_fh = kzalloc(sizeof(*subdev_fh), GFP_KERNEL);
....@@ -73,12 +65,15 @@
7365 v4l2_fh_add(&subdev_fh->vfh);
7466 file->private_data = &subdev_fh->vfh;
7567 #if defined(CONFIG_MEDIA_CONTROLLER)
76
- if (sd->v4l2_dev->mdev) {
77
- entity = media_entity_get(&sd->entity);
78
- if (!entity) {
68
+ if (sd->v4l2_dev->mdev && sd->entity.graph_obj.mdev->dev) {
69
+ struct module *owner;
70
+
71
+ owner = sd->entity.graph_obj.mdev->dev->driver->owner;
72
+ if (!try_module_get(owner)) {
7973 ret = -EBUSY;
8074 goto err;
8175 }
76
+ subdev_fh->owner = owner;
8277 }
8378 #endif
8479
....@@ -91,9 +86,7 @@
9186 return 0;
9287
9388 err:
94
-#if defined(CONFIG_MEDIA_CONTROLLER)
95
- media_entity_put(entity);
96
-#endif
89
+ module_put(subdev_fh->owner);
9790 v4l2_fh_del(&subdev_fh->vfh);
9891 v4l2_fh_exit(&subdev_fh->vfh);
9992 subdev_fh_free(subdev_fh);
....@@ -111,10 +104,7 @@
111104
112105 if (sd->internal_ops && sd->internal_ops->close)
113106 sd->internal_ops->close(sd, subdev_fh);
114
-#if defined(CONFIG_MEDIA_CONTROLLER)
115
- if (sd->v4l2_dev->mdev)
116
- media_entity_put(&sd->entity);
117
-#endif
107
+ module_put(subdev_fh->owner);
118108 v4l2_fh_del(vfh);
119109 v4l2_fh_exit(vfh);
120110 subdev_fh_free(subdev_fh);
....@@ -123,69 +113,267 @@
123113
124114 return 0;
125115 }
116
+#else /* CONFIG_VIDEO_V4L2_SUBDEV_API */
117
+static int subdev_open(struct file *file)
118
+{
119
+ return -ENODEV;
120
+}
126121
127
-#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
128
-static int check_format(struct v4l2_subdev *sd,
122
+static int subdev_close(struct file *file)
123
+{
124
+ return -ENODEV;
125
+}
126
+#endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
127
+
128
+static inline int check_which(u32 which)
129
+{
130
+ if (which != V4L2_SUBDEV_FORMAT_TRY &&
131
+ which != V4L2_SUBDEV_FORMAT_ACTIVE)
132
+ return -EINVAL;
133
+
134
+ return 0;
135
+}
136
+
137
+static inline int check_pad(struct v4l2_subdev *sd, u32 pad)
138
+{
139
+#if defined(CONFIG_MEDIA_CONTROLLER)
140
+ if (sd->entity.num_pads) {
141
+ if (pad >= sd->entity.num_pads)
142
+ return -EINVAL;
143
+ return 0;
144
+ }
145
+#endif
146
+ /* allow pad 0 on subdevices not registered as media entities */
147
+ if (pad > 0)
148
+ return -EINVAL;
149
+ return 0;
150
+}
151
+
152
+static int check_cfg(u32 which, struct v4l2_subdev_pad_config *cfg)
153
+{
154
+ if (which == V4L2_SUBDEV_FORMAT_TRY && !cfg)
155
+ return -EINVAL;
156
+
157
+ return 0;
158
+}
159
+
160
+static inline int check_format(struct v4l2_subdev *sd,
161
+ struct v4l2_subdev_pad_config *cfg,
162
+ struct v4l2_subdev_format *format)
163
+{
164
+ if (!format)
165
+ return -EINVAL;
166
+
167
+ return check_which(format->which) ? : check_pad(sd, format->pad) ? :
168
+ check_cfg(format->which, cfg);
169
+}
170
+
171
+static int call_get_fmt(struct v4l2_subdev *sd,
172
+ struct v4l2_subdev_pad_config *cfg,
129173 struct v4l2_subdev_format *format)
130174 {
131
- if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
132
- format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
133
- return -EINVAL;
134
-
135
- if (format->pad >= sd->entity.num_pads)
136
- return -EINVAL;
137
-
138
- return 0;
175
+ return check_format(sd, cfg, format) ? :
176
+ sd->ops->pad->get_fmt(sd, cfg, format);
139177 }
140178
141
-static int check_crop(struct v4l2_subdev *sd, struct v4l2_subdev_crop *crop)
179
+static int call_set_fmt(struct v4l2_subdev *sd,
180
+ struct v4l2_subdev_pad_config *cfg,
181
+ struct v4l2_subdev_format *format)
142182 {
143
- if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
144
- crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
145
- return -EINVAL;
146
-
147
- if (crop->pad >= sd->entity.num_pads)
148
- return -EINVAL;
149
-
150
- return 0;
183
+ return check_format(sd, cfg, format) ? :
184
+ sd->ops->pad->set_fmt(sd, cfg, format);
151185 }
152186
153
-static int check_selection(struct v4l2_subdev *sd,
154
- struct v4l2_subdev_selection *sel)
187
+static int call_enum_mbus_code(struct v4l2_subdev *sd,
188
+ struct v4l2_subdev_pad_config *cfg,
189
+ struct v4l2_subdev_mbus_code_enum *code)
155190 {
156
- if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
157
- sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
191
+ if (!code)
158192 return -EINVAL;
159193
160
- if (sel->pad >= sd->entity.num_pads)
161
- return -EINVAL;
162
-
163
- return 0;
194
+ return check_which(code->which) ? : check_pad(sd, code->pad) ? :
195
+ check_cfg(code->which, cfg) ? :
196
+ sd->ops->pad->enum_mbus_code(sd, cfg, code);
164197 }
165198
166
-static int check_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
199
+static int call_enum_frame_size(struct v4l2_subdev *sd,
200
+ struct v4l2_subdev_pad_config *cfg,
201
+ struct v4l2_subdev_frame_size_enum *fse)
167202 {
168
- if (edid->pad >= sd->entity.num_pads)
203
+ if (!fse)
204
+ return -EINVAL;
205
+
206
+ return check_which(fse->which) ? : check_pad(sd, fse->pad) ? :
207
+ check_cfg(fse->which, cfg) ? :
208
+ sd->ops->pad->enum_frame_size(sd, cfg, fse);
209
+}
210
+
211
+static inline int check_frame_interval(struct v4l2_subdev *sd,
212
+ struct v4l2_subdev_frame_interval *fi)
213
+{
214
+ if (!fi)
215
+ return -EINVAL;
216
+
217
+ return check_pad(sd, fi->pad);
218
+}
219
+
220
+static int call_g_frame_interval(struct v4l2_subdev *sd,
221
+ struct v4l2_subdev_frame_interval *fi)
222
+{
223
+ return check_frame_interval(sd, fi) ? :
224
+ sd->ops->video->g_frame_interval(sd, fi);
225
+}
226
+
227
+static int call_s_frame_interval(struct v4l2_subdev *sd,
228
+ struct v4l2_subdev_frame_interval *fi)
229
+{
230
+ return check_frame_interval(sd, fi) ? :
231
+ sd->ops->video->s_frame_interval(sd, fi);
232
+}
233
+
234
+static int call_enum_frame_interval(struct v4l2_subdev *sd,
235
+ struct v4l2_subdev_pad_config *cfg,
236
+ struct v4l2_subdev_frame_interval_enum *fie)
237
+{
238
+ if (!fie)
239
+ return -EINVAL;
240
+
241
+ return check_which(fie->which) ? : check_pad(sd, fie->pad) ? :
242
+ check_cfg(fie->which, cfg) ? :
243
+ sd->ops->pad->enum_frame_interval(sd, cfg, fie);
244
+}
245
+
246
+static inline int check_selection(struct v4l2_subdev *sd,
247
+ struct v4l2_subdev_pad_config *cfg,
248
+ struct v4l2_subdev_selection *sel)
249
+{
250
+ if (!sel)
251
+ return -EINVAL;
252
+
253
+ return check_which(sel->which) ? : check_pad(sd, sel->pad) ? :
254
+ check_cfg(sel->which, cfg);
255
+}
256
+
257
+static int call_get_selection(struct v4l2_subdev *sd,
258
+ struct v4l2_subdev_pad_config *cfg,
259
+ struct v4l2_subdev_selection *sel)
260
+{
261
+ return check_selection(sd, cfg, sel) ? :
262
+ sd->ops->pad->get_selection(sd, cfg, sel);
263
+}
264
+
265
+static int call_set_selection(struct v4l2_subdev *sd,
266
+ struct v4l2_subdev_pad_config *cfg,
267
+ struct v4l2_subdev_selection *sel)
268
+{
269
+ return check_selection(sd, cfg, sel) ? :
270
+ sd->ops->pad->set_selection(sd, cfg, sel);
271
+}
272
+
273
+static inline int check_edid(struct v4l2_subdev *sd,
274
+ struct v4l2_subdev_edid *edid)
275
+{
276
+ if (!edid)
169277 return -EINVAL;
170278
171279 if (edid->blocks && edid->edid == NULL)
172280 return -EINVAL;
173281
174
- return 0;
282
+ return check_pad(sd, edid->pad);
175283 }
176
-#endif
177284
285
+static int call_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
286
+{
287
+ return check_edid(sd, edid) ? : sd->ops->pad->get_edid(sd, edid);
288
+}
289
+
290
+static int call_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
291
+{
292
+ return check_edid(sd, edid) ? : sd->ops->pad->set_edid(sd, edid);
293
+}
294
+
295
+static int call_dv_timings_cap(struct v4l2_subdev *sd,
296
+ struct v4l2_dv_timings_cap *cap)
297
+{
298
+ if (!cap)
299
+ return -EINVAL;
300
+
301
+ return check_pad(sd, cap->pad) ? :
302
+ sd->ops->pad->dv_timings_cap(sd, cap);
303
+}
304
+
305
+static int call_enum_dv_timings(struct v4l2_subdev *sd,
306
+ struct v4l2_enum_dv_timings *dvt)
307
+{
308
+ if (!dvt)
309
+ return -EINVAL;
310
+
311
+ return check_pad(sd, dvt->pad) ? :
312
+ sd->ops->pad->enum_dv_timings(sd, dvt);
313
+}
314
+
315
+static int call_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
316
+ struct v4l2_mbus_config *config)
317
+{
318
+ return check_pad(sd, pad) ? :
319
+ sd->ops->pad->get_mbus_config(sd, pad, config);
320
+}
321
+
322
+static int call_set_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
323
+ struct v4l2_mbus_config *config)
324
+{
325
+ return check_pad(sd, pad) ? :
326
+ sd->ops->pad->get_mbus_config(sd, pad, config);
327
+}
328
+
329
+static const struct v4l2_subdev_pad_ops v4l2_subdev_call_pad_wrappers = {
330
+ .get_fmt = call_get_fmt,
331
+ .set_fmt = call_set_fmt,
332
+ .enum_mbus_code = call_enum_mbus_code,
333
+ .enum_frame_size = call_enum_frame_size,
334
+ .enum_frame_interval = call_enum_frame_interval,
335
+ .get_selection = call_get_selection,
336
+ .set_selection = call_set_selection,
337
+ .get_edid = call_get_edid,
338
+ .set_edid = call_set_edid,
339
+ .dv_timings_cap = call_dv_timings_cap,
340
+ .enum_dv_timings = call_enum_dv_timings,
341
+ .get_mbus_config = call_get_mbus_config,
342
+ .set_mbus_config = call_set_mbus_config,
343
+};
344
+
345
+static const struct v4l2_subdev_video_ops v4l2_subdev_call_video_wrappers = {
346
+ .g_frame_interval = call_g_frame_interval,
347
+ .s_frame_interval = call_s_frame_interval,
348
+};
349
+
350
+const struct v4l2_subdev_ops v4l2_subdev_call_wrappers = {
351
+ .pad = &v4l2_subdev_call_pad_wrappers,
352
+ .video = &v4l2_subdev_call_video_wrappers,
353
+};
354
+EXPORT_SYMBOL(v4l2_subdev_call_wrappers);
355
+
356
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
178357 static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
179358 {
180359 struct video_device *vdev = video_devdata(file);
181360 struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
182361 struct v4l2_fh *vfh = file->private_data;
183
-#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
184362 struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
363
+ bool ro_subdev = test_bit(V4L2_FL_SUBDEV_RO_DEVNODE, &vdev->flags);
185364 int rval;
186
-#endif
187365
188366 switch (cmd) {
367
+ case VIDIOC_SUBDEV_QUERYCAP: {
368
+ struct v4l2_subdev_capability *cap = arg;
369
+
370
+ memset(cap->reserved, 0, sizeof(cap->reserved));
371
+ cap->version = LINUX_VERSION_CODE;
372
+ cap->capabilities = ro_subdev ? V4L2_SUBDEV_CAP_RO_SUBDEV : 0;
373
+
374
+ return 0;
375
+ }
376
+
189377 case VIDIOC_QUERYCTRL:
190378 /*
191379 * TODO: this really should be folded into v4l2_queryctrl (this
....@@ -222,17 +410,20 @@
222410 case VIDIOC_G_EXT_CTRLS:
223411 if (!vfh->ctrl_handler)
224412 return -ENOTTY;
225
- return v4l2_g_ext_ctrls(vfh->ctrl_handler, arg);
413
+ return v4l2_g_ext_ctrls(vfh->ctrl_handler,
414
+ vdev, sd->v4l2_dev->mdev, arg);
226415
227416 case VIDIOC_S_EXT_CTRLS:
228417 if (!vfh->ctrl_handler)
229418 return -ENOTTY;
230
- return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, arg);
419
+ return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler,
420
+ vdev, sd->v4l2_dev->mdev, arg);
231421
232422 case VIDIOC_TRY_EXT_CTRLS:
233423 if (!vfh->ctrl_handler)
234424 return -ENOTTY;
235
- return v4l2_try_ext_ctrls(vfh->ctrl_handler, arg);
425
+ return v4l2_try_ext_ctrls(vfh->ctrl_handler,
426
+ vdev, sd->v4l2_dev->mdev, arg);
236427
237428 case VIDIOC_DQEVENT:
238429 if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
....@@ -273,7 +464,7 @@
273464 p->flags |= V4L2_CHIP_FL_WRITABLE;
274465 if (sd->ops->core && sd->ops->core->g_register)
275466 p->flags |= V4L2_CHIP_FL_READABLE;
276
- strlcpy(p->name, sd->name, sizeof(p->name));
467
+ strscpy(p->name, sd->name, sizeof(p->name));
277468 return 0;
278469 }
279470 #endif
....@@ -289,13 +480,8 @@
289480 return ret;
290481 }
291482
292
-#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
293483 case VIDIOC_SUBDEV_G_FMT: {
294484 struct v4l2_subdev_format *format = arg;
295
-
296
- rval = check_format(sd, format);
297
- if (rval)
298
- return rval;
299485
300486 memset(format->reserved, 0, sizeof(format->reserved));
301487 memset(format->format.reserved, 0, sizeof(format->format.reserved));
....@@ -304,10 +490,17 @@
304490
305491 case VIDIOC_SUBDEV_S_FMT: {
306492 struct v4l2_subdev_format *format = arg;
493
+ int ret = 0;
307494
308
- rval = check_format(sd, format);
309
- if (rval)
310
- return rval;
495
+ if (format->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev)
496
+ return -EPERM;
497
+
498
+ trace_android_vh_v4l2subdev_set_fmt(sd, subdev_fh->pad,
499
+ format, &ret);
500
+ trace_android_rvh_v4l2subdev_set_fmt(sd, subdev_fh->pad,
501
+ format, &ret);
502
+ if (ret)
503
+ return ret;
311504
312505 memset(format->reserved, 0, sizeof(format->reserved));
313506 memset(format->format.reserved, 0, sizeof(format->format.reserved));
....@@ -317,10 +510,6 @@
317510 case VIDIOC_SUBDEV_G_CROP: {
318511 struct v4l2_subdev_crop *crop = arg;
319512 struct v4l2_subdev_selection sel;
320
-
321
- rval = check_crop(sd, crop);
322
- if (rval)
323
- return rval;
324513
325514 memset(crop->reserved, 0, sizeof(crop->reserved));
326515 memset(&sel, 0, sizeof(sel));
....@@ -340,11 +529,10 @@
340529 struct v4l2_subdev_crop *crop = arg;
341530 struct v4l2_subdev_selection sel;
342531
343
- memset(crop->reserved, 0, sizeof(crop->reserved));
344
- rval = check_crop(sd, crop);
345
- if (rval)
346
- return rval;
532
+ if (crop->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev)
533
+ return -EPERM;
347534
535
+ memset(crop->reserved, 0, sizeof(crop->reserved));
348536 memset(&sel, 0, sizeof(sel));
349537 sel.which = crop->which;
350538 sel.pad = crop->pad;
....@@ -362,13 +550,6 @@
362550 case VIDIOC_SUBDEV_ENUM_MBUS_CODE: {
363551 struct v4l2_subdev_mbus_code_enum *code = arg;
364552
365
- if (code->which != V4L2_SUBDEV_FORMAT_TRY &&
366
- code->which != V4L2_SUBDEV_FORMAT_ACTIVE)
367
- return -EINVAL;
368
-
369
- if (code->pad >= sd->entity.num_pads)
370
- return -EINVAL;
371
-
372553 memset(code->reserved, 0, sizeof(code->reserved));
373554 return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh->pad,
374555 code);
....@@ -376,13 +557,6 @@
376557
377558 case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: {
378559 struct v4l2_subdev_frame_size_enum *fse = arg;
379
-
380
- if (fse->which != V4L2_SUBDEV_FORMAT_TRY &&
381
- fse->which != V4L2_SUBDEV_FORMAT_ACTIVE)
382
- return -EINVAL;
383
-
384
- if (fse->pad >= sd->entity.num_pads)
385
- return -EINVAL;
386560
387561 memset(fse->reserved, 0, sizeof(fse->reserved));
388562 return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh->pad,
....@@ -392,18 +566,21 @@
392566 case VIDIOC_SUBDEV_G_FRAME_INTERVAL: {
393567 struct v4l2_subdev_frame_interval *fi = arg;
394568
395
- if (fi->pad >= sd->entity.num_pads)
396
- return -EINVAL;
397
-
398569 memset(fi->reserved, 0, sizeof(fi->reserved));
399570 return v4l2_subdev_call(sd, video, g_frame_interval, arg);
400571 }
401572
402573 case VIDIOC_SUBDEV_S_FRAME_INTERVAL: {
403574 struct v4l2_subdev_frame_interval *fi = arg;
575
+ int ret = 0;
404576
405
- if (fi->pad >= sd->entity.num_pads)
406
- return -EINVAL;
577
+ if (ro_subdev)
578
+ return -EPERM;
579
+
580
+ trace_android_vh_v4l2subdev_set_frame_interval(sd, fi, &ret);
581
+ trace_android_rvh_v4l2subdev_set_frame_interval(sd, fi, &ret);
582
+ if (ret)
583
+ return ret;
407584
408585 memset(fi->reserved, 0, sizeof(fi->reserved));
409586 return v4l2_subdev_call(sd, video, s_frame_interval, arg);
....@@ -411,13 +588,6 @@
411588
412589 case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: {
413590 struct v4l2_subdev_frame_interval_enum *fie = arg;
414
-
415
- if (fie->which != V4L2_SUBDEV_FORMAT_TRY &&
416
- fie->which != V4L2_SUBDEV_FORMAT_ACTIVE)
417
- return -EINVAL;
418
-
419
- if (fie->pad >= sd->entity.num_pads)
420
- return -EINVAL;
421591
422592 memset(fie->reserved, 0, sizeof(fie->reserved));
423593 return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh->pad,
....@@ -427,10 +597,6 @@
427597 case VIDIOC_SUBDEV_G_SELECTION: {
428598 struct v4l2_subdev_selection *sel = arg;
429599
430
- rval = check_selection(sd, sel);
431
- if (rval)
432
- return rval;
433
-
434600 memset(sel->reserved, 0, sizeof(sel->reserved));
435601 return v4l2_subdev_call(
436602 sd, pad, get_selection, subdev_fh->pad, sel);
....@@ -438,10 +604,17 @@
438604
439605 case VIDIOC_SUBDEV_S_SELECTION: {
440606 struct v4l2_subdev_selection *sel = arg;
607
+ int ret = 0;
441608
442
- rval = check_selection(sd, sel);
443
- if (rval)
444
- return rval;
609
+ if (sel->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev)
610
+ return -EPERM;
611
+
612
+ trace_android_vh_v4l2subdev_set_selection(sd, subdev_fh->pad,
613
+ sel, &ret);
614
+ trace_android_rvh_v4l2subdev_set_selection(sd, subdev_fh->pad,
615
+ sel, &ret);
616
+ if (ret)
617
+ return ret;
445618
446619 memset(sel->reserved, 0, sizeof(sel->reserved));
447620 return v4l2_subdev_call(
....@@ -451,19 +624,11 @@
451624 case VIDIOC_G_EDID: {
452625 struct v4l2_subdev_edid *edid = arg;
453626
454
- rval = check_edid(sd, edid);
455
- if (rval)
456
- return rval;
457
-
458627 return v4l2_subdev_call(sd, pad, get_edid, edid);
459628 }
460629
461630 case VIDIOC_S_EDID: {
462631 struct v4l2_subdev_edid *edid = arg;
463
-
464
- rval = check_edid(sd, edid);
465
- if (rval)
466
- return rval;
467632
468633 return v4l2_subdev_call(sd, pad, set_edid, edid);
469634 }
....@@ -471,17 +636,11 @@
471636 case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
472637 struct v4l2_dv_timings_cap *cap = arg;
473638
474
- if (cap->pad >= sd->entity.num_pads)
475
- return -EINVAL;
476
-
477639 return v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
478640 }
479641
480642 case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: {
481643 struct v4l2_enum_dv_timings *dvt = arg;
482
-
483
- if (dvt->pad >= sd->entity.num_pads)
484
- return -EINVAL;
485644
486645 return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt);
487646 }
....@@ -493,16 +652,19 @@
493652 return v4l2_subdev_call(sd, video, g_dv_timings, arg);
494653
495654 case VIDIOC_SUBDEV_S_DV_TIMINGS:
496
- return v4l2_subdev_call(sd, video, s_dv_timings, arg);
655
+ if (ro_subdev)
656
+ return -EPERM;
497657
498
- case VIDIOC_G_INPUT:
499
- return v4l2_subdev_call(sd, video, g_input_status, arg);
658
+ return v4l2_subdev_call(sd, video, s_dv_timings, arg);
500659
501660 case VIDIOC_SUBDEV_G_STD:
502661 return v4l2_subdev_call(sd, video, g_std, arg);
503662
504663 case VIDIOC_SUBDEV_S_STD: {
505664 v4l2_std_id *std = arg;
665
+
666
+ if (ro_subdev)
667
+ return -EPERM;
506668
507669 return v4l2_subdev_call(sd, video, s_std, *std);
508670 }
....@@ -519,7 +681,7 @@
519681
520682 case VIDIOC_SUBDEV_QUERYSTD:
521683 return v4l2_subdev_call(sd, video, querystd, arg);
522
-#endif
684
+
523685 default:
524686 return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
525687 }
....@@ -559,6 +721,22 @@
559721 }
560722 #endif
561723
724
+#else /* CONFIG_VIDEO_V4L2_SUBDEV_API */
725
+static long subdev_ioctl(struct file *file, unsigned int cmd,
726
+ unsigned long arg)
727
+{
728
+ return -ENODEV;
729
+}
730
+
731
+#ifdef CONFIG_COMPAT
732
+static long subdev_compat_ioctl32(struct file *file, unsigned int cmd,
733
+ unsigned long arg)
734
+{
735
+ return -ENODEV;
736
+}
737
+#endif
738
+#endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
739
+
562740 static __poll_t subdev_poll(struct file *file, poll_table *wait)
563741 {
564742 struct video_device *vdev = video_devdata(file);
....@@ -586,9 +764,30 @@
586764 .release = subdev_close,
587765 .poll = subdev_poll,
588766 };
589
-EXPORT_SYMBOL_GPL(v4l2_subdev_fops);
590767
591768 #ifdef CONFIG_MEDIA_CONTROLLER
769
+
770
+int v4l2_subdev_get_fwnode_pad_1_to_1(struct media_entity *entity,
771
+ struct fwnode_endpoint *endpoint)
772
+{
773
+ struct fwnode_handle *fwnode;
774
+ struct v4l2_subdev *sd;
775
+
776
+ if (!is_media_entity_v4l2_subdev(entity))
777
+ return -EINVAL;
778
+
779
+ sd = media_entity_to_v4l2_subdev(entity);
780
+
781
+ fwnode = fwnode_graph_get_port_parent(endpoint->local_fwnode);
782
+ fwnode_handle_put(fwnode);
783
+
784
+ if (dev_fwnode(sd->dev) == fwnode)
785
+ return endpoint->port;
786
+
787
+ return -ENXIO;
788
+}
789
+EXPORT_SYMBOL_GPL(v4l2_subdev_get_fwnode_pad_1_to_1);
790
+
592791 int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
593792 struct media_link *link,
594793 struct v4l2_subdev_format *source_fmt,