4 * Copyright (C) 2010 Nokia Corporation
6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7 * Sakari Ailus <sakari.ailus@iki.fi>
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.
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.
19 #include <linux/ioctl.h>
21 #include <linux/slab.h>
22 #include <linux/types.h>
23 #include <linux/videodev2.h>
24 #include <linux/export.h>
26 #include <media/v4l2-ctrls.h>
27 #include <media/v4l2-device.h>
28 #include <media/v4l2-ioctl.h>
29 #include <media/v4l2-fh.h>
30 #include <media/v4l2-event.h>
32 static int subdev_fh_init(struct v4l2_subdev_fh
*fh
, struct v4l2_subdev
*sd
)
34 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
35 if (sd
->entity
.num_pads
) {
36 fh
->pad
= v4l2_subdev_alloc_pad_config(sd
);
44 static void subdev_fh_free(struct v4l2_subdev_fh
*fh
)
46 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
47 v4l2_subdev_free_pad_config(fh
->pad
);
52 static int subdev_open(struct file
*file
)
54 struct video_device
*vdev
= video_devdata(file
);
55 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
56 struct v4l2_subdev_fh
*subdev_fh
;
57 #if defined(CONFIG_MEDIA_CONTROLLER)
58 struct media_entity
*entity
= NULL
;
62 subdev_fh
= kzalloc(sizeof(*subdev_fh
), GFP_KERNEL
);
63 if (subdev_fh
== NULL
)
66 ret
= subdev_fh_init(subdev_fh
, sd
);
72 v4l2_fh_init(&subdev_fh
->vfh
, vdev
);
73 v4l2_fh_add(&subdev_fh
->vfh
);
74 file
->private_data
= &subdev_fh
->vfh
;
75 #if defined(CONFIG_MEDIA_CONTROLLER)
76 if (sd
->v4l2_dev
->mdev
) {
77 entity
= media_entity_get(&sd
->entity
);
85 if (sd
->internal_ops
&& sd
->internal_ops
->open
) {
86 ret
= sd
->internal_ops
->open(sd
, subdev_fh
);
94 #if defined(CONFIG_MEDIA_CONTROLLER)
95 media_entity_put(entity
);
97 v4l2_fh_del(&subdev_fh
->vfh
);
98 v4l2_fh_exit(&subdev_fh
->vfh
);
99 subdev_fh_free(subdev_fh
);
105 static int subdev_close(struct file
*file
)
107 struct video_device
*vdev
= video_devdata(file
);
108 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
109 struct v4l2_fh
*vfh
= file
->private_data
;
110 struct v4l2_subdev_fh
*subdev_fh
= to_v4l2_subdev_fh(vfh
);
112 if (sd
->internal_ops
&& sd
->internal_ops
->close
)
113 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
);
120 subdev_fh_free(subdev_fh
);
122 file
->private_data
= NULL
;
127 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
128 static int check_format(struct v4l2_subdev
*sd
,
129 struct v4l2_subdev_format
*format
)
131 if (format
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
132 format
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
135 if (format
->pad
>= sd
->entity
.num_pads
)
141 static int check_crop(struct v4l2_subdev
*sd
, struct v4l2_subdev_crop
*crop
)
143 if (crop
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
144 crop
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
147 if (crop
->pad
>= sd
->entity
.num_pads
)
153 static int check_selection(struct v4l2_subdev
*sd
,
154 struct v4l2_subdev_selection
*sel
)
156 if (sel
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
157 sel
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
160 if (sel
->pad
>= sd
->entity
.num_pads
)
166 static int check_edid(struct v4l2_subdev
*sd
, struct v4l2_subdev_edid
*edid
)
168 if (edid
->pad
>= sd
->entity
.num_pads
)
171 if (edid
->blocks
&& edid
->edid
== NULL
)
178 static long subdev_do_ioctl(struct file
*file
, unsigned int cmd
, void *arg
)
180 struct video_device
*vdev
= video_devdata(file
);
181 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
182 struct v4l2_fh
*vfh
= file
->private_data
;
183 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
184 struct v4l2_subdev_fh
*subdev_fh
= to_v4l2_subdev_fh(vfh
);
189 case VIDIOC_QUERYCTRL
:
190 return v4l2_queryctrl(vfh
->ctrl_handler
, arg
);
192 case VIDIOC_QUERY_EXT_CTRL
:
193 return v4l2_query_ext_ctrl(vfh
->ctrl_handler
, arg
);
195 case VIDIOC_QUERYMENU
:
196 return v4l2_querymenu(vfh
->ctrl_handler
, arg
);
199 return v4l2_g_ctrl(vfh
->ctrl_handler
, arg
);
202 return v4l2_s_ctrl(vfh
, vfh
->ctrl_handler
, arg
);
204 case VIDIOC_G_EXT_CTRLS
:
205 return v4l2_g_ext_ctrls(vfh
->ctrl_handler
, arg
);
207 case VIDIOC_S_EXT_CTRLS
:
208 return v4l2_s_ext_ctrls(vfh
, vfh
->ctrl_handler
, arg
);
210 case VIDIOC_TRY_EXT_CTRLS
:
211 return v4l2_try_ext_ctrls(vfh
->ctrl_handler
, arg
);
214 if (!(sd
->flags
& V4L2_SUBDEV_FL_HAS_EVENTS
))
217 return v4l2_event_dequeue(vfh
, arg
, file
->f_flags
& O_NONBLOCK
);
219 case VIDIOC_SUBSCRIBE_EVENT
:
220 return v4l2_subdev_call(sd
, core
, subscribe_event
, vfh
, arg
);
222 case VIDIOC_UNSUBSCRIBE_EVENT
:
223 return v4l2_subdev_call(sd
, core
, unsubscribe_event
, vfh
, arg
);
225 #ifdef CONFIG_VIDEO_ADV_DEBUG
226 case VIDIOC_DBG_G_REGISTER
:
228 struct v4l2_dbg_register
*p
= arg
;
230 if (!capable(CAP_SYS_ADMIN
))
232 return v4l2_subdev_call(sd
, core
, g_register
, p
);
234 case VIDIOC_DBG_S_REGISTER
:
236 struct v4l2_dbg_register
*p
= arg
;
238 if (!capable(CAP_SYS_ADMIN
))
240 return v4l2_subdev_call(sd
, core
, s_register
, p
);
244 case VIDIOC_LOG_STATUS
: {
247 pr_info("%s: ================= START STATUS =================\n",
249 ret
= v4l2_subdev_call(sd
, core
, log_status
);
250 pr_info("%s: ================== END STATUS ==================\n",
255 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
256 case VIDIOC_SUBDEV_G_FMT
: {
257 struct v4l2_subdev_format
*format
= arg
;
259 rval
= check_format(sd
, format
);
263 return v4l2_subdev_call(sd
, pad
, get_fmt
, subdev_fh
->pad
, format
);
266 case VIDIOC_SUBDEV_S_FMT
: {
267 struct v4l2_subdev_format
*format
= arg
;
269 rval
= check_format(sd
, format
);
273 return v4l2_subdev_call(sd
, pad
, set_fmt
, subdev_fh
->pad
, format
);
276 case VIDIOC_SUBDEV_G_CROP
: {
277 struct v4l2_subdev_crop
*crop
= arg
;
278 struct v4l2_subdev_selection sel
;
280 rval
= check_crop(sd
, crop
);
284 memset(&sel
, 0, sizeof(sel
));
285 sel
.which
= crop
->which
;
287 sel
.target
= V4L2_SEL_TGT_CROP
;
289 rval
= v4l2_subdev_call(
290 sd
, pad
, get_selection
, subdev_fh
->pad
, &sel
);
297 case VIDIOC_SUBDEV_S_CROP
: {
298 struct v4l2_subdev_crop
*crop
= arg
;
299 struct v4l2_subdev_selection sel
;
301 rval
= check_crop(sd
, crop
);
305 memset(&sel
, 0, sizeof(sel
));
306 sel
.which
= crop
->which
;
308 sel
.target
= V4L2_SEL_TGT_CROP
;
311 rval
= v4l2_subdev_call(
312 sd
, pad
, set_selection
, subdev_fh
->pad
, &sel
);
319 case VIDIOC_SUBDEV_ENUM_MBUS_CODE
: {
320 struct v4l2_subdev_mbus_code_enum
*code
= arg
;
322 if (code
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
323 code
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
326 if (code
->pad
>= sd
->entity
.num_pads
)
329 return v4l2_subdev_call(sd
, pad
, enum_mbus_code
, subdev_fh
->pad
,
333 case VIDIOC_SUBDEV_ENUM_FRAME_SIZE
: {
334 struct v4l2_subdev_frame_size_enum
*fse
= arg
;
336 if (fse
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
337 fse
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
340 if (fse
->pad
>= sd
->entity
.num_pads
)
343 return v4l2_subdev_call(sd
, pad
, enum_frame_size
, subdev_fh
->pad
,
347 case VIDIOC_SUBDEV_G_FRAME_INTERVAL
: {
348 struct v4l2_subdev_frame_interval
*fi
= arg
;
350 if (fi
->pad
>= sd
->entity
.num_pads
)
353 return v4l2_subdev_call(sd
, video
, g_frame_interval
, arg
);
356 case VIDIOC_SUBDEV_S_FRAME_INTERVAL
: {
357 struct v4l2_subdev_frame_interval
*fi
= arg
;
359 if (fi
->pad
>= sd
->entity
.num_pads
)
362 return v4l2_subdev_call(sd
, video
, s_frame_interval
, arg
);
365 case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
: {
366 struct v4l2_subdev_frame_interval_enum
*fie
= arg
;
368 if (fie
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
369 fie
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
372 if (fie
->pad
>= sd
->entity
.num_pads
)
375 return v4l2_subdev_call(sd
, pad
, enum_frame_interval
, subdev_fh
->pad
,
379 case VIDIOC_SUBDEV_G_SELECTION
: {
380 struct v4l2_subdev_selection
*sel
= arg
;
382 rval
= check_selection(sd
, sel
);
386 return v4l2_subdev_call(
387 sd
, pad
, get_selection
, subdev_fh
->pad
, sel
);
390 case VIDIOC_SUBDEV_S_SELECTION
: {
391 struct v4l2_subdev_selection
*sel
= arg
;
393 rval
= check_selection(sd
, sel
);
397 return v4l2_subdev_call(
398 sd
, pad
, set_selection
, subdev_fh
->pad
, sel
);
401 case VIDIOC_G_EDID
: {
402 struct v4l2_subdev_edid
*edid
= arg
;
404 rval
= check_edid(sd
, edid
);
408 return v4l2_subdev_call(sd
, pad
, get_edid
, edid
);
411 case VIDIOC_S_EDID
: {
412 struct v4l2_subdev_edid
*edid
= arg
;
414 rval
= check_edid(sd
, edid
);
418 return v4l2_subdev_call(sd
, pad
, set_edid
, edid
);
421 case VIDIOC_SUBDEV_DV_TIMINGS_CAP
: {
422 struct v4l2_dv_timings_cap
*cap
= arg
;
424 if (cap
->pad
>= sd
->entity
.num_pads
)
427 return v4l2_subdev_call(sd
, pad
, dv_timings_cap
, cap
);
430 case VIDIOC_SUBDEV_ENUM_DV_TIMINGS
: {
431 struct v4l2_enum_dv_timings
*dvt
= arg
;
433 if (dvt
->pad
>= sd
->entity
.num_pads
)
436 return v4l2_subdev_call(sd
, pad
, enum_dv_timings
, dvt
);
439 case VIDIOC_SUBDEV_QUERY_DV_TIMINGS
:
440 return v4l2_subdev_call(sd
, video
, query_dv_timings
, arg
);
442 case VIDIOC_SUBDEV_G_DV_TIMINGS
:
443 return v4l2_subdev_call(sd
, video
, g_dv_timings
, arg
);
445 case VIDIOC_SUBDEV_S_DV_TIMINGS
:
446 return v4l2_subdev_call(sd
, video
, s_dv_timings
, arg
);
449 return v4l2_subdev_call(sd
, core
, ioctl
, cmd
, arg
);
455 static long subdev_ioctl(struct file
*file
, unsigned int cmd
,
458 return video_usercopy(file
, cmd
, arg
, subdev_do_ioctl
);
462 static long subdev_compat_ioctl32(struct file
*file
, unsigned int cmd
,
465 struct video_device
*vdev
= video_devdata(file
);
466 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
468 return v4l2_subdev_call(sd
, core
, compat_ioctl32
, cmd
, arg
);
472 static __poll_t
subdev_poll(struct file
*file
, poll_table
*wait
)
474 struct video_device
*vdev
= video_devdata(file
);
475 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
476 struct v4l2_fh
*fh
= file
->private_data
;
478 if (!(sd
->flags
& V4L2_SUBDEV_FL_HAS_EVENTS
))
481 poll_wait(file
, &fh
->wait
, wait
);
483 if (v4l2_event_pending(fh
))
489 const struct v4l2_file_operations v4l2_subdev_fops
= {
490 .owner
= THIS_MODULE
,
492 .unlocked_ioctl
= subdev_ioctl
,
494 .compat_ioctl32
= subdev_compat_ioctl32
,
496 .release
= subdev_close
,
500 #ifdef CONFIG_MEDIA_CONTROLLER
501 int v4l2_subdev_link_validate_default(struct v4l2_subdev
*sd
,
502 struct media_link
*link
,
503 struct v4l2_subdev_format
*source_fmt
,
504 struct v4l2_subdev_format
*sink_fmt
)
506 /* The width, height and code must match. */
507 if (source_fmt
->format
.width
!= sink_fmt
->format
.width
508 || source_fmt
->format
.height
!= sink_fmt
->format
.height
509 || source_fmt
->format
.code
!= sink_fmt
->format
.code
)
512 /* The field order must match, or the sink field order must be NONE
513 * to support interlaced hardware connected to bridges that support
514 * progressive formats only.
516 if (source_fmt
->format
.field
!= sink_fmt
->format
.field
&&
517 sink_fmt
->format
.field
!= V4L2_FIELD_NONE
)
522 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default
);
525 v4l2_subdev_link_validate_get_format(struct media_pad
*pad
,
526 struct v4l2_subdev_format
*fmt
)
528 if (is_media_entity_v4l2_subdev(pad
->entity
)) {
529 struct v4l2_subdev
*sd
=
530 media_entity_to_v4l2_subdev(pad
->entity
);
532 fmt
->which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
533 fmt
->pad
= pad
->index
;
534 return v4l2_subdev_call(sd
, pad
, get_fmt
, NULL
, fmt
);
537 WARN(pad
->entity
->function
!= MEDIA_ENT_F_IO_V4L
,
538 "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
539 pad
->entity
->function
, pad
->entity
->name
);
544 int v4l2_subdev_link_validate(struct media_link
*link
)
546 struct v4l2_subdev
*sink
;
547 struct v4l2_subdev_format sink_fmt
, source_fmt
;
550 rval
= v4l2_subdev_link_validate_get_format(
551 link
->source
, &source_fmt
);
555 rval
= v4l2_subdev_link_validate_get_format(
556 link
->sink
, &sink_fmt
);
560 sink
= media_entity_to_v4l2_subdev(link
->sink
->entity
);
562 rval
= v4l2_subdev_call(sink
, pad
, link_validate
, link
,
563 &source_fmt
, &sink_fmt
);
564 if (rval
!= -ENOIOCTLCMD
)
567 return v4l2_subdev_link_validate_default(
568 sink
, link
, &source_fmt
, &sink_fmt
);
570 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate
);
572 struct v4l2_subdev_pad_config
*
573 v4l2_subdev_alloc_pad_config(struct v4l2_subdev
*sd
)
575 struct v4l2_subdev_pad_config
*cfg
;
578 if (!sd
->entity
.num_pads
)
581 cfg
= kvmalloc_array(sd
->entity
.num_pads
, sizeof(*cfg
),
582 GFP_KERNEL
| __GFP_ZERO
);
586 ret
= v4l2_subdev_call(sd
, pad
, init_cfg
, cfg
);
587 if (ret
< 0 && ret
!= -ENOIOCTLCMD
) {
594 EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_pad_config
);
596 void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config
*cfg
)
600 EXPORT_SYMBOL_GPL(v4l2_subdev_free_pad_config
);
601 #endif /* CONFIG_MEDIA_CONTROLLER */
603 void v4l2_subdev_init(struct v4l2_subdev
*sd
, const struct v4l2_subdev_ops
*ops
)
605 INIT_LIST_HEAD(&sd
->list
);
613 sd
->host_priv
= NULL
;
614 #if defined(CONFIG_MEDIA_CONTROLLER)
615 sd
->entity
.name
= sd
->name
;
616 sd
->entity
.obj_type
= MEDIA_ENTITY_TYPE_V4L2_SUBDEV
;
617 sd
->entity
.function
= MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN
;
620 EXPORT_SYMBOL(v4l2_subdev_init
);
622 void v4l2_subdev_notify_event(struct v4l2_subdev
*sd
,
623 const struct v4l2_event
*ev
)
625 v4l2_event_queue(sd
->devnode
, ev
);
626 v4l2_subdev_notify(sd
, V4L2_DEVICE_NOTIFY_EVENT
, (void *)ev
);
628 EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event
);