1 // SPDX-License-Identifier: GPL-2.0+
3 * Driver for Renesas R-Car VIN
5 * Copyright (C) 2016 Renesas Electronics Corp.
6 * Copyright (C) 2011-2013 Renesas Solutions Corp.
7 * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
8 * Copyright (C) 2008 Magnus Damm
10 * Based on the soc-camera rcar_vin driver
13 #include <linux/pm_runtime.h>
15 #include <media/v4l2-event.h>
16 #include <media/v4l2-ioctl.h>
17 #include <media/v4l2-mc.h>
18 #include <media/v4l2-rect.h>
22 #define RVIN_DEFAULT_FORMAT V4L2_PIX_FMT_YUYV
23 #define RVIN_DEFAULT_WIDTH 800
24 #define RVIN_DEFAULT_HEIGHT 600
25 #define RVIN_DEFAULT_FIELD V4L2_FIELD_NONE
26 #define RVIN_DEFAULT_COLORSPACE V4L2_COLORSPACE_SRGB
28 /* -----------------------------------------------------------------------------
32 static const struct rvin_video_format rvin_formats
[] = {
34 .fourcc
= V4L2_PIX_FMT_NV12
,
38 .fourcc
= V4L2_PIX_FMT_NV16
,
42 .fourcc
= V4L2_PIX_FMT_YUYV
,
46 .fourcc
= V4L2_PIX_FMT_UYVY
,
50 .fourcc
= V4L2_PIX_FMT_RGB565
,
54 .fourcc
= V4L2_PIX_FMT_XRGB555
,
58 .fourcc
= V4L2_PIX_FMT_XBGR32
,
62 .fourcc
= V4L2_PIX_FMT_ARGB555
,
66 .fourcc
= V4L2_PIX_FMT_ABGR32
,
70 .fourcc
= V4L2_PIX_FMT_SBGGR8
,
74 .fourcc
= V4L2_PIX_FMT_SGBRG8
,
78 .fourcc
= V4L2_PIX_FMT_SGRBG8
,
82 .fourcc
= V4L2_PIX_FMT_SRGGB8
,
87 const struct rvin_video_format
*rvin_format_from_pixel(struct rvin_dev
*vin
,
92 switch (pixelformat
) {
93 case V4L2_PIX_FMT_XBGR32
:
94 if (vin
->info
->model
== RCAR_M1
)
97 case V4L2_PIX_FMT_NV12
:
99 * If NV12 is supported it's only supported on channels 0, 1, 4,
100 * 5, 8, 9, 12 and 13.
102 if (!vin
->info
->nv12
|| !(BIT(vin
->id
) & 0x3333))
109 for (i
= 0; i
< ARRAY_SIZE(rvin_formats
); i
++)
110 if (rvin_formats
[i
].fourcc
== pixelformat
)
111 return rvin_formats
+ i
;
116 static u32
rvin_format_bytesperline(struct rvin_dev
*vin
,
117 struct v4l2_pix_format
*pix
)
119 const struct rvin_video_format
*fmt
;
122 fmt
= rvin_format_from_pixel(vin
, pix
->pixelformat
);
127 switch (pix
->pixelformat
) {
128 case V4L2_PIX_FMT_NV12
:
129 case V4L2_PIX_FMT_NV16
:
137 if (V4L2_FIELD_IS_SEQUENTIAL(pix
->field
))
140 return ALIGN(pix
->width
, align
) * fmt
->bpp
;
143 static u32
rvin_format_sizeimage(struct v4l2_pix_format
*pix
)
145 switch (pix
->pixelformat
) {
146 case V4L2_PIX_FMT_NV12
:
147 return pix
->bytesperline
* pix
->height
* 3 / 2;
148 case V4L2_PIX_FMT_NV16
:
149 return pix
->bytesperline
* pix
->height
* 2;
151 return pix
->bytesperline
* pix
->height
;
155 static void rvin_format_align(struct rvin_dev
*vin
, struct v4l2_pix_format
*pix
)
159 if (!rvin_format_from_pixel(vin
, pix
->pixelformat
))
160 pix
->pixelformat
= RVIN_DEFAULT_FORMAT
;
162 switch (pix
->field
) {
164 case V4L2_FIELD_BOTTOM
:
165 case V4L2_FIELD_NONE
:
166 case V4L2_FIELD_INTERLACED_TB
:
167 case V4L2_FIELD_INTERLACED_BT
:
168 case V4L2_FIELD_INTERLACED
:
169 case V4L2_FIELD_ALTERNATE
:
170 case V4L2_FIELD_SEQ_TB
:
171 case V4L2_FIELD_SEQ_BT
:
174 pix
->field
= RVIN_DEFAULT_FIELD
;
178 /* HW limit width to a multiple of 32 (2^5) for NV12/16 else 2 (2^1) */
179 switch (pix
->pixelformat
) {
180 case V4L2_PIX_FMT_NV12
:
181 case V4L2_PIX_FMT_NV16
:
189 /* Limit to VIN capabilities */
190 v4l_bound_align_image(&pix
->width
, 2, vin
->info
->max_width
, walign
,
191 &pix
->height
, 4, vin
->info
->max_height
, 2, 0);
193 pix
->bytesperline
= rvin_format_bytesperline(vin
, pix
);
194 pix
->sizeimage
= rvin_format_sizeimage(pix
);
196 vin_dbg(vin
, "Format %ux%u bpl: %u size: %u\n",
197 pix
->width
, pix
->height
, pix
->bytesperline
, pix
->sizeimage
);
200 /* -----------------------------------------------------------------------------
204 static int rvin_reset_format(struct rvin_dev
*vin
)
206 struct v4l2_subdev_format fmt
= {
207 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
208 .pad
= vin
->parallel
.source_pad
,
212 ret
= v4l2_subdev_call(vin_to_source(vin
), pad
, get_fmt
, NULL
, &fmt
);
216 v4l2_fill_pix_format(&vin
->format
, &fmt
.format
);
218 vin
->src_rect
.top
= 0;
219 vin
->src_rect
.left
= 0;
220 vin
->src_rect
.width
= vin
->format
.width
;
221 vin
->src_rect
.height
= vin
->format
.height
;
223 /* Make use of the hardware interlacer by default. */
224 if (vin
->format
.field
== V4L2_FIELD_ALTERNATE
) {
225 vin
->format
.field
= V4L2_FIELD_INTERLACED
;
226 vin
->format
.height
*= 2;
229 rvin_format_align(vin
, &vin
->format
);
231 vin
->crop
= vin
->src_rect
;
233 vin
->compose
.top
= 0;
234 vin
->compose
.left
= 0;
235 vin
->compose
.width
= vin
->format
.width
;
236 vin
->compose
.height
= vin
->format
.height
;
241 static int rvin_try_format(struct rvin_dev
*vin
, u32 which
,
242 struct v4l2_pix_format
*pix
,
243 struct v4l2_rect
*src_rect
)
245 struct v4l2_subdev
*sd
= vin_to_source(vin
);
246 struct v4l2_subdev_pad_config
*pad_cfg
;
247 struct v4l2_subdev_format format
= {
249 .pad
= vin
->parallel
.source_pad
,
251 enum v4l2_field field
;
255 pad_cfg
= v4l2_subdev_alloc_pad_config(sd
);
259 if (!rvin_format_from_pixel(vin
, pix
->pixelformat
))
260 pix
->pixelformat
= RVIN_DEFAULT_FORMAT
;
262 v4l2_fill_mbus_format(&format
.format
, pix
, vin
->mbus_code
);
264 /* Allow the video device to override field and to scale */
267 height
= pix
->height
;
269 ret
= v4l2_subdev_call(sd
, pad
, set_fmt
, pad_cfg
, &format
);
270 if (ret
< 0 && ret
!= -ENOIOCTLCMD
)
274 v4l2_fill_pix_format(pix
, &format
.format
);
279 src_rect
->width
= pix
->width
;
280 src_rect
->height
= pix
->height
;
283 if (field
!= V4L2_FIELD_ANY
)
287 pix
->height
= height
;
289 rvin_format_align(vin
, pix
);
291 v4l2_subdev_free_pad_config(pad_cfg
);
296 static int rvin_querycap(struct file
*file
, void *priv
,
297 struct v4l2_capability
*cap
)
299 struct rvin_dev
*vin
= video_drvdata(file
);
301 strscpy(cap
->driver
, KBUILD_MODNAME
, sizeof(cap
->driver
));
302 strscpy(cap
->card
, "R_Car_VIN", sizeof(cap
->card
));
303 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
), "platform:%s",
308 static int rvin_try_fmt_vid_cap(struct file
*file
, void *priv
,
309 struct v4l2_format
*f
)
311 struct rvin_dev
*vin
= video_drvdata(file
);
313 return rvin_try_format(vin
, V4L2_SUBDEV_FORMAT_TRY
, &f
->fmt
.pix
, NULL
);
316 static int rvin_s_fmt_vid_cap(struct file
*file
, void *priv
,
317 struct v4l2_format
*f
)
319 struct rvin_dev
*vin
= video_drvdata(file
);
320 struct v4l2_rect fmt_rect
, src_rect
;
323 if (vb2_is_busy(&vin
->queue
))
326 ret
= rvin_try_format(vin
, V4L2_SUBDEV_FORMAT_ACTIVE
, &f
->fmt
.pix
,
331 vin
->format
= f
->fmt
.pix
;
335 fmt_rect
.width
= vin
->format
.width
;
336 fmt_rect
.height
= vin
->format
.height
;
338 v4l2_rect_map_inside(&vin
->crop
, &src_rect
);
339 v4l2_rect_map_inside(&vin
->compose
, &fmt_rect
);
340 vin
->src_rect
= src_rect
;
345 static int rvin_g_fmt_vid_cap(struct file
*file
, void *priv
,
346 struct v4l2_format
*f
)
348 struct rvin_dev
*vin
= video_drvdata(file
);
350 f
->fmt
.pix
= vin
->format
;
355 static int rvin_enum_fmt_vid_cap(struct file
*file
, void *priv
,
356 struct v4l2_fmtdesc
*f
)
358 struct rvin_dev
*vin
= video_drvdata(file
);
363 * If mbus_code is set only enumerate supported pixel formats for that
364 * bus code. Converting from YCbCr to RGB and RGB to YCbCr is possible
365 * with VIN, so all supported YCbCr and RGB media bus codes can produce
366 * all of the related pixel formats. If mbus_code is not set enumerate
367 * all possible pixelformats.
369 * TODO: Once raw MEDIA_BUS_FMT_SRGGB12_1X12 format is added to the
370 * driver this needs to be extended so raw media bus code only result in
373 switch (f
->mbus_code
) {
375 case MEDIA_BUS_FMT_YUYV8_1X16
:
376 case MEDIA_BUS_FMT_UYVY8_1X16
:
377 case MEDIA_BUS_FMT_UYVY8_2X8
:
378 case MEDIA_BUS_FMT_UYVY10_2X10
:
379 case MEDIA_BUS_FMT_RGB888_1X24
:
381 case MEDIA_BUS_FMT_SBGGR8_1X8
:
384 f
->pixelformat
= V4L2_PIX_FMT_SBGGR8
;
386 case MEDIA_BUS_FMT_SGBRG8_1X8
:
389 f
->pixelformat
= V4L2_PIX_FMT_SGBRG8
;
391 case MEDIA_BUS_FMT_SGRBG8_1X8
:
394 f
->pixelformat
= V4L2_PIX_FMT_SGRBG8
;
396 case MEDIA_BUS_FMT_SRGGB8_1X8
:
399 f
->pixelformat
= V4L2_PIX_FMT_SRGGB8
;
406 for (i
= 0; i
< ARRAY_SIZE(rvin_formats
); i
++) {
407 if (rvin_format_from_pixel(vin
, rvin_formats
[i
].fourcc
))
410 if (matched
== f
->index
) {
411 f
->pixelformat
= rvin_formats
[i
].fourcc
;
419 static int rvin_g_selection(struct file
*file
, void *fh
,
420 struct v4l2_selection
*s
)
422 struct rvin_dev
*vin
= video_drvdata(file
);
424 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
428 case V4L2_SEL_TGT_CROP_BOUNDS
:
429 case V4L2_SEL_TGT_CROP_DEFAULT
:
430 s
->r
.left
= s
->r
.top
= 0;
431 s
->r
.width
= vin
->src_rect
.width
;
432 s
->r
.height
= vin
->src_rect
.height
;
434 case V4L2_SEL_TGT_CROP
:
437 case V4L2_SEL_TGT_COMPOSE_BOUNDS
:
438 case V4L2_SEL_TGT_COMPOSE_DEFAULT
:
439 s
->r
.left
= s
->r
.top
= 0;
440 s
->r
.width
= vin
->format
.width
;
441 s
->r
.height
= vin
->format
.height
;
443 case V4L2_SEL_TGT_COMPOSE
:
453 static int rvin_s_selection(struct file
*file
, void *fh
,
454 struct v4l2_selection
*s
)
456 struct rvin_dev
*vin
= video_drvdata(file
);
457 const struct rvin_video_format
*fmt
;
458 struct v4l2_rect r
= s
->r
;
459 struct v4l2_rect max_rect
;
460 struct v4l2_rect min_rect
= {
465 if (s
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
468 v4l2_rect_set_min_size(&r
, &min_rect
);
471 case V4L2_SEL_TGT_CROP
:
472 /* Can't crop outside of source input */
473 max_rect
.top
= max_rect
.left
= 0;
474 max_rect
.width
= vin
->src_rect
.width
;
475 max_rect
.height
= vin
->src_rect
.height
;
476 v4l2_rect_map_inside(&r
, &max_rect
);
478 v4l_bound_align_image(&r
.width
, 6, vin
->src_rect
.width
, 0,
479 &r
.height
, 2, vin
->src_rect
.height
, 0, 0);
481 r
.top
= clamp_t(s32
, r
.top
, 0,
482 vin
->src_rect
.height
- r
.height
);
483 r
.left
= clamp_t(s32
, r
.left
, 0, vin
->src_rect
.width
- r
.width
);
485 vin
->crop
= s
->r
= r
;
487 vin_dbg(vin
, "Cropped %dx%d@%d:%d of %dx%d\n",
488 r
.width
, r
.height
, r
.left
, r
.top
,
489 vin
->src_rect
.width
, vin
->src_rect
.height
);
491 case V4L2_SEL_TGT_COMPOSE
:
492 /* Make sure compose rect fits inside output format */
493 max_rect
.top
= max_rect
.left
= 0;
494 max_rect
.width
= vin
->format
.width
;
495 max_rect
.height
= vin
->format
.height
;
496 v4l2_rect_map_inside(&r
, &max_rect
);
499 * Composing is done by adding a offset to the buffer address,
500 * the HW wants this address to be aligned to HW_BUFFER_MASK.
501 * Make sure the top and left values meets this requirement.
503 while ((r
.top
* vin
->format
.bytesperline
) & HW_BUFFER_MASK
)
506 fmt
= rvin_format_from_pixel(vin
, vin
->format
.pixelformat
);
507 while ((r
.left
* fmt
->bpp
) & HW_BUFFER_MASK
)
510 vin
->compose
= s
->r
= r
;
512 vin_dbg(vin
, "Compose %dx%d@%d:%d in %dx%d\n",
513 r
.width
, r
.height
, r
.left
, r
.top
,
514 vin
->format
.width
, vin
->format
.height
);
520 /* HW supports modifying configuration while running */
521 rvin_crop_scale_comp(vin
);
526 static int rvin_g_pixelaspect(struct file
*file
, void *priv
,
527 int type
, struct v4l2_fract
*f
)
529 struct rvin_dev
*vin
= video_drvdata(file
);
530 struct v4l2_subdev
*sd
= vin_to_source(vin
);
532 if (type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
535 return v4l2_subdev_call(sd
, video
, g_pixelaspect
, f
);
538 static int rvin_enum_input(struct file
*file
, void *priv
,
539 struct v4l2_input
*i
)
541 struct rvin_dev
*vin
= video_drvdata(file
);
542 struct v4l2_subdev
*sd
= vin_to_source(vin
);
548 ret
= v4l2_subdev_call(sd
, video
, g_input_status
, &i
->status
);
549 if (ret
< 0 && ret
!= -ENOIOCTLCMD
&& ret
!= -ENODEV
)
552 i
->type
= V4L2_INPUT_TYPE_CAMERA
;
554 if (v4l2_subdev_has_op(sd
, pad
, dv_timings_cap
)) {
555 i
->capabilities
= V4L2_IN_CAP_DV_TIMINGS
;
558 i
->capabilities
= V4L2_IN_CAP_STD
;
559 i
->std
= vin
->vdev
.tvnorms
;
562 strscpy(i
->name
, "Camera", sizeof(i
->name
));
567 static int rvin_g_input(struct file
*file
, void *priv
, unsigned int *i
)
573 static int rvin_s_input(struct file
*file
, void *priv
, unsigned int i
)
580 static int rvin_querystd(struct file
*file
, void *priv
, v4l2_std_id
*a
)
582 struct rvin_dev
*vin
= video_drvdata(file
);
583 struct v4l2_subdev
*sd
= vin_to_source(vin
);
585 return v4l2_subdev_call(sd
, video
, querystd
, a
);
588 static int rvin_s_std(struct file
*file
, void *priv
, v4l2_std_id a
)
590 struct rvin_dev
*vin
= video_drvdata(file
);
593 ret
= v4l2_subdev_call(vin_to_source(vin
), video
, s_std
, a
);
599 /* Changing the standard will change the width/height */
600 return rvin_reset_format(vin
);
603 static int rvin_g_std(struct file
*file
, void *priv
, v4l2_std_id
*a
)
605 struct rvin_dev
*vin
= video_drvdata(file
);
607 if (v4l2_subdev_has_op(vin_to_source(vin
), pad
, dv_timings_cap
))
615 static int rvin_subscribe_event(struct v4l2_fh
*fh
,
616 const struct v4l2_event_subscription
*sub
)
619 case V4L2_EVENT_SOURCE_CHANGE
:
620 return v4l2_event_subscribe(fh
, sub
, 4, NULL
);
622 return v4l2_ctrl_subscribe_event(fh
, sub
);
625 static int rvin_enum_dv_timings(struct file
*file
, void *priv_fh
,
626 struct v4l2_enum_dv_timings
*timings
)
628 struct rvin_dev
*vin
= video_drvdata(file
);
629 struct v4l2_subdev
*sd
= vin_to_source(vin
);
635 timings
->pad
= vin
->parallel
.sink_pad
;
637 ret
= v4l2_subdev_call(sd
, pad
, enum_dv_timings
, timings
);
644 static int rvin_s_dv_timings(struct file
*file
, void *priv_fh
,
645 struct v4l2_dv_timings
*timings
)
647 struct rvin_dev
*vin
= video_drvdata(file
);
648 struct v4l2_subdev
*sd
= vin_to_source(vin
);
651 ret
= v4l2_subdev_call(sd
, video
, s_dv_timings
, timings
);
655 /* Changing the timings will change the width/height */
656 return rvin_reset_format(vin
);
659 static int rvin_g_dv_timings(struct file
*file
, void *priv_fh
,
660 struct v4l2_dv_timings
*timings
)
662 struct rvin_dev
*vin
= video_drvdata(file
);
663 struct v4l2_subdev
*sd
= vin_to_source(vin
);
665 return v4l2_subdev_call(sd
, video
, g_dv_timings
, timings
);
668 static int rvin_query_dv_timings(struct file
*file
, void *priv_fh
,
669 struct v4l2_dv_timings
*timings
)
671 struct rvin_dev
*vin
= video_drvdata(file
);
672 struct v4l2_subdev
*sd
= vin_to_source(vin
);
674 return v4l2_subdev_call(sd
, video
, query_dv_timings
, timings
);
677 static int rvin_dv_timings_cap(struct file
*file
, void *priv_fh
,
678 struct v4l2_dv_timings_cap
*cap
)
680 struct rvin_dev
*vin
= video_drvdata(file
);
681 struct v4l2_subdev
*sd
= vin_to_source(vin
);
687 cap
->pad
= vin
->parallel
.sink_pad
;
689 ret
= v4l2_subdev_call(sd
, pad
, dv_timings_cap
, cap
);
696 static int rvin_g_edid(struct file
*file
, void *fh
, struct v4l2_edid
*edid
)
698 struct rvin_dev
*vin
= video_drvdata(file
);
699 struct v4l2_subdev
*sd
= vin_to_source(vin
);
705 edid
->pad
= vin
->parallel
.sink_pad
;
707 ret
= v4l2_subdev_call(sd
, pad
, get_edid
, edid
);
714 static int rvin_s_edid(struct file
*file
, void *fh
, struct v4l2_edid
*edid
)
716 struct rvin_dev
*vin
= video_drvdata(file
);
717 struct v4l2_subdev
*sd
= vin_to_source(vin
);
723 edid
->pad
= vin
->parallel
.sink_pad
;
725 ret
= v4l2_subdev_call(sd
, pad
, set_edid
, edid
);
732 static const struct v4l2_ioctl_ops rvin_ioctl_ops
= {
733 .vidioc_querycap
= rvin_querycap
,
734 .vidioc_try_fmt_vid_cap
= rvin_try_fmt_vid_cap
,
735 .vidioc_g_fmt_vid_cap
= rvin_g_fmt_vid_cap
,
736 .vidioc_s_fmt_vid_cap
= rvin_s_fmt_vid_cap
,
737 .vidioc_enum_fmt_vid_cap
= rvin_enum_fmt_vid_cap
,
739 .vidioc_g_selection
= rvin_g_selection
,
740 .vidioc_s_selection
= rvin_s_selection
,
742 .vidioc_g_pixelaspect
= rvin_g_pixelaspect
,
744 .vidioc_enum_input
= rvin_enum_input
,
745 .vidioc_g_input
= rvin_g_input
,
746 .vidioc_s_input
= rvin_s_input
,
748 .vidioc_dv_timings_cap
= rvin_dv_timings_cap
,
749 .vidioc_enum_dv_timings
= rvin_enum_dv_timings
,
750 .vidioc_g_dv_timings
= rvin_g_dv_timings
,
751 .vidioc_s_dv_timings
= rvin_s_dv_timings
,
752 .vidioc_query_dv_timings
= rvin_query_dv_timings
,
754 .vidioc_g_edid
= rvin_g_edid
,
755 .vidioc_s_edid
= rvin_s_edid
,
757 .vidioc_querystd
= rvin_querystd
,
758 .vidioc_g_std
= rvin_g_std
,
759 .vidioc_s_std
= rvin_s_std
,
761 .vidioc_reqbufs
= vb2_ioctl_reqbufs
,
762 .vidioc_create_bufs
= vb2_ioctl_create_bufs
,
763 .vidioc_querybuf
= vb2_ioctl_querybuf
,
764 .vidioc_qbuf
= vb2_ioctl_qbuf
,
765 .vidioc_dqbuf
= vb2_ioctl_dqbuf
,
766 .vidioc_expbuf
= vb2_ioctl_expbuf
,
767 .vidioc_prepare_buf
= vb2_ioctl_prepare_buf
,
768 .vidioc_streamon
= vb2_ioctl_streamon
,
769 .vidioc_streamoff
= vb2_ioctl_streamoff
,
771 .vidioc_log_status
= v4l2_ctrl_log_status
,
772 .vidioc_subscribe_event
= rvin_subscribe_event
,
773 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
776 /* -----------------------------------------------------------------------------
777 * V4L2 Media Controller
780 static void rvin_mc_try_format(struct rvin_dev
*vin
,
781 struct v4l2_pix_format
*pix
)
784 * The V4L2 specification clearly documents the colorspace fields
785 * as being set by drivers for capture devices. Using the values
786 * supplied by userspace thus wouldn't comply with the API. Until
787 * the API is updated force fixed values.
789 pix
->colorspace
= RVIN_DEFAULT_COLORSPACE
;
790 pix
->xfer_func
= V4L2_MAP_XFER_FUNC_DEFAULT(pix
->colorspace
);
791 pix
->ycbcr_enc
= V4L2_MAP_YCBCR_ENC_DEFAULT(pix
->colorspace
);
792 pix
->quantization
= V4L2_MAP_QUANTIZATION_DEFAULT(true, pix
->colorspace
,
795 rvin_format_align(vin
, pix
);
798 static int rvin_mc_try_fmt_vid_cap(struct file
*file
, void *priv
,
799 struct v4l2_format
*f
)
801 struct rvin_dev
*vin
= video_drvdata(file
);
803 rvin_mc_try_format(vin
, &f
->fmt
.pix
);
808 static int rvin_mc_s_fmt_vid_cap(struct file
*file
, void *priv
,
809 struct v4l2_format
*f
)
811 struct rvin_dev
*vin
= video_drvdata(file
);
813 if (vb2_is_busy(&vin
->queue
))
816 rvin_mc_try_format(vin
, &f
->fmt
.pix
);
818 vin
->format
= f
->fmt
.pix
;
822 vin
->crop
.width
= vin
->format
.width
;
823 vin
->crop
.height
= vin
->format
.height
;
824 vin
->compose
= vin
->crop
;
829 static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops
= {
830 .vidioc_querycap
= rvin_querycap
,
831 .vidioc_try_fmt_vid_cap
= rvin_mc_try_fmt_vid_cap
,
832 .vidioc_g_fmt_vid_cap
= rvin_g_fmt_vid_cap
,
833 .vidioc_s_fmt_vid_cap
= rvin_mc_s_fmt_vid_cap
,
834 .vidioc_enum_fmt_vid_cap
= rvin_enum_fmt_vid_cap
,
836 .vidioc_reqbufs
= vb2_ioctl_reqbufs
,
837 .vidioc_create_bufs
= vb2_ioctl_create_bufs
,
838 .vidioc_querybuf
= vb2_ioctl_querybuf
,
839 .vidioc_qbuf
= vb2_ioctl_qbuf
,
840 .vidioc_dqbuf
= vb2_ioctl_dqbuf
,
841 .vidioc_expbuf
= vb2_ioctl_expbuf
,
842 .vidioc_prepare_buf
= vb2_ioctl_prepare_buf
,
843 .vidioc_streamon
= vb2_ioctl_streamon
,
844 .vidioc_streamoff
= vb2_ioctl_streamoff
,
846 .vidioc_log_status
= v4l2_ctrl_log_status
,
847 .vidioc_subscribe_event
= rvin_subscribe_event
,
848 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
851 /* -----------------------------------------------------------------------------
855 static int rvin_power_parallel(struct rvin_dev
*vin
, bool on
)
857 struct v4l2_subdev
*sd
= vin_to_source(vin
);
858 int power
= on
? 1 : 0;
861 ret
= v4l2_subdev_call(sd
, core
, s_power
, power
);
862 if (ret
< 0 && ret
!= -ENOIOCTLCMD
&& ret
!= -ENODEV
)
868 static int rvin_open(struct file
*file
)
870 struct rvin_dev
*vin
= video_drvdata(file
);
873 ret
= pm_runtime_get_sync(vin
->dev
);
875 pm_runtime_put_noidle(vin
->dev
);
879 ret
= mutex_lock_interruptible(&vin
->lock
);
883 file
->private_data
= vin
;
885 ret
= v4l2_fh_open(file
);
889 if (vin
->info
->use_mc
)
890 ret
= v4l2_pipeline_pm_get(&vin
->vdev
.entity
);
891 else if (v4l2_fh_is_singular_file(file
))
892 ret
= rvin_power_parallel(vin
, true);
897 ret
= v4l2_ctrl_handler_setup(&vin
->ctrl_handler
);
901 mutex_unlock(&vin
->lock
);
905 if (vin
->info
->use_mc
)
906 v4l2_pipeline_pm_put(&vin
->vdev
.entity
);
907 else if (v4l2_fh_is_singular_file(file
))
908 rvin_power_parallel(vin
, false);
910 v4l2_fh_release(file
);
912 mutex_unlock(&vin
->lock
);
914 pm_runtime_put(vin
->dev
);
919 static int rvin_release(struct file
*file
)
921 struct rvin_dev
*vin
= video_drvdata(file
);
925 mutex_lock(&vin
->lock
);
927 /* Save the singular status before we call the clean-up helper */
928 fh_singular
= v4l2_fh_is_singular_file(file
);
930 /* the release helper will cleanup any on-going streaming */
931 ret
= _vb2_fop_release(file
, NULL
);
933 if (vin
->info
->use_mc
) {
934 v4l2_pipeline_pm_put(&vin
->vdev
.entity
);
937 rvin_power_parallel(vin
, false);
940 mutex_unlock(&vin
->lock
);
942 pm_runtime_put(vin
->dev
);
947 static const struct v4l2_file_operations rvin_fops
= {
948 .owner
= THIS_MODULE
,
949 .unlocked_ioctl
= video_ioctl2
,
951 .release
= rvin_release
,
952 .poll
= vb2_fop_poll
,
953 .mmap
= vb2_fop_mmap
,
954 .read
= vb2_fop_read
,
957 void rvin_v4l2_unregister(struct rvin_dev
*vin
)
959 if (!video_is_registered(&vin
->vdev
))
962 v4l2_info(&vin
->v4l2_dev
, "Removing %s\n",
963 video_device_node_name(&vin
->vdev
));
965 /* Checks internally if vdev have been init or not */
966 video_unregister_device(&vin
->vdev
);
969 static void rvin_notify(struct v4l2_subdev
*sd
,
970 unsigned int notification
, void *arg
)
972 struct rvin_dev
*vin
=
973 container_of(sd
->v4l2_dev
, struct rvin_dev
, v4l2_dev
);
975 switch (notification
) {
976 case V4L2_DEVICE_NOTIFY_EVENT
:
977 v4l2_event_queue(&vin
->vdev
, arg
);
984 int rvin_v4l2_register(struct rvin_dev
*vin
)
986 struct video_device
*vdev
= &vin
->vdev
;
989 vin
->v4l2_dev
.notify
= rvin_notify
;
992 vdev
->v4l2_dev
= &vin
->v4l2_dev
;
993 vdev
->queue
= &vin
->queue
;
994 snprintf(vdev
->name
, sizeof(vdev
->name
), "VIN%u output", vin
->id
);
995 vdev
->release
= video_device_release_empty
;
996 vdev
->lock
= &vin
->lock
;
997 vdev
->fops
= &rvin_fops
;
998 vdev
->device_caps
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING
|
1001 /* Set a default format */
1002 vin
->format
.pixelformat
= RVIN_DEFAULT_FORMAT
;
1003 vin
->format
.width
= RVIN_DEFAULT_WIDTH
;
1004 vin
->format
.height
= RVIN_DEFAULT_HEIGHT
;
1005 vin
->format
.field
= RVIN_DEFAULT_FIELD
;
1006 vin
->format
.colorspace
= RVIN_DEFAULT_COLORSPACE
;
1008 if (vin
->info
->use_mc
) {
1009 vdev
->device_caps
|= V4L2_CAP_IO_MC
;
1010 vdev
->ioctl_ops
= &rvin_mc_ioctl_ops
;
1012 vdev
->ioctl_ops
= &rvin_ioctl_ops
;
1013 rvin_reset_format(vin
);
1016 rvin_format_align(vin
, &vin
->format
);
1018 ret
= video_register_device(&vin
->vdev
, VFL_TYPE_VIDEO
, -1);
1020 vin_err(vin
, "Failed to register video device\n");
1024 video_set_drvdata(&vin
->vdev
, vin
);
1026 v4l2_info(&vin
->v4l2_dev
, "Device registered as %s\n",
1027 video_device_node_name(&vin
->vdev
));