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>
20 #include <linux/slab.h>
21 #include <linux/types.h>
22 #include <linux/videodev2.h>
23 #include <linux/export.h>
25 #include <media/v4l2-ctrls.h>
26 #include <media/v4l2-device.h>
27 #include <media/v4l2-ioctl.h>
28 #include <media/v4l2-fh.h>
29 #include <media/v4l2-event.h>
31 static int subdev_fh_init(struct v4l2_subdev_fh
*fh
, struct v4l2_subdev
*sd
)
33 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
34 if (sd
->entity
.num_pads
) {
35 fh
->pad
= v4l2_subdev_alloc_pad_config(sd
);
43 static void subdev_fh_free(struct v4l2_subdev_fh
*fh
)
45 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
46 v4l2_subdev_free_pad_config(fh
->pad
);
51 static int subdev_open(struct file
*file
)
53 struct video_device
*vdev
= video_devdata(file
);
54 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
55 struct v4l2_subdev_fh
*subdev_fh
;
56 #if defined(CONFIG_MEDIA_CONTROLLER)
57 struct media_entity
*entity
= NULL
;
61 subdev_fh
= kzalloc(sizeof(*subdev_fh
), GFP_KERNEL
);
62 if (subdev_fh
== NULL
)
65 ret
= subdev_fh_init(subdev_fh
, sd
);
71 v4l2_fh_init(&subdev_fh
->vfh
, vdev
);
72 v4l2_fh_add(&subdev_fh
->vfh
);
73 file
->private_data
= &subdev_fh
->vfh
;
74 #if defined(CONFIG_MEDIA_CONTROLLER)
75 if (sd
->v4l2_dev
->mdev
) {
76 entity
= media_entity_get(&sd
->entity
);
84 if (sd
->internal_ops
&& sd
->internal_ops
->open
) {
85 ret
= sd
->internal_ops
->open(sd
, subdev_fh
);
93 #if defined(CONFIG_MEDIA_CONTROLLER)
94 media_entity_put(entity
);
96 v4l2_fh_del(&subdev_fh
->vfh
);
97 v4l2_fh_exit(&subdev_fh
->vfh
);
98 subdev_fh_free(subdev_fh
);
104 static int subdev_close(struct file
*file
)
106 struct video_device
*vdev
= video_devdata(file
);
107 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
108 struct v4l2_fh
*vfh
= file
->private_data
;
109 struct v4l2_subdev_fh
*subdev_fh
= to_v4l2_subdev_fh(vfh
);
111 if (sd
->internal_ops
&& sd
->internal_ops
->close
)
112 sd
->internal_ops
->close(sd
, subdev_fh
);
113 #if defined(CONFIG_MEDIA_CONTROLLER)
114 if (sd
->v4l2_dev
->mdev
)
115 media_entity_put(&sd
->entity
);
119 subdev_fh_free(subdev_fh
);
121 file
->private_data
= NULL
;
126 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
127 static int check_format(struct v4l2_subdev
*sd
,
128 struct v4l2_subdev_format
*format
)
130 if (format
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
131 format
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
134 if (format
->pad
>= sd
->entity
.num_pads
)
140 static int check_crop(struct v4l2_subdev
*sd
, struct v4l2_subdev_crop
*crop
)
142 if (crop
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
143 crop
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
146 if (crop
->pad
>= sd
->entity
.num_pads
)
152 static int check_selection(struct v4l2_subdev
*sd
,
153 struct v4l2_subdev_selection
*sel
)
155 if (sel
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
156 sel
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
159 if (sel
->pad
>= sd
->entity
.num_pads
)
165 static int check_edid(struct v4l2_subdev
*sd
, struct v4l2_subdev_edid
*edid
)
167 if (edid
->pad
>= sd
->entity
.num_pads
)
170 if (edid
->blocks
&& edid
->edid
== NULL
)
177 static long subdev_do_ioctl(struct file
*file
, unsigned int cmd
, void *arg
)
179 struct video_device
*vdev
= video_devdata(file
);
180 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
181 struct v4l2_fh
*vfh
= file
->private_data
;
182 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
183 struct v4l2_subdev_fh
*subdev_fh
= to_v4l2_subdev_fh(vfh
);
188 case VIDIOC_QUERYCTRL
:
189 return v4l2_queryctrl(vfh
->ctrl_handler
, arg
);
191 case VIDIOC_QUERY_EXT_CTRL
:
192 return v4l2_query_ext_ctrl(vfh
->ctrl_handler
, arg
);
194 case VIDIOC_QUERYMENU
:
195 return v4l2_querymenu(vfh
->ctrl_handler
, arg
);
198 return v4l2_g_ctrl(vfh
->ctrl_handler
, arg
);
201 return v4l2_s_ctrl(vfh
, vfh
->ctrl_handler
, arg
);
203 case VIDIOC_G_EXT_CTRLS
:
204 return v4l2_g_ext_ctrls(vfh
->ctrl_handler
, arg
);
206 case VIDIOC_S_EXT_CTRLS
:
207 return v4l2_s_ext_ctrls(vfh
, vfh
->ctrl_handler
, arg
);
209 case VIDIOC_TRY_EXT_CTRLS
:
210 return v4l2_try_ext_ctrls(vfh
->ctrl_handler
, arg
);
213 if (!(sd
->flags
& V4L2_SUBDEV_FL_HAS_EVENTS
))
216 return v4l2_event_dequeue(vfh
, arg
, file
->f_flags
& O_NONBLOCK
);
218 case VIDIOC_SUBSCRIBE_EVENT
:
219 return v4l2_subdev_call(sd
, core
, subscribe_event
, vfh
, arg
);
221 case VIDIOC_UNSUBSCRIBE_EVENT
:
222 return v4l2_subdev_call(sd
, core
, unsubscribe_event
, vfh
, arg
);
224 #ifdef CONFIG_VIDEO_ADV_DEBUG
225 case VIDIOC_DBG_G_REGISTER
:
227 struct v4l2_dbg_register
*p
= arg
;
229 if (!capable(CAP_SYS_ADMIN
))
231 return v4l2_subdev_call(sd
, core
, g_register
, p
);
233 case VIDIOC_DBG_S_REGISTER
:
235 struct v4l2_dbg_register
*p
= arg
;
237 if (!capable(CAP_SYS_ADMIN
))
239 return v4l2_subdev_call(sd
, core
, s_register
, p
);
243 case VIDIOC_LOG_STATUS
: {
246 pr_info("%s: ================= START STATUS =================\n",
248 ret
= v4l2_subdev_call(sd
, core
, log_status
);
249 pr_info("%s: ================== END STATUS ==================\n",
254 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
255 case VIDIOC_SUBDEV_G_FMT
: {
256 struct v4l2_subdev_format
*format
= arg
;
258 rval
= check_format(sd
, format
);
262 return v4l2_subdev_call(sd
, pad
, get_fmt
, subdev_fh
->pad
, format
);
265 case VIDIOC_SUBDEV_S_FMT
: {
266 struct v4l2_subdev_format
*format
= arg
;
268 rval
= check_format(sd
, format
);
272 return v4l2_subdev_call(sd
, pad
, set_fmt
, subdev_fh
->pad
, format
);
275 case VIDIOC_SUBDEV_G_CROP
: {
276 struct v4l2_subdev_crop
*crop
= arg
;
277 struct v4l2_subdev_selection sel
;
279 rval
= check_crop(sd
, crop
);
283 memset(&sel
, 0, sizeof(sel
));
284 sel
.which
= crop
->which
;
286 sel
.target
= V4L2_SEL_TGT_CROP
;
288 rval
= v4l2_subdev_call(
289 sd
, pad
, get_selection
, subdev_fh
->pad
, &sel
);
296 case VIDIOC_SUBDEV_S_CROP
: {
297 struct v4l2_subdev_crop
*crop
= arg
;
298 struct v4l2_subdev_selection sel
;
300 rval
= check_crop(sd
, crop
);
304 memset(&sel
, 0, sizeof(sel
));
305 sel
.which
= crop
->which
;
307 sel
.target
= V4L2_SEL_TGT_CROP
;
310 rval
= v4l2_subdev_call(
311 sd
, pad
, set_selection
, subdev_fh
->pad
, &sel
);
318 case VIDIOC_SUBDEV_ENUM_MBUS_CODE
: {
319 struct v4l2_subdev_mbus_code_enum
*code
= arg
;
321 if (code
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
322 code
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
325 if (code
->pad
>= sd
->entity
.num_pads
)
328 return v4l2_subdev_call(sd
, pad
, enum_mbus_code
, subdev_fh
->pad
,
332 case VIDIOC_SUBDEV_ENUM_FRAME_SIZE
: {
333 struct v4l2_subdev_frame_size_enum
*fse
= arg
;
335 if (fse
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
336 fse
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
339 if (fse
->pad
>= sd
->entity
.num_pads
)
342 return v4l2_subdev_call(sd
, pad
, enum_frame_size
, subdev_fh
->pad
,
346 case VIDIOC_SUBDEV_G_FRAME_INTERVAL
: {
347 struct v4l2_subdev_frame_interval
*fi
= arg
;
349 if (fi
->pad
>= sd
->entity
.num_pads
)
352 return v4l2_subdev_call(sd
, video
, g_frame_interval
, arg
);
355 case VIDIOC_SUBDEV_S_FRAME_INTERVAL
: {
356 struct v4l2_subdev_frame_interval
*fi
= arg
;
358 if (fi
->pad
>= sd
->entity
.num_pads
)
361 return v4l2_subdev_call(sd
, video
, s_frame_interval
, arg
);
364 case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
: {
365 struct v4l2_subdev_frame_interval_enum
*fie
= arg
;
367 if (fie
->which
!= V4L2_SUBDEV_FORMAT_TRY
&&
368 fie
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
371 if (fie
->pad
>= sd
->entity
.num_pads
)
374 return v4l2_subdev_call(sd
, pad
, enum_frame_interval
, subdev_fh
->pad
,
378 case VIDIOC_SUBDEV_G_SELECTION
: {
379 struct v4l2_subdev_selection
*sel
= arg
;
381 rval
= check_selection(sd
, sel
);
385 return v4l2_subdev_call(
386 sd
, pad
, get_selection
, subdev_fh
->pad
, sel
);
389 case VIDIOC_SUBDEV_S_SELECTION
: {
390 struct v4l2_subdev_selection
*sel
= arg
;
392 rval
= check_selection(sd
, sel
);
396 return v4l2_subdev_call(
397 sd
, pad
, set_selection
, subdev_fh
->pad
, sel
);
400 case VIDIOC_G_EDID
: {
401 struct v4l2_subdev_edid
*edid
= arg
;
403 rval
= check_edid(sd
, edid
);
407 return v4l2_subdev_call(sd
, pad
, get_edid
, edid
);
410 case VIDIOC_S_EDID
: {
411 struct v4l2_subdev_edid
*edid
= arg
;
413 rval
= check_edid(sd
, edid
);
417 return v4l2_subdev_call(sd
, pad
, set_edid
, edid
);
420 case VIDIOC_SUBDEV_DV_TIMINGS_CAP
: {
421 struct v4l2_dv_timings_cap
*cap
= arg
;
423 if (cap
->pad
>= sd
->entity
.num_pads
)
426 return v4l2_subdev_call(sd
, pad
, dv_timings_cap
, cap
);
429 case VIDIOC_SUBDEV_ENUM_DV_TIMINGS
: {
430 struct v4l2_enum_dv_timings
*dvt
= arg
;
432 if (dvt
->pad
>= sd
->entity
.num_pads
)
435 return v4l2_subdev_call(sd
, pad
, enum_dv_timings
, dvt
);
438 case VIDIOC_SUBDEV_QUERY_DV_TIMINGS
:
439 return v4l2_subdev_call(sd
, video
, query_dv_timings
, arg
);
441 case VIDIOC_SUBDEV_G_DV_TIMINGS
:
442 return v4l2_subdev_call(sd
, video
, g_dv_timings
, arg
);
444 case VIDIOC_SUBDEV_S_DV_TIMINGS
:
445 return v4l2_subdev_call(sd
, video
, s_dv_timings
, arg
);
448 return v4l2_subdev_call(sd
, core
, ioctl
, cmd
, arg
);
454 static long subdev_ioctl(struct file
*file
, unsigned int cmd
,
457 return video_usercopy(file
, cmd
, arg
, subdev_do_ioctl
);
461 static long subdev_compat_ioctl32(struct file
*file
, unsigned int cmd
,
464 struct video_device
*vdev
= video_devdata(file
);
465 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
467 return v4l2_subdev_call(sd
, core
, compat_ioctl32
, cmd
, arg
);
471 static unsigned int subdev_poll(struct file
*file
, poll_table
*wait
)
473 struct video_device
*vdev
= video_devdata(file
);
474 struct v4l2_subdev
*sd
= vdev_to_v4l2_subdev(vdev
);
475 struct v4l2_fh
*fh
= file
->private_data
;
477 if (!(sd
->flags
& V4L2_SUBDEV_FL_HAS_EVENTS
))
480 poll_wait(file
, &fh
->wait
, wait
);
482 if (v4l2_event_pending(fh
))
488 const struct v4l2_file_operations v4l2_subdev_fops
= {
489 .owner
= THIS_MODULE
,
491 .unlocked_ioctl
= subdev_ioctl
,
493 .compat_ioctl32
= subdev_compat_ioctl32
,
495 .release
= subdev_close
,
499 #ifdef CONFIG_MEDIA_CONTROLLER
500 int v4l2_subdev_link_validate_default(struct v4l2_subdev
*sd
,
501 struct media_link
*link
,
502 struct v4l2_subdev_format
*source_fmt
,
503 struct v4l2_subdev_format
*sink_fmt
)
505 /* The width, height and code must match. */
506 if (source_fmt
->format
.width
!= sink_fmt
->format
.width
507 || source_fmt
->format
.height
!= sink_fmt
->format
.height
508 || source_fmt
->format
.code
!= sink_fmt
->format
.code
)
511 /* The field order must match, or the sink field order must be NONE
512 * to support interlaced hardware connected to bridges that support
513 * progressive formats only.
515 if (source_fmt
->format
.field
!= sink_fmt
->format
.field
&&
516 sink_fmt
->format
.field
!= V4L2_FIELD_NONE
)
521 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default
);
524 v4l2_subdev_link_validate_get_format(struct media_pad
*pad
,
525 struct v4l2_subdev_format
*fmt
)
527 if (is_media_entity_v4l2_subdev(pad
->entity
)) {
528 struct v4l2_subdev
*sd
=
529 media_entity_to_v4l2_subdev(pad
->entity
);
531 fmt
->which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
532 fmt
->pad
= pad
->index
;
533 return v4l2_subdev_call(sd
, pad
, get_fmt
, NULL
, fmt
);
536 WARN(pad
->entity
->function
!= MEDIA_ENT_F_IO_V4L
,
537 "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
538 pad
->entity
->function
, pad
->entity
->name
);
543 int v4l2_subdev_link_validate(struct media_link
*link
)
545 struct v4l2_subdev
*sink
;
546 struct v4l2_subdev_format sink_fmt
, source_fmt
;
549 rval
= v4l2_subdev_link_validate_get_format(
550 link
->source
, &source_fmt
);
554 rval
= v4l2_subdev_link_validate_get_format(
555 link
->sink
, &sink_fmt
);
559 sink
= media_entity_to_v4l2_subdev(link
->sink
->entity
);
561 rval
= v4l2_subdev_call(sink
, pad
, link_validate
, link
,
562 &source_fmt
, &sink_fmt
);
563 if (rval
!= -ENOIOCTLCMD
)
566 return v4l2_subdev_link_validate_default(
567 sink
, link
, &source_fmt
, &sink_fmt
);
569 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate
);
571 struct v4l2_subdev_pad_config
*
572 v4l2_subdev_alloc_pad_config(struct v4l2_subdev
*sd
)
574 struct v4l2_subdev_pad_config
*cfg
;
577 if (!sd
->entity
.num_pads
)
580 cfg
= kcalloc(sd
->entity
.num_pads
, sizeof(*cfg
), GFP_KERNEL
);
584 ret
= v4l2_subdev_call(sd
, pad
, init_cfg
, cfg
);
585 if (ret
< 0 && ret
!= -ENOIOCTLCMD
) {
592 EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_pad_config
);
594 void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config
*cfg
)
598 EXPORT_SYMBOL_GPL(v4l2_subdev_free_pad_config
);
599 #endif /* CONFIG_MEDIA_CONTROLLER */
601 void v4l2_subdev_init(struct v4l2_subdev
*sd
, const struct v4l2_subdev_ops
*ops
)
603 INIT_LIST_HEAD(&sd
->list
);
611 sd
->host_priv
= NULL
;
612 #if defined(CONFIG_MEDIA_CONTROLLER)
613 sd
->entity
.name
= sd
->name
;
614 sd
->entity
.obj_type
= MEDIA_ENTITY_TYPE_V4L2_SUBDEV
;
615 sd
->entity
.function
= MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN
;
618 EXPORT_SYMBOL(v4l2_subdev_init
);
620 void v4l2_subdev_notify_event(struct v4l2_subdev
*sd
,
621 const struct v4l2_event
*ev
)
623 v4l2_event_queue(sd
->devnode
, ev
);
624 v4l2_subdev_notify(sd
, V4L2_DEVICE_NOTIFY_EVENT
, (void *)ev
);
626 EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event
);