1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2010 Nokia Corporation
7 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
8 * Sakari Ailus <sakari.ailus@iki.fi>
11 #include <linux/ioctl.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/types.h>
16 #include <linux/videodev2.h>
17 #include <linux/export.h>
19 #include <media/v4l2-ctrls.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-ioctl.h>
22 #include <media/v4l2-fh.h>
23 #include <media/v4l2-event.h>
25 static int subdev_fh_init(struct v4l2_subdev_fh
*fh
, struct v4l2_subdev
*sd
)
27 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
28 if (sd
->entity
.num_pads
) {
29 fh
->pad
= v4l2_subdev_alloc_pad_config(sd
);
37 static void subdev_fh_free(struct v4l2_subdev_fh
*fh
)
39 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
40 v4l2_subdev_free_pad_config(fh
->pad
);
45 static int subdev_open(struct file
*file
)
47 struct video_device
*vdev
= video_devdata(file
);
48 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
49 struct v4l2_subdev_fh
*subdev_fh
;
52 subdev_fh
= kzalloc(sizeof(*subdev_fh
), GFP_KERNEL
);
53 if (subdev_fh
== NULL
)
56 ret
= subdev_fh_init(subdev_fh
, sd
);
62 v4l2_fh_init(&subdev_fh
->vfh
, vdev
);
63 v4l2_fh_add(&subdev_fh
->vfh
);
64 file
->private_data
= &subdev_fh
->vfh
;
65 #if defined(CONFIG_MEDIA_CONTROLLER)
66 if (sd
->v4l2_dev
->mdev
&& sd
->entity
.graph_obj
.mdev
->dev
) {
69 owner
= sd
->entity
.graph_obj
.mdev
->dev
->driver
->owner
;
70 if (!try_module_get(owner
)) {
74 subdev_fh
->owner
= owner
;
78 if (sd
->internal_ops
&& sd
->internal_ops
->open
) {
79 ret
= sd
->internal_ops
->open(sd
, subdev_fh
);
87 module_put(subdev_fh
->owner
);
88 v4l2_fh_del(&subdev_fh
->vfh
);
89 v4l2_fh_exit(&subdev_fh
->vfh
);
90 subdev_fh_free(subdev_fh
);
96 static int subdev_close(struct file
*file
)
98 struct video_device
*vdev
= video_devdata(file
);
99 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
100 struct v4l2_fh
*vfh
= file
->private_data
;
101 struct v4l2_subdev_fh
*subdev_fh
= to_v4l2_subdev_fh(vfh
);
103 if (sd
->internal_ops
&& sd
->internal_ops
->close
)
104 sd
->internal_ops
->close(sd
, subdev_fh
);
105 module_put(subdev_fh
->owner
);
108 subdev_fh_free(subdev_fh
);
110 file
->private_data
= NULL
;
115 static inline int check_which(__u32 which
)
117 if (which
!= V4L2_SUBDEV_FORMAT_TRY
&&
118 which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
124 static inline int check_pad(struct v4l2_subdev
*sd
, __u32 pad
)
126 #if defined(CONFIG_MEDIA_CONTROLLER)
127 if (sd
->entity
.num_pads
) {
128 if (pad
>= sd
->entity
.num_pads
)
133 /* allow pad 0 on subdevices not registered as media entities */
139 static int check_cfg(__u32 which
, struct v4l2_subdev_pad_config
*cfg
)
141 if (which
== V4L2_SUBDEV_FORMAT_TRY
&& !cfg
)
147 static inline int check_format(struct v4l2_subdev
*sd
,
148 struct v4l2_subdev_pad_config
*cfg
,
149 struct v4l2_subdev_format
*format
)
154 return check_which(format
->which
) ? : check_pad(sd
, format
->pad
) ? :
155 check_cfg(format
->which
, cfg
);
158 static int call_get_fmt(struct v4l2_subdev
*sd
,
159 struct v4l2_subdev_pad_config
*cfg
,
160 struct v4l2_subdev_format
*format
)
162 return check_format(sd
, cfg
, format
) ? :
163 sd
->ops
->pad
->get_fmt(sd
, cfg
, format
);
166 static int call_set_fmt(struct v4l2_subdev
*sd
,
167 struct v4l2_subdev_pad_config
*cfg
,
168 struct v4l2_subdev_format
*format
)
170 return check_format(sd
, cfg
, format
) ? :
171 sd
->ops
->pad
->set_fmt(sd
, cfg
, format
);
174 static int call_enum_mbus_code(struct v4l2_subdev
*sd
,
175 struct v4l2_subdev_pad_config
*cfg
,
176 struct v4l2_subdev_mbus_code_enum
*code
)
181 return check_which(code
->which
) ? : check_pad(sd
, code
->pad
) ? :
182 check_cfg(code
->which
, cfg
) ? :
183 sd
->ops
->pad
->enum_mbus_code(sd
, cfg
, code
);
186 static int call_enum_frame_size(struct v4l2_subdev
*sd
,
187 struct v4l2_subdev_pad_config
*cfg
,
188 struct v4l2_subdev_frame_size_enum
*fse
)
193 return check_which(fse
->which
) ? : check_pad(sd
, fse
->pad
) ? :
194 check_cfg(fse
->which
, cfg
) ? :
195 sd
->ops
->pad
->enum_frame_size(sd
, cfg
, fse
);
198 static inline int check_frame_interval(struct v4l2_subdev
*sd
,
199 struct v4l2_subdev_frame_interval
*fi
)
204 return check_pad(sd
, fi
->pad
);
207 static int call_g_frame_interval(struct v4l2_subdev
*sd
,
208 struct v4l2_subdev_frame_interval
*fi
)
210 return check_frame_interval(sd
, fi
) ? :
211 sd
->ops
->video
->g_frame_interval(sd
, fi
);
214 static int call_s_frame_interval(struct v4l2_subdev
*sd
,
215 struct v4l2_subdev_frame_interval
*fi
)
217 return check_frame_interval(sd
, fi
) ? :
218 sd
->ops
->video
->s_frame_interval(sd
, fi
);
221 static int call_enum_frame_interval(struct v4l2_subdev
*sd
,
222 struct v4l2_subdev_pad_config
*cfg
,
223 struct v4l2_subdev_frame_interval_enum
*fie
)
228 return check_which(fie
->which
) ? : check_pad(sd
, fie
->pad
) ? :
229 check_cfg(fie
->which
, cfg
) ? :
230 sd
->ops
->pad
->enum_frame_interval(sd
, cfg
, fie
);
233 static inline int check_selection(struct v4l2_subdev
*sd
,
234 struct v4l2_subdev_pad_config
*cfg
,
235 struct v4l2_subdev_selection
*sel
)
240 return check_which(sel
->which
) ? : check_pad(sd
, sel
->pad
) ? :
241 check_cfg(sel
->which
, cfg
);
244 static int call_get_selection(struct v4l2_subdev
*sd
,
245 struct v4l2_subdev_pad_config
*cfg
,
246 struct v4l2_subdev_selection
*sel
)
248 return check_selection(sd
, cfg
, sel
) ? :
249 sd
->ops
->pad
->get_selection(sd
, cfg
, sel
);
252 static int call_set_selection(struct v4l2_subdev
*sd
,
253 struct v4l2_subdev_pad_config
*cfg
,
254 struct v4l2_subdev_selection
*sel
)
256 return check_selection(sd
, cfg
, sel
) ? :
257 sd
->ops
->pad
->set_selection(sd
, cfg
, sel
);
260 static inline int check_edid(struct v4l2_subdev
*sd
,
261 struct v4l2_subdev_edid
*edid
)
266 if (edid
->blocks
&& edid
->edid
== NULL
)
269 return check_pad(sd
, edid
->pad
);
272 static int call_get_edid(struct v4l2_subdev
*sd
, struct v4l2_subdev_edid
*edid
)
274 return check_edid(sd
, edid
) ? : sd
->ops
->pad
->get_edid(sd
, edid
);
277 static int call_set_edid(struct v4l2_subdev
*sd
, struct v4l2_subdev_edid
*edid
)
279 return check_edid(sd
, edid
) ? : sd
->ops
->pad
->set_edid(sd
, edid
);
282 static int call_dv_timings_cap(struct v4l2_subdev
*sd
,
283 struct v4l2_dv_timings_cap
*cap
)
288 return check_pad(sd
, cap
->pad
) ? :
289 sd
->ops
->pad
->dv_timings_cap(sd
, cap
);
292 static int call_enum_dv_timings(struct v4l2_subdev
*sd
,
293 struct v4l2_enum_dv_timings
*dvt
)
298 return check_pad(sd
, dvt
->pad
) ? :
299 sd
->ops
->pad
->enum_dv_timings(sd
, dvt
);
302 static const struct v4l2_subdev_pad_ops v4l2_subdev_call_pad_wrappers
= {
303 .get_fmt
= call_get_fmt
,
304 .set_fmt
= call_set_fmt
,
305 .enum_mbus_code
= call_enum_mbus_code
,
306 .enum_frame_size
= call_enum_frame_size
,
307 .enum_frame_interval
= call_enum_frame_interval
,
308 .get_selection
= call_get_selection
,
309 .set_selection
= call_set_selection
,
310 .get_edid
= call_get_edid
,
311 .set_edid
= call_set_edid
,
312 .dv_timings_cap
= call_dv_timings_cap
,
313 .enum_dv_timings
= call_enum_dv_timings
,
316 static const struct v4l2_subdev_video_ops v4l2_subdev_call_video_wrappers
= {
317 .g_frame_interval
= call_g_frame_interval
,
318 .s_frame_interval
= call_s_frame_interval
,
321 const struct v4l2_subdev_ops v4l2_subdev_call_wrappers
= {
322 .pad
= &v4l2_subdev_call_pad_wrappers
,
323 .video
= &v4l2_subdev_call_video_wrappers
,
325 EXPORT_SYMBOL(v4l2_subdev_call_wrappers
);
327 static long subdev_do_ioctl(struct file
*file
, unsigned int cmd
, void *arg
)
329 struct video_device
*vdev
= video_devdata(file
);
330 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
331 struct v4l2_fh
*vfh
= file
->private_data
;
332 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
333 struct v4l2_subdev_fh
*subdev_fh
= to_v4l2_subdev_fh(vfh
);
338 case VIDIOC_QUERYCTRL
:
340 * TODO: this really should be folded into v4l2_queryctrl (this
341 * currently returns -EINVAL for NULL control handlers).
342 * However, v4l2_queryctrl() is still called directly by
343 * drivers as well and until that has been addressed I believe
344 * it is safer to do the check here. The same is true for the
345 * other control ioctls below.
347 if (!vfh
->ctrl_handler
)
349 return v4l2_queryctrl(vfh
->ctrl_handler
, arg
);
351 case VIDIOC_QUERY_EXT_CTRL
:
352 if (!vfh
->ctrl_handler
)
354 return v4l2_query_ext_ctrl(vfh
->ctrl_handler
, arg
);
356 case VIDIOC_QUERYMENU
:
357 if (!vfh
->ctrl_handler
)
359 return v4l2_querymenu(vfh
->ctrl_handler
, arg
);
362 if (!vfh
->ctrl_handler
)
364 return v4l2_g_ctrl(vfh
->ctrl_handler
, arg
);
367 if (!vfh
->ctrl_handler
)
369 return v4l2_s_ctrl(vfh
, vfh
->ctrl_handler
, arg
);
371 case VIDIOC_G_EXT_CTRLS
:
372 if (!vfh
->ctrl_handler
)
374 return v4l2_g_ext_ctrls(vfh
->ctrl_handler
,
375 sd
->v4l2_dev
->mdev
, arg
);
377 case VIDIOC_S_EXT_CTRLS
:
378 if (!vfh
->ctrl_handler
)
380 return v4l2_s_ext_ctrls(vfh
, vfh
->ctrl_handler
,
381 sd
->v4l2_dev
->mdev
, arg
);
383 case VIDIOC_TRY_EXT_CTRLS
:
384 if (!vfh
->ctrl_handler
)
386 return v4l2_try_ext_ctrls(vfh
->ctrl_handler
,
387 sd
->v4l2_dev
->mdev
, arg
);
390 if (!(sd
->flags
& V4L2_SUBDEV_FL_HAS_EVENTS
))
393 return v4l2_event_dequeue(vfh
, arg
, file
->f_flags
& O_NONBLOCK
);
395 case VIDIOC_SUBSCRIBE_EVENT
:
396 return v4l2_subdev_call(sd
, core
, subscribe_event
, vfh
, arg
);
398 case VIDIOC_UNSUBSCRIBE_EVENT
:
399 return v4l2_subdev_call(sd
, core
, unsubscribe_event
, vfh
, arg
);
401 #ifdef CONFIG_VIDEO_ADV_DEBUG
402 case VIDIOC_DBG_G_REGISTER
:
404 struct v4l2_dbg_register
*p
= arg
;
406 if (!capable(CAP_SYS_ADMIN
))
408 return v4l2_subdev_call(sd
, core
, g_register
, p
);
410 case VIDIOC_DBG_S_REGISTER
:
412 struct v4l2_dbg_register
*p
= arg
;
414 if (!capable(CAP_SYS_ADMIN
))
416 return v4l2_subdev_call(sd
, core
, s_register
, p
);
418 case VIDIOC_DBG_G_CHIP_INFO
:
420 struct v4l2_dbg_chip_info
*p
= arg
;
422 if (p
->match
.type
!= V4L2_CHIP_MATCH_SUBDEV
|| p
->match
.addr
)
424 if (sd
->ops
->core
&& sd
->ops
->core
->s_register
)
425 p
->flags
|= V4L2_CHIP_FL_WRITABLE
;
426 if (sd
->ops
->core
&& sd
->ops
->core
->g_register
)
427 p
->flags
|= V4L2_CHIP_FL_READABLE
;
428 strscpy(p
->name
, sd
->name
, sizeof(p
->name
));
433 case VIDIOC_LOG_STATUS
: {
436 pr_info("%s: ================= START STATUS =================\n",
438 ret
= v4l2_subdev_call(sd
, core
, log_status
);
439 pr_info("%s: ================== END STATUS ==================\n",
444 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
445 case VIDIOC_SUBDEV_G_FMT
: {
446 struct v4l2_subdev_format
*format
= arg
;
448 memset(format
->reserved
, 0, sizeof(format
->reserved
));
449 memset(format
->format
.reserved
, 0, sizeof(format
->format
.reserved
));
450 return v4l2_subdev_call(sd
, pad
, get_fmt
, subdev_fh
->pad
, format
);
453 case VIDIOC_SUBDEV_S_FMT
: {
454 struct v4l2_subdev_format
*format
= arg
;
456 memset(format
->reserved
, 0, sizeof(format
->reserved
));
457 memset(format
->format
.reserved
, 0, sizeof(format
->format
.reserved
));
458 return v4l2_subdev_call(sd
, pad
, set_fmt
, subdev_fh
->pad
, format
);
461 case VIDIOC_SUBDEV_G_CROP
: {
462 struct v4l2_subdev_crop
*crop
= arg
;
463 struct v4l2_subdev_selection sel
;
465 memset(crop
->reserved
, 0, sizeof(crop
->reserved
));
466 memset(&sel
, 0, sizeof(sel
));
467 sel
.which
= crop
->which
;
469 sel
.target
= V4L2_SEL_TGT_CROP
;
471 rval
= v4l2_subdev_call(
472 sd
, pad
, get_selection
, subdev_fh
->pad
, &sel
);
479 case VIDIOC_SUBDEV_S_CROP
: {
480 struct v4l2_subdev_crop
*crop
= arg
;
481 struct v4l2_subdev_selection sel
;
483 memset(crop
->reserved
, 0, sizeof(crop
->reserved
));
484 memset(&sel
, 0, sizeof(sel
));
485 sel
.which
= crop
->which
;
487 sel
.target
= V4L2_SEL_TGT_CROP
;
490 rval
= v4l2_subdev_call(
491 sd
, pad
, set_selection
, subdev_fh
->pad
, &sel
);
498 case VIDIOC_SUBDEV_ENUM_MBUS_CODE
: {
499 struct v4l2_subdev_mbus_code_enum
*code
= arg
;
501 memset(code
->reserved
, 0, sizeof(code
->reserved
));
502 return v4l2_subdev_call(sd
, pad
, enum_mbus_code
, subdev_fh
->pad
,
506 case VIDIOC_SUBDEV_ENUM_FRAME_SIZE
: {
507 struct v4l2_subdev_frame_size_enum
*fse
= arg
;
509 memset(fse
->reserved
, 0, sizeof(fse
->reserved
));
510 return v4l2_subdev_call(sd
, pad
, enum_frame_size
, subdev_fh
->pad
,
514 case VIDIOC_SUBDEV_G_FRAME_INTERVAL
: {
515 struct v4l2_subdev_frame_interval
*fi
= arg
;
517 memset(fi
->reserved
, 0, sizeof(fi
->reserved
));
518 return v4l2_subdev_call(sd
, video
, g_frame_interval
, arg
);
521 case VIDIOC_SUBDEV_S_FRAME_INTERVAL
: {
522 struct v4l2_subdev_frame_interval
*fi
= arg
;
524 memset(fi
->reserved
, 0, sizeof(fi
->reserved
));
525 return v4l2_subdev_call(sd
, video
, s_frame_interval
, arg
);
528 case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
: {
529 struct v4l2_subdev_frame_interval_enum
*fie
= arg
;
531 memset(fie
->reserved
, 0, sizeof(fie
->reserved
));
532 return v4l2_subdev_call(sd
, pad
, enum_frame_interval
, subdev_fh
->pad
,
536 case VIDIOC_SUBDEV_G_SELECTION
: {
537 struct v4l2_subdev_selection
*sel
= arg
;
539 memset(sel
->reserved
, 0, sizeof(sel
->reserved
));
540 return v4l2_subdev_call(
541 sd
, pad
, get_selection
, subdev_fh
->pad
, sel
);
544 case VIDIOC_SUBDEV_S_SELECTION
: {
545 struct v4l2_subdev_selection
*sel
= arg
;
547 memset(sel
->reserved
, 0, sizeof(sel
->reserved
));
548 return v4l2_subdev_call(
549 sd
, pad
, set_selection
, subdev_fh
->pad
, sel
);
552 case VIDIOC_G_EDID
: {
553 struct v4l2_subdev_edid
*edid
= arg
;
555 return v4l2_subdev_call(sd
, pad
, get_edid
, edid
);
558 case VIDIOC_S_EDID
: {
559 struct v4l2_subdev_edid
*edid
= arg
;
561 return v4l2_subdev_call(sd
, pad
, set_edid
, edid
);
564 case VIDIOC_SUBDEV_DV_TIMINGS_CAP
: {
565 struct v4l2_dv_timings_cap
*cap
= arg
;
567 return v4l2_subdev_call(sd
, pad
, dv_timings_cap
, cap
);
570 case VIDIOC_SUBDEV_ENUM_DV_TIMINGS
: {
571 struct v4l2_enum_dv_timings
*dvt
= arg
;
573 return v4l2_subdev_call(sd
, pad
, enum_dv_timings
, dvt
);
576 case VIDIOC_SUBDEV_QUERY_DV_TIMINGS
:
577 return v4l2_subdev_call(sd
, video
, query_dv_timings
, arg
);
579 case VIDIOC_SUBDEV_G_DV_TIMINGS
:
580 return v4l2_subdev_call(sd
, video
, g_dv_timings
, arg
);
582 case VIDIOC_SUBDEV_S_DV_TIMINGS
:
583 return v4l2_subdev_call(sd
, video
, s_dv_timings
, arg
);
585 case VIDIOC_SUBDEV_G_STD
:
586 return v4l2_subdev_call(sd
, video
, g_std
, arg
);
588 case VIDIOC_SUBDEV_S_STD
: {
589 v4l2_std_id
*std
= arg
;
591 return v4l2_subdev_call(sd
, video
, s_std
, *std
);
594 case VIDIOC_SUBDEV_ENUMSTD
: {
595 struct v4l2_standard
*p
= arg
;
598 if (v4l2_subdev_call(sd
, video
, g_tvnorms
, &id
))
601 return v4l_video_std_enumstd(p
, id
);
604 case VIDIOC_SUBDEV_QUERYSTD
:
605 return v4l2_subdev_call(sd
, video
, querystd
, arg
);
608 return v4l2_subdev_call(sd
, core
, ioctl
, cmd
, arg
);
614 static long subdev_do_ioctl_lock(struct file
*file
, unsigned int cmd
, void *arg
)
616 struct video_device
*vdev
= video_devdata(file
);
617 struct mutex
*lock
= vdev
->lock
;
620 if (lock
&& mutex_lock_interruptible(lock
))
622 if (video_is_registered(vdev
))
623 ret
= subdev_do_ioctl(file
, cmd
, arg
);
629 static long subdev_ioctl(struct file
*file
, unsigned int cmd
,
632 return video_usercopy(file
, cmd
, arg
, subdev_do_ioctl_lock
);
636 static long subdev_compat_ioctl32(struct file
*file
, unsigned int cmd
,
639 struct video_device
*vdev
= video_devdata(file
);
640 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
642 return v4l2_subdev_call(sd
, core
, compat_ioctl32
, cmd
, arg
);
646 static __poll_t
subdev_poll(struct file
*file
, poll_table
*wait
)
648 struct video_device
*vdev
= video_devdata(file
);
649 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
650 struct v4l2_fh
*fh
= file
->private_data
;
652 if (!(sd
->flags
& V4L2_SUBDEV_FL_HAS_EVENTS
))
655 poll_wait(file
, &fh
->wait
, wait
);
657 if (v4l2_event_pending(fh
))
663 const struct v4l2_file_operations v4l2_subdev_fops
= {
664 .owner
= THIS_MODULE
,
666 .unlocked_ioctl
= subdev_ioctl
,
668 .compat_ioctl32
= subdev_compat_ioctl32
,
670 .release
= subdev_close
,
674 #ifdef CONFIG_MEDIA_CONTROLLER
675 int v4l2_subdev_link_validate_default(struct v4l2_subdev
*sd
,
676 struct media_link
*link
,
677 struct v4l2_subdev_format
*source_fmt
,
678 struct v4l2_subdev_format
*sink_fmt
)
680 /* The width, height and code must match. */
681 if (source_fmt
->format
.width
!= sink_fmt
->format
.width
682 || source_fmt
->format
.height
!= sink_fmt
->format
.height
683 || source_fmt
->format
.code
!= sink_fmt
->format
.code
)
686 /* The field order must match, or the sink field order must be NONE
687 * to support interlaced hardware connected to bridges that support
688 * progressive formats only.
690 if (source_fmt
->format
.field
!= sink_fmt
->format
.field
&&
691 sink_fmt
->format
.field
!= V4L2_FIELD_NONE
)
696 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default
);
699 v4l2_subdev_link_validate_get_format(struct media_pad
*pad
,
700 struct v4l2_subdev_format
*fmt
)
702 if (is_media_entity_v4l2_subdev(pad
->entity
)) {
703 struct v4l2_subdev
*sd
=
704 media_entity_to_v4l2_subdev(pad
->entity
);
706 fmt
->which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
707 fmt
->pad
= pad
->index
;
708 return v4l2_subdev_call(sd
, pad
, get_fmt
, NULL
, fmt
);
711 WARN(pad
->entity
->function
!= MEDIA_ENT_F_IO_V4L
,
712 "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
713 pad
->entity
->function
, pad
->entity
->name
);
718 int v4l2_subdev_link_validate(struct media_link
*link
)
720 struct v4l2_subdev
*sink
;
721 struct v4l2_subdev_format sink_fmt
, source_fmt
;
724 rval
= v4l2_subdev_link_validate_get_format(
725 link
->source
, &source_fmt
);
729 rval
= v4l2_subdev_link_validate_get_format(
730 link
->sink
, &sink_fmt
);
734 sink
= media_entity_to_v4l2_subdev(link
->sink
->entity
);
736 rval
= v4l2_subdev_call(sink
, pad
, link_validate
, link
,
737 &source_fmt
, &sink_fmt
);
738 if (rval
!= -ENOIOCTLCMD
)
741 return v4l2_subdev_link_validate_default(
742 sink
, link
, &source_fmt
, &sink_fmt
);
744 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate
);
746 struct v4l2_subdev_pad_config
*
747 v4l2_subdev_alloc_pad_config(struct v4l2_subdev
*sd
)
749 struct v4l2_subdev_pad_config
*cfg
;
752 if (!sd
->entity
.num_pads
)
755 cfg
= kvmalloc_array(sd
->entity
.num_pads
, sizeof(*cfg
),
756 GFP_KERNEL
| __GFP_ZERO
);
760 ret
= v4l2_subdev_call(sd
, pad
, init_cfg
, cfg
);
761 if (ret
< 0 && ret
!= -ENOIOCTLCMD
) {
768 EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_pad_config
);
770 void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config
*cfg
)
774 EXPORT_SYMBOL_GPL(v4l2_subdev_free_pad_config
);
775 #endif /* CONFIG_MEDIA_CONTROLLER */
777 void v4l2_subdev_init(struct v4l2_subdev
*sd
, const struct v4l2_subdev_ops
*ops
)
779 INIT_LIST_HEAD(&sd
->list
);
787 sd
->host_priv
= NULL
;
788 #if defined(CONFIG_MEDIA_CONTROLLER)
789 sd
->entity
.name
= sd
->name
;
790 sd
->entity
.obj_type
= MEDIA_ENTITY_TYPE_V4L2_SUBDEV
;
791 sd
->entity
.function
= MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN
;
794 EXPORT_SYMBOL(v4l2_subdev_init
);
796 void v4l2_subdev_notify_event(struct v4l2_subdev
*sd
,
797 const struct v4l2_event
*ev
)
799 v4l2_event_queue(sd
->devnode
, ev
);
800 v4l2_subdev_notify(sd
, V4L2_DEVICE_NOTIFY_EVENT
, (void *)ev
);
802 EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event
);