2 * Driver for Renesas R-Car VIN
4 * Copyright (C) 2016 Renesas Electronics Corp.
5 * Copyright (C) 2011-2013 Renesas Solutions Corp.
6 * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
7 * Copyright (C) 2008 Magnus Damm
9 * Based on the soc-camera rcar_vin driver
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
17 #include <linux/pm_runtime.h>
19 #include <media/v4l2-event.h>
20 #include <media/v4l2-ioctl.h>
21 #include <media/v4l2-rect.h>
25 #define RVIN_DEFAULT_FORMAT V4L2_PIX_FMT_YUYV
26 #define RVIN_MAX_WIDTH 2048
27 #define RVIN_MAX_HEIGHT 2048
29 /* -----------------------------------------------------------------------------
33 static const struct rvin_video_format rvin_formats
[] = {
35 .fourcc
= V4L2_PIX_FMT_NV16
,
39 .fourcc
= V4L2_PIX_FMT_YUYV
,
43 .fourcc
= V4L2_PIX_FMT_UYVY
,
47 .fourcc
= V4L2_PIX_FMT_RGB565
,
51 .fourcc
= V4L2_PIX_FMT_XRGB555
,
55 .fourcc
= V4L2_PIX_FMT_XBGR32
,
60 const struct rvin_video_format
*rvin_format_from_pixel(u32 pixelformat
)
64 for (i
= 0; i
< ARRAY_SIZE(rvin_formats
); i
++)
65 if (rvin_formats
[i
].fourcc
== pixelformat
)
66 return rvin_formats
+ i
;
71 static u32
rvin_format_bytesperline(struct v4l2_pix_format
*pix
)
73 const struct rvin_video_format
*fmt
;
75 fmt
= rvin_format_from_pixel(pix
->pixelformat
);
80 return pix
->width
* fmt
->bpp
;
83 static u32
rvin_format_sizeimage(struct v4l2_pix_format
*pix
)
85 if (pix
->pixelformat
== V4L2_PIX_FMT_NV16
)
86 return pix
->bytesperline
* pix
->height
* 2;
88 return pix
->bytesperline
* pix
->height
;
91 /* -----------------------------------------------------------------------------
95 static void rvin_reset_crop_compose(struct rvin_dev
*vin
)
97 vin
->crop
.top
= vin
->crop
.left
= 0;
98 vin
->crop
.width
= vin
->source
.width
;
99 vin
->crop
.height
= vin
->source
.height
;
101 vin
->compose
.top
= vin
->compose
.left
= 0;
102 vin
->compose
.width
= vin
->format
.width
;
103 vin
->compose
.height
= vin
->format
.height
;
106 static int rvin_reset_format(struct rvin_dev
*vin
)
108 struct v4l2_subdev_format fmt
= {
109 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
111 struct v4l2_mbus_framefmt
*mf
= &fmt
.format
;
114 fmt
.pad
= vin
->src_pad_idx
;
116 ret
= v4l2_subdev_call(vin_to_source(vin
), pad
, get_fmt
, NULL
, &fmt
);
120 vin
->format
.width
= mf
->width
;
121 vin
->format
.height
= mf
->height
;
122 vin
->format
.colorspace
= mf
->colorspace
;
123 vin
->format
.field
= mf
->field
;
126 * If the subdevice uses ALTERNATE field mode and G_STD is
127 * implemented use the VIN HW to combine the two fields to
128 * one INTERLACED frame. The ALTERNATE field mode can still
129 * be requested in S_FMT and be respected, this is just the
130 * default which is applied at probing or when S_STD is called.
132 if (vin
->format
.field
== V4L2_FIELD_ALTERNATE
&&
133 v4l2_subdev_has_op(vin_to_source(vin
), video
, g_std
))
134 vin
->format
.field
= V4L2_FIELD_INTERLACED
;
136 switch (vin
->format
.field
) {
138 case V4L2_FIELD_BOTTOM
:
139 case V4L2_FIELD_ALTERNATE
:
140 vin
->format
.height
/= 2;
142 case V4L2_FIELD_NONE
:
143 case V4L2_FIELD_INTERLACED_TB
:
144 case V4L2_FIELD_INTERLACED_BT
:
145 case V4L2_FIELD_INTERLACED
:
148 vin
->format
.field
= V4L2_FIELD_NONE
;
152 rvin_reset_crop_compose(vin
);
157 static int __rvin_try_format_source(struct rvin_dev
*vin
,
159 struct v4l2_pix_format
*pix
,
160 struct rvin_source_fmt
*source
)
162 struct v4l2_subdev
*sd
;
163 struct v4l2_subdev_pad_config
*pad_cfg
;
164 struct v4l2_subdev_format format
= {
167 enum v4l2_field field
;
170 sd
= vin_to_source(vin
);
172 v4l2_fill_mbus_format(&format
.format
, pix
, vin
->digital
.code
);
174 pad_cfg
= v4l2_subdev_alloc_pad_config(sd
);
178 format
.pad
= vin
->src_pad_idx
;
182 ret
= v4l2_subdev_call(sd
, pad
, set_fmt
, pad_cfg
, &format
);
183 if (ret
< 0 && ret
!= -ENOIOCTLCMD
)
186 v4l2_fill_pix_format(pix
, &format
.format
);
190 source
->width
= pix
->width
;
191 source
->height
= pix
->height
;
193 vin_dbg(vin
, "Source resolution: %ux%u\n", source
->width
,
197 v4l2_subdev_free_pad_config(pad_cfg
);
201 static int __rvin_try_format(struct rvin_dev
*vin
,
203 struct v4l2_pix_format
*pix
,
204 struct rvin_source_fmt
*source
)
206 const struct rvin_video_format
*info
;
207 u32 rwidth
, rheight
, walign
;
211 rheight
= pix
->height
;
213 /* Keep current field if no specific one is asked for */
214 if (pix
->field
== V4L2_FIELD_ANY
)
215 pix
->field
= vin
->format
.field
;
218 * Retrieve format information and select the current format if the
219 * requested format isn't supported.
221 info
= rvin_format_from_pixel(pix
->pixelformat
);
223 vin_dbg(vin
, "Format %x not found, keeping %x\n",
224 pix
->pixelformat
, vin
->format
.pixelformat
);
227 pix
->height
= rheight
;
230 /* Always recalculate */
231 pix
->bytesperline
= 0;
234 /* Limit to source capabilities */
235 __rvin_try_format_source(vin
, which
, pix
, source
);
237 switch (pix
->field
) {
239 case V4L2_FIELD_BOTTOM
:
240 case V4L2_FIELD_ALTERNATE
:
244 case V4L2_FIELD_NONE
:
245 case V4L2_FIELD_INTERLACED_TB
:
246 case V4L2_FIELD_INTERLACED_BT
:
247 case V4L2_FIELD_INTERLACED
:
250 pix
->field
= V4L2_FIELD_NONE
;
254 /* If source can't match format try if VIN can scale */
255 if (source
->width
!= rwidth
|| source
->height
!= rheight
)
256 rvin_scale_try(vin
, pix
, rwidth
, rheight
);
258 /* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
259 walign
= vin
->format
.pixelformat
== V4L2_PIX_FMT_NV16
? 5 : 1;
261 /* Limit to VIN capabilities */
262 v4l_bound_align_image(&pix
->width
, 2, RVIN_MAX_WIDTH
, walign
,
263 &pix
->height
, 4, RVIN_MAX_HEIGHT
, 2, 0);
265 pix
->bytesperline
= max_t(u32
, pix
->bytesperline
,
266 rvin_format_bytesperline(pix
));
267 pix
->sizeimage
= max_t(u32
, pix
->sizeimage
,
268 rvin_format_sizeimage(pix
));
270 if (vin
->chip
== RCAR_M1
&& pix
->pixelformat
== V4L2_PIX_FMT_XBGR32
) {
271 vin_err(vin
, "pixel format XBGR32 not supported on M1\n");
275 vin_dbg(vin
, "Requested %ux%u Got %ux%u bpl: %d size: %d\n",
276 rwidth
, rheight
, pix
->width
, pix
->height
,
277 pix
->bytesperline
, pix
->sizeimage
);
282 static int rvin_querycap(struct file
*file
, void *priv
,
283 struct v4l2_capability
*cap
)
285 struct rvin_dev
*vin
= video_drvdata(file
);
287 strlcpy(cap
->driver
, KBUILD_MODNAME
, sizeof(cap
->driver
));
288 strlcpy(cap
->card
, "R_Car_VIN", sizeof(cap
->card
));
289 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
), "platform:%s",
294 static int rvin_try_fmt_vid_cap(struct file
*file
, void *priv
,
295 struct v4l2_format
*f
)
297 struct rvin_dev
*vin
= video_drvdata(file
);
298 struct rvin_source_fmt source
;
300 return __rvin_try_format(vin
, V4L2_SUBDEV_FORMAT_TRY
, &f
->fmt
.pix
,
304 static int rvin_s_fmt_vid_cap(struct file
*file
, void *priv
,
305 struct v4l2_format
*f
)
307 struct rvin_dev
*vin
= video_drvdata(file
);
308 struct rvin_source_fmt source
;
311 if (vb2_is_busy(&vin
->queue
))
314 ret
= __rvin_try_format(vin
, V4L2_SUBDEV_FORMAT_ACTIVE
, &f
->fmt
.pix
,
319 vin
->source
.width
= source
.width
;
320 vin
->source
.height
= source
.height
;
322 vin
->format
= f
->fmt
.pix
;
324 rvin_reset_crop_compose(vin
);
329 static int rvin_g_fmt_vid_cap(struct file
*file
, void *priv
,
330 struct v4l2_format
*f
)
332 struct rvin_dev
*vin
= video_drvdata(file
);
334 f
->fmt
.pix
= vin
->format
;
339 static int rvin_enum_fmt_vid_cap(struct file
*file
, void *priv
,
340 struct v4l2_fmtdesc
*f
)
342 if (f
->index
>= ARRAY_SIZE(rvin_formats
))
345 f
->pixelformat
= rvin_formats
[f
->index
].fourcc
;
350 static int rvin_g_selection(struct file
*file
, void *fh
,
351 struct v4l2_selection
*s
)
353 struct rvin_dev
*vin
= video_drvdata(file
);
355 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
359 case V4L2_SEL_TGT_CROP_BOUNDS
:
360 case V4L2_SEL_TGT_CROP_DEFAULT
:
361 s
->r
.left
= s
->r
.top
= 0;
362 s
->r
.width
= vin
->source
.width
;
363 s
->r
.height
= vin
->source
.height
;
365 case V4L2_SEL_TGT_CROP
:
368 case V4L2_SEL_TGT_COMPOSE_BOUNDS
:
369 case V4L2_SEL_TGT_COMPOSE_DEFAULT
:
370 s
->r
.left
= s
->r
.top
= 0;
371 s
->r
.width
= vin
->format
.width
;
372 s
->r
.height
= vin
->format
.height
;
374 case V4L2_SEL_TGT_COMPOSE
:
384 static int rvin_s_selection(struct file
*file
, void *fh
,
385 struct v4l2_selection
*s
)
387 struct rvin_dev
*vin
= video_drvdata(file
);
388 const struct rvin_video_format
*fmt
;
389 struct v4l2_rect r
= s
->r
;
390 struct v4l2_rect max_rect
;
391 struct v4l2_rect min_rect
= {
396 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
399 v4l2_rect_set_min_size(&r
, &min_rect
);
402 case V4L2_SEL_TGT_CROP
:
403 /* Can't crop outside of source input */
404 max_rect
.top
= max_rect
.left
= 0;
405 max_rect
.width
= vin
->source
.width
;
406 max_rect
.height
= vin
->source
.height
;
407 v4l2_rect_map_inside(&r
, &max_rect
);
409 v4l_bound_align_image(&r
.width
, 2, vin
->source
.width
, 1,
410 &r
.height
, 4, vin
->source
.height
, 2, 0);
412 r
.top
= clamp_t(s32
, r
.top
, 0, vin
->source
.height
- r
.height
);
413 r
.left
= clamp_t(s32
, r
.left
, 0, vin
->source
.width
- r
.width
);
415 vin
->crop
= s
->r
= r
;
417 vin_dbg(vin
, "Cropped %dx%d@%d:%d of %dx%d\n",
418 r
.width
, r
.height
, r
.left
, r
.top
,
419 vin
->source
.width
, vin
->source
.height
);
421 case V4L2_SEL_TGT_COMPOSE
:
422 /* Make sure compose rect fits inside output format */
423 max_rect
.top
= max_rect
.left
= 0;
424 max_rect
.width
= vin
->format
.width
;
425 max_rect
.height
= vin
->format
.height
;
426 v4l2_rect_map_inside(&r
, &max_rect
);
429 * Composing is done by adding a offset to the buffer address,
430 * the HW wants this address to be aligned to HW_BUFFER_MASK.
431 * Make sure the top and left values meets this requirement.
433 while ((r
.top
* vin
->format
.bytesperline
) & HW_BUFFER_MASK
)
436 fmt
= rvin_format_from_pixel(vin
->format
.pixelformat
);
437 while ((r
.left
* fmt
->bpp
) & HW_BUFFER_MASK
)
440 vin
->compose
= s
->r
= r
;
442 vin_dbg(vin
, "Compose %dx%d@%d:%d in %dx%d\n",
443 r
.width
, r
.height
, r
.left
, r
.top
,
444 vin
->format
.width
, vin
->format
.height
);
450 /* HW supports modifying configuration while running */
451 rvin_crop_scale_comp(vin
);
456 static int rvin_cropcap(struct file
*file
, void *priv
,
457 struct v4l2_cropcap
*crop
)
459 struct rvin_dev
*vin
= video_drvdata(file
);
460 struct v4l2_subdev
*sd
= vin_to_source(vin
);
462 if (crop
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
465 return v4l2_subdev_call(sd
, video
, g_pixelaspect
, &crop
->pixelaspect
);
468 static int rvin_enum_input(struct file
*file
, void *priv
,
469 struct v4l2_input
*i
)
471 struct rvin_dev
*vin
= video_drvdata(file
);
472 struct v4l2_subdev
*sd
= vin_to_source(vin
);
478 ret
= v4l2_subdev_call(sd
, video
, g_input_status
, &i
->status
);
479 if (ret
< 0 && ret
!= -ENOIOCTLCMD
&& ret
!= -ENODEV
)
482 i
->type
= V4L2_INPUT_TYPE_CAMERA
;
483 i
->std
= vin
->vdev
.tvnorms
;
485 if (v4l2_subdev_has_op(sd
, pad
, dv_timings_cap
))
486 i
->capabilities
= V4L2_IN_CAP_DV_TIMINGS
;
488 strlcpy(i
->name
, "Camera", sizeof(i
->name
));
493 static int rvin_g_input(struct file
*file
, void *priv
, unsigned int *i
)
499 static int rvin_s_input(struct file
*file
, void *priv
, unsigned int i
)
506 static int rvin_querystd(struct file
*file
, void *priv
, v4l2_std_id
*a
)
508 struct rvin_dev
*vin
= video_drvdata(file
);
509 struct v4l2_subdev
*sd
= vin_to_source(vin
);
511 return v4l2_subdev_call(sd
, video
, querystd
, a
);
514 static int rvin_s_std(struct file
*file
, void *priv
, v4l2_std_id a
)
516 struct rvin_dev
*vin
= video_drvdata(file
);
519 ret
= v4l2_subdev_call(vin_to_source(vin
), video
, s_std
, a
);
523 /* Changing the standard will change the width/height */
524 return rvin_reset_format(vin
);
527 static int rvin_g_std(struct file
*file
, void *priv
, v4l2_std_id
*a
)
529 struct rvin_dev
*vin
= video_drvdata(file
);
530 struct v4l2_subdev
*sd
= vin_to_source(vin
);
532 return v4l2_subdev_call(sd
, video
, g_std
, a
);
535 static int rvin_subscribe_event(struct v4l2_fh
*fh
,
536 const struct v4l2_event_subscription
*sub
)
539 case V4L2_EVENT_SOURCE_CHANGE
:
540 return v4l2_event_subscribe(fh
, sub
, 4, NULL
);
542 return v4l2_ctrl_subscribe_event(fh
, sub
);
545 static int rvin_enum_dv_timings(struct file
*file
, void *priv_fh
,
546 struct v4l2_enum_dv_timings
*timings
)
548 struct rvin_dev
*vin
= video_drvdata(file
);
549 struct v4l2_subdev
*sd
= vin_to_source(vin
);
553 timings
->pad
= vin
->sink_pad_idx
;
555 ret
= v4l2_subdev_call(sd
, pad
, enum_dv_timings
, timings
);
562 static int rvin_s_dv_timings(struct file
*file
, void *priv_fh
,
563 struct v4l2_dv_timings
*timings
)
565 struct rvin_dev
*vin
= video_drvdata(file
);
566 struct v4l2_subdev
*sd
= vin_to_source(vin
);
569 ret
= v4l2_subdev_call(sd
, video
, s_dv_timings
, timings
);
573 vin
->source
.width
= timings
->bt
.width
;
574 vin
->source
.height
= timings
->bt
.height
;
575 vin
->format
.width
= timings
->bt
.width
;
576 vin
->format
.height
= timings
->bt
.height
;
581 static int rvin_g_dv_timings(struct file
*file
, void *priv_fh
,
582 struct v4l2_dv_timings
*timings
)
584 struct rvin_dev
*vin
= video_drvdata(file
);
585 struct v4l2_subdev
*sd
= vin_to_source(vin
);
587 return v4l2_subdev_call(sd
, video
, g_dv_timings
, timings
);
590 static int rvin_query_dv_timings(struct file
*file
, void *priv_fh
,
591 struct v4l2_dv_timings
*timings
)
593 struct rvin_dev
*vin
= video_drvdata(file
);
594 struct v4l2_subdev
*sd
= vin_to_source(vin
);
596 return v4l2_subdev_call(sd
, video
, query_dv_timings
, timings
);
599 static int rvin_dv_timings_cap(struct file
*file
, void *priv_fh
,
600 struct v4l2_dv_timings_cap
*cap
)
602 struct rvin_dev
*vin
= video_drvdata(file
);
603 struct v4l2_subdev
*sd
= vin_to_source(vin
);
607 cap
->pad
= vin
->sink_pad_idx
;
609 ret
= v4l2_subdev_call(sd
, pad
, dv_timings_cap
, cap
);
616 static int rvin_g_edid(struct file
*file
, void *fh
, struct v4l2_edid
*edid
)
618 struct rvin_dev
*vin
= video_drvdata(file
);
619 struct v4l2_subdev
*sd
= vin_to_source(vin
);
626 edid
->pad
= vin
->sink_pad_idx
;
628 ret
= v4l2_subdev_call(sd
, pad
, get_edid
, edid
);
635 static int rvin_s_edid(struct file
*file
, void *fh
, struct v4l2_edid
*edid
)
637 struct rvin_dev
*vin
= video_drvdata(file
);
638 struct v4l2_subdev
*sd
= vin_to_source(vin
);
645 edid
->pad
= vin
->sink_pad_idx
;
647 ret
= v4l2_subdev_call(sd
, pad
, set_edid
, edid
);
654 static const struct v4l2_ioctl_ops rvin_ioctl_ops
= {
655 .vidioc_querycap
= rvin_querycap
,
656 .vidioc_try_fmt_vid_cap
= rvin_try_fmt_vid_cap
,
657 .vidioc_g_fmt_vid_cap
= rvin_g_fmt_vid_cap
,
658 .vidioc_s_fmt_vid_cap
= rvin_s_fmt_vid_cap
,
659 .vidioc_enum_fmt_vid_cap
= rvin_enum_fmt_vid_cap
,
661 .vidioc_g_selection
= rvin_g_selection
,
662 .vidioc_s_selection
= rvin_s_selection
,
664 .vidioc_cropcap
= rvin_cropcap
,
666 .vidioc_enum_input
= rvin_enum_input
,
667 .vidioc_g_input
= rvin_g_input
,
668 .vidioc_s_input
= rvin_s_input
,
670 .vidioc_dv_timings_cap
= rvin_dv_timings_cap
,
671 .vidioc_enum_dv_timings
= rvin_enum_dv_timings
,
672 .vidioc_g_dv_timings
= rvin_g_dv_timings
,
673 .vidioc_s_dv_timings
= rvin_s_dv_timings
,
674 .vidioc_query_dv_timings
= rvin_query_dv_timings
,
676 .vidioc_g_edid
= rvin_g_edid
,
677 .vidioc_s_edid
= rvin_s_edid
,
679 .vidioc_querystd
= rvin_querystd
,
680 .vidioc_g_std
= rvin_g_std
,
681 .vidioc_s_std
= rvin_s_std
,
683 .vidioc_reqbufs
= vb2_ioctl_reqbufs
,
684 .vidioc_create_bufs
= vb2_ioctl_create_bufs
,
685 .vidioc_querybuf
= vb2_ioctl_querybuf
,
686 .vidioc_qbuf
= vb2_ioctl_qbuf
,
687 .vidioc_dqbuf
= vb2_ioctl_dqbuf
,
688 .vidioc_expbuf
= vb2_ioctl_expbuf
,
689 .vidioc_prepare_buf
= vb2_ioctl_prepare_buf
,
690 .vidioc_streamon
= vb2_ioctl_streamon
,
691 .vidioc_streamoff
= vb2_ioctl_streamoff
,
693 .vidioc_log_status
= v4l2_ctrl_log_status
,
694 .vidioc_subscribe_event
= rvin_subscribe_event
,
695 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
698 /* -----------------------------------------------------------------------------
702 static int rvin_power_on(struct rvin_dev
*vin
)
705 struct v4l2_subdev
*sd
= vin_to_source(vin
);
707 pm_runtime_get_sync(vin
->v4l2_dev
.dev
);
709 ret
= v4l2_subdev_call(sd
, core
, s_power
, 1);
710 if (ret
< 0 && ret
!= -ENOIOCTLCMD
&& ret
!= -ENODEV
)
715 static int rvin_power_off(struct rvin_dev
*vin
)
718 struct v4l2_subdev
*sd
= vin_to_source(vin
);
720 ret
= v4l2_subdev_call(sd
, core
, s_power
, 0);
722 pm_runtime_put(vin
->v4l2_dev
.dev
);
724 if (ret
< 0 && ret
!= -ENOIOCTLCMD
&& ret
!= -ENODEV
)
730 static int rvin_initialize_device(struct file
*file
)
732 struct rvin_dev
*vin
= video_drvdata(file
);
735 struct v4l2_format f
= {
736 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
,
738 .width
= vin
->format
.width
,
739 .height
= vin
->format
.height
,
740 .field
= vin
->format
.field
,
741 .colorspace
= vin
->format
.colorspace
,
742 .pixelformat
= vin
->format
.pixelformat
,
746 ret
= rvin_power_on(vin
);
750 pm_runtime_enable(&vin
->vdev
.dev
);
751 ret
= pm_runtime_resume(&vin
->vdev
.dev
);
752 if (ret
< 0 && ret
!= -ENOSYS
)
756 * Try to configure with default parameters. Notice: this is the
757 * very first open, so, we cannot race against other calls,
758 * apart from someone else calling open() simultaneously, but
759 * .host_lock is protecting us against it.
761 ret
= rvin_s_fmt_vid_cap(file
, NULL
, &f
);
765 v4l2_ctrl_handler_setup(&vin
->ctrl_handler
);
769 pm_runtime_disable(&vin
->vdev
.dev
);
776 static int rvin_open(struct file
*file
)
778 struct rvin_dev
*vin
= video_drvdata(file
);
781 mutex_lock(&vin
->lock
);
783 file
->private_data
= vin
;
785 ret
= v4l2_fh_open(file
);
789 if (!v4l2_fh_is_singular_file(file
))
792 if (rvin_initialize_device(file
)) {
793 v4l2_fh_release(file
);
798 mutex_unlock(&vin
->lock
);
802 static int rvin_release(struct file
*file
)
804 struct rvin_dev
*vin
= video_drvdata(file
);
808 mutex_lock(&vin
->lock
);
810 /* Save the singular status before we call the clean-up helper */
811 fh_singular
= v4l2_fh_is_singular_file(file
);
813 /* the release helper will cleanup any on-going streaming */
814 ret
= _vb2_fop_release(file
, NULL
);
817 * If this was the last open file.
818 * Then de-initialize hw module.
821 pm_runtime_suspend(&vin
->vdev
.dev
);
822 pm_runtime_disable(&vin
->vdev
.dev
);
826 mutex_unlock(&vin
->lock
);
831 static const struct v4l2_file_operations rvin_fops
= {
832 .owner
= THIS_MODULE
,
833 .unlocked_ioctl
= video_ioctl2
,
835 .release
= rvin_release
,
836 .poll
= vb2_fop_poll
,
837 .mmap
= vb2_fop_mmap
,
838 .read
= vb2_fop_read
,
841 void rvin_v4l2_remove(struct rvin_dev
*vin
)
843 v4l2_info(&vin
->v4l2_dev
, "Removing %s\n",
844 video_device_node_name(&vin
->vdev
));
846 /* Checks internaly if handlers have been init or not */
847 v4l2_ctrl_handler_free(&vin
->ctrl_handler
);
849 /* Checks internaly if vdev have been init or not */
850 video_unregister_device(&vin
->vdev
);
853 static void rvin_notify(struct v4l2_subdev
*sd
,
854 unsigned int notification
, void *arg
)
856 struct rvin_dev
*vin
=
857 container_of(sd
->v4l2_dev
, struct rvin_dev
, v4l2_dev
);
859 switch (notification
) {
860 case V4L2_DEVICE_NOTIFY_EVENT
:
861 v4l2_event_queue(&vin
->vdev
, arg
);
868 int rvin_v4l2_probe(struct rvin_dev
*vin
)
870 struct video_device
*vdev
= &vin
->vdev
;
871 struct v4l2_subdev
*sd
= vin_to_source(vin
);
874 v4l2_set_subdev_hostdata(sd
, vin
);
876 vin
->v4l2_dev
.notify
= rvin_notify
;
878 ret
= v4l2_subdev_call(sd
, video
, g_tvnorms
, &vin
->vdev
.tvnorms
);
879 if (ret
< 0 && ret
!= -ENOIOCTLCMD
&& ret
!= -ENODEV
)
882 if (vin
->vdev
.tvnorms
== 0) {
883 /* Disable the STD API if there are no tvnorms defined */
884 v4l2_disable_ioctl(&vin
->vdev
, VIDIOC_G_STD
);
885 v4l2_disable_ioctl(&vin
->vdev
, VIDIOC_S_STD
);
886 v4l2_disable_ioctl(&vin
->vdev
, VIDIOC_QUERYSTD
);
887 v4l2_disable_ioctl(&vin
->vdev
, VIDIOC_ENUMSTD
);
890 /* Add the controls */
892 * Currently the subdev with the largest number of controls (13) is
893 * ov6550. So let's pick 16 as a hint for the control handler. Note
894 * that this is a hint only: too large and you waste some memory, too
895 * small and there is a (very) small performance hit when looking up
896 * controls in the internal hash.
898 ret
= v4l2_ctrl_handler_init(&vin
->ctrl_handler
, 16);
902 ret
= v4l2_ctrl_add_handler(&vin
->ctrl_handler
, sd
->ctrl_handler
, NULL
);
907 vdev
->fops
= &rvin_fops
;
908 vdev
->v4l2_dev
= &vin
->v4l2_dev
;
909 vdev
->queue
= &vin
->queue
;
910 strlcpy(vdev
->name
, KBUILD_MODNAME
, sizeof(vdev
->name
));
911 vdev
->release
= video_device_release_empty
;
912 vdev
->ioctl_ops
= &rvin_ioctl_ops
;
913 vdev
->lock
= &vin
->lock
;
914 vdev
->ctrl_handler
= &vin
->ctrl_handler
;
915 vdev
->device_caps
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING
|
918 vin
->src_pad_idx
= 0;
919 for (pad_idx
= 0; pad_idx
< sd
->entity
.num_pads
; pad_idx
++)
920 if (sd
->entity
.pads
[pad_idx
].flags
== MEDIA_PAD_FL_SOURCE
)
922 if (pad_idx
>= sd
->entity
.num_pads
)
925 vin
->src_pad_idx
= pad_idx
;
927 vin
->sink_pad_idx
= 0;
928 for (pad_idx
= 0; pad_idx
< sd
->entity
.num_pads
; pad_idx
++)
929 if (sd
->entity
.pads
[pad_idx
].flags
== MEDIA_PAD_FL_SINK
) {
930 vin
->sink_pad_idx
= pad_idx
;
934 vin
->format
.pixelformat
= RVIN_DEFAULT_FORMAT
;
935 rvin_reset_format(vin
);
937 ret
= video_register_device(&vin
->vdev
, VFL_TYPE_GRABBER
, -1);
939 vin_err(vin
, "Failed to register video device\n");
943 video_set_drvdata(&vin
->vdev
, vin
);
945 v4l2_info(&vin
->v4l2_dev
, "Device registered as %s\n",
946 video_device_node_name(&vin
->vdev
));