Linux-libre 4.19.116-gnu
[librecmc/linux-libre.git] / drivers / media / platform / rcar-vin / rcar-v4l2.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Driver for Renesas R-Car VIN
4  *
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
9  *
10  * Based on the soc-camera rcar_vin driver
11  */
12
13 #include <linux/pm_runtime.h>
14
15 #include <media/v4l2-event.h>
16 #include <media/v4l2-ioctl.h>
17 #include <media/v4l2-mc.h>
18 #include <media/v4l2-rect.h>
19
20 #include "rcar-vin.h"
21
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
27
28 /* -----------------------------------------------------------------------------
29  * Format Conversions
30  */
31
32 static const struct rvin_video_format rvin_formats[] = {
33         {
34                 .fourcc                 = V4L2_PIX_FMT_NV16,
35                 .bpp                    = 1,
36         },
37         {
38                 .fourcc                 = V4L2_PIX_FMT_YUYV,
39                 .bpp                    = 2,
40         },
41         {
42                 .fourcc                 = V4L2_PIX_FMT_UYVY,
43                 .bpp                    = 2,
44         },
45         {
46                 .fourcc                 = V4L2_PIX_FMT_RGB565,
47                 .bpp                    = 2,
48         },
49         {
50                 .fourcc                 = V4L2_PIX_FMT_XRGB555,
51                 .bpp                    = 2,
52         },
53         {
54                 .fourcc                 = V4L2_PIX_FMT_XBGR32,
55                 .bpp                    = 4,
56         },
57 };
58
59 const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat)
60 {
61         int i;
62
63         for (i = 0; i < ARRAY_SIZE(rvin_formats); i++)
64                 if (rvin_formats[i].fourcc == pixelformat)
65                         return rvin_formats + i;
66
67         return NULL;
68 }
69
70 static u32 rvin_format_bytesperline(struct v4l2_pix_format *pix)
71 {
72         const struct rvin_video_format *fmt;
73
74         fmt = rvin_format_from_pixel(pix->pixelformat);
75
76         if (WARN_ON(!fmt))
77                 return -EINVAL;
78
79         return pix->width * fmt->bpp;
80 }
81
82 static u32 rvin_format_sizeimage(struct v4l2_pix_format *pix)
83 {
84         if (pix->pixelformat == V4L2_PIX_FMT_NV16)
85                 return pix->bytesperline * pix->height * 2;
86
87         return pix->bytesperline * pix->height;
88 }
89
90 static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
91 {
92         u32 walign;
93
94         if (!rvin_format_from_pixel(pix->pixelformat) ||
95             (vin->info->model == RCAR_M1 &&
96              pix->pixelformat == V4L2_PIX_FMT_XBGR32))
97                 pix->pixelformat = RVIN_DEFAULT_FORMAT;
98
99         switch (pix->field) {
100         case V4L2_FIELD_TOP:
101         case V4L2_FIELD_BOTTOM:
102         case V4L2_FIELD_NONE:
103         case V4L2_FIELD_INTERLACED_TB:
104         case V4L2_FIELD_INTERLACED_BT:
105         case V4L2_FIELD_INTERLACED:
106                 break;
107         case V4L2_FIELD_ALTERNATE:
108                 /*
109                  * Driver does not (yet) support outputting ALTERNATE to a
110                  * userspace. It does support outputting INTERLACED so use
111                  * the VIN hardware to combine the two fields.
112                  */
113                 pix->field = V4L2_FIELD_INTERLACED;
114                 pix->height *= 2;
115                 break;
116         default:
117                 pix->field = RVIN_DEFAULT_FIELD;
118                 break;
119         }
120
121         /* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
122         walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
123
124         /* Limit to VIN capabilities */
125         v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,
126                               &pix->height, 4, vin->info->max_height, 2, 0);
127
128         pix->bytesperline = rvin_format_bytesperline(pix);
129         pix->sizeimage = rvin_format_sizeimage(pix);
130
131         vin_dbg(vin, "Format %ux%u bpl: %u size: %u\n",
132                 pix->width, pix->height, pix->bytesperline, pix->sizeimage);
133 }
134
135 /* -----------------------------------------------------------------------------
136  * V4L2
137  */
138
139 static int rvin_reset_format(struct rvin_dev *vin)
140 {
141         struct v4l2_subdev_format fmt = {
142                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
143                 .pad = vin->parallel->source_pad,
144         };
145         int ret;
146
147         ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt);
148         if (ret)
149                 return ret;
150
151         v4l2_fill_pix_format(&vin->format, &fmt.format);
152
153         rvin_format_align(vin, &vin->format);
154
155         vin->source.top = 0;
156         vin->source.left = 0;
157         vin->source.width = vin->format.width;
158         vin->source.height = vin->format.height;
159
160         vin->crop = vin->source;
161         vin->compose = vin->source;
162
163         return 0;
164 }
165
166 static int rvin_try_format(struct rvin_dev *vin, u32 which,
167                            struct v4l2_pix_format *pix,
168                            struct v4l2_rect *crop, struct v4l2_rect *compose)
169 {
170         struct v4l2_subdev *sd = vin_to_source(vin);
171         struct v4l2_subdev_pad_config *pad_cfg;
172         struct v4l2_subdev_format format = {
173                 .which = which,
174                 .pad = vin->parallel->source_pad,
175         };
176         enum v4l2_field field;
177         u32 width, height;
178         int ret;
179
180         pad_cfg = v4l2_subdev_alloc_pad_config(sd);
181         if (pad_cfg == NULL)
182                 return -ENOMEM;
183
184         if (!rvin_format_from_pixel(pix->pixelformat) ||
185             (vin->info->model == RCAR_M1 &&
186              pix->pixelformat == V4L2_PIX_FMT_XBGR32))
187                 pix->pixelformat = RVIN_DEFAULT_FORMAT;
188
189         v4l2_fill_mbus_format(&format.format, pix, vin->mbus_code);
190
191         /* Allow the video device to override field and to scale */
192         field = pix->field;
193         width = pix->width;
194         height = pix->height;
195
196         ret = v4l2_subdev_call(sd, pad, set_fmt, pad_cfg, &format);
197         if (ret < 0 && ret != -ENOIOCTLCMD)
198                 goto done;
199         ret = 0;
200
201         v4l2_fill_pix_format(pix, &format.format);
202
203         if (crop) {
204                 crop->top = 0;
205                 crop->left = 0;
206                 crop->width = pix->width;
207                 crop->height = pix->height;
208
209                 /*
210                  * If source is ALTERNATE the driver will use the VIN hardware
211                  * to INTERLACE it. The crop height then needs to be doubled.
212                  */
213                 if (pix->field == V4L2_FIELD_ALTERNATE)
214                         crop->height *= 2;
215         }
216
217         if (field != V4L2_FIELD_ANY)
218                 pix->field = field;
219
220         pix->width = width;
221         pix->height = height;
222
223         rvin_format_align(vin, pix);
224
225         if (compose) {
226                 compose->top = 0;
227                 compose->left = 0;
228                 compose->width = pix->width;
229                 compose->height = pix->height;
230         }
231 done:
232         v4l2_subdev_free_pad_config(pad_cfg);
233
234         return ret;
235 }
236
237 static int rvin_querycap(struct file *file, void *priv,
238                          struct v4l2_capability *cap)
239 {
240         struct rvin_dev *vin = video_drvdata(file);
241
242         strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
243         strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
244         snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
245                  dev_name(vin->dev));
246         return 0;
247 }
248
249 static int rvin_try_fmt_vid_cap(struct file *file, void *priv,
250                                 struct v4l2_format *f)
251 {
252         struct rvin_dev *vin = video_drvdata(file);
253
254         return rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix, NULL,
255                                NULL);
256 }
257
258 static int rvin_s_fmt_vid_cap(struct file *file, void *priv,
259                               struct v4l2_format *f)
260 {
261         struct rvin_dev *vin = video_drvdata(file);
262         struct v4l2_rect crop, compose;
263         int ret;
264
265         if (vb2_is_busy(&vin->queue))
266                 return -EBUSY;
267
268         ret = rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
269                               &crop, &compose);
270         if (ret)
271                 return ret;
272
273         vin->format = f->fmt.pix;
274         vin->crop = crop;
275         vin->compose = compose;
276         vin->source = crop;
277
278         return 0;
279 }
280
281 static int rvin_g_fmt_vid_cap(struct file *file, void *priv,
282                               struct v4l2_format *f)
283 {
284         struct rvin_dev *vin = video_drvdata(file);
285
286         f->fmt.pix = vin->format;
287
288         return 0;
289 }
290
291 static int rvin_enum_fmt_vid_cap(struct file *file, void *priv,
292                                  struct v4l2_fmtdesc *f)
293 {
294         if (f->index >= ARRAY_SIZE(rvin_formats))
295                 return -EINVAL;
296
297         f->pixelformat = rvin_formats[f->index].fourcc;
298
299         return 0;
300 }
301
302 static int rvin_g_selection(struct file *file, void *fh,
303                             struct v4l2_selection *s)
304 {
305         struct rvin_dev *vin = video_drvdata(file);
306
307         if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
308                 return -EINVAL;
309
310         switch (s->target) {
311         case V4L2_SEL_TGT_CROP_BOUNDS:
312         case V4L2_SEL_TGT_CROP_DEFAULT:
313                 s->r.left = s->r.top = 0;
314                 s->r.width = vin->source.width;
315                 s->r.height = vin->source.height;
316                 break;
317         case V4L2_SEL_TGT_CROP:
318                 s->r = vin->crop;
319                 break;
320         case V4L2_SEL_TGT_COMPOSE_BOUNDS:
321         case V4L2_SEL_TGT_COMPOSE_DEFAULT:
322                 s->r.left = s->r.top = 0;
323                 s->r.width = vin->format.width;
324                 s->r.height = vin->format.height;
325                 break;
326         case V4L2_SEL_TGT_COMPOSE:
327                 s->r = vin->compose;
328                 break;
329         default:
330                 return -EINVAL;
331         }
332
333         return 0;
334 }
335
336 static int rvin_s_selection(struct file *file, void *fh,
337                             struct v4l2_selection *s)
338 {
339         struct rvin_dev *vin = video_drvdata(file);
340         const struct rvin_video_format *fmt;
341         struct v4l2_rect r = s->r;
342         struct v4l2_rect max_rect;
343         struct v4l2_rect min_rect = {
344                 .width = 6,
345                 .height = 2,
346         };
347
348         if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
349                 return -EINVAL;
350
351         v4l2_rect_set_min_size(&r, &min_rect);
352
353         switch (s->target) {
354         case V4L2_SEL_TGT_CROP:
355                 /* Can't crop outside of source input */
356                 max_rect.top = max_rect.left = 0;
357                 max_rect.width = vin->source.width;
358                 max_rect.height = vin->source.height;
359                 v4l2_rect_map_inside(&r, &max_rect);
360
361                 v4l_bound_align_image(&r.width, 6, vin->source.width, 0,
362                                       &r.height, 2, vin->source.height, 0, 0);
363
364                 r.top  = clamp_t(s32, r.top, 0, vin->source.height - r.height);
365                 r.left = clamp_t(s32, r.left, 0, vin->source.width - r.width);
366
367                 vin->crop = s->r = r;
368
369                 vin_dbg(vin, "Cropped %dx%d@%d:%d of %dx%d\n",
370                         r.width, r.height, r.left, r.top,
371                         vin->source.width, vin->source.height);
372                 break;
373         case V4L2_SEL_TGT_COMPOSE:
374                 /* Make sure compose rect fits inside output format */
375                 max_rect.top = max_rect.left = 0;
376                 max_rect.width = vin->format.width;
377                 max_rect.height = vin->format.height;
378                 v4l2_rect_map_inside(&r, &max_rect);
379
380                 /*
381                  * Composing is done by adding a offset to the buffer address,
382                  * the HW wants this address to be aligned to HW_BUFFER_MASK.
383                  * Make sure the top and left values meets this requirement.
384                  */
385                 while ((r.top * vin->format.bytesperline) & HW_BUFFER_MASK)
386                         r.top--;
387
388                 fmt = rvin_format_from_pixel(vin->format.pixelformat);
389                 while ((r.left * fmt->bpp) & HW_BUFFER_MASK)
390                         r.left--;
391
392                 vin->compose = s->r = r;
393
394                 vin_dbg(vin, "Compose %dx%d@%d:%d in %dx%d\n",
395                         r.width, r.height, r.left, r.top,
396                         vin->format.width, vin->format.height);
397                 break;
398         default:
399                 return -EINVAL;
400         }
401
402         /* HW supports modifying configuration while running */
403         rvin_crop_scale_comp(vin);
404
405         return 0;
406 }
407
408 static int rvin_cropcap(struct file *file, void *priv,
409                         struct v4l2_cropcap *crop)
410 {
411         struct rvin_dev *vin = video_drvdata(file);
412         struct v4l2_subdev *sd = vin_to_source(vin);
413
414         if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
415                 return -EINVAL;
416
417         return v4l2_subdev_call(sd, video, g_pixelaspect, &crop->pixelaspect);
418 }
419
420 static int rvin_enum_input(struct file *file, void *priv,
421                            struct v4l2_input *i)
422 {
423         struct rvin_dev *vin = video_drvdata(file);
424         struct v4l2_subdev *sd = vin_to_source(vin);
425         int ret;
426
427         if (i->index != 0)
428                 return -EINVAL;
429
430         ret = v4l2_subdev_call(sd, video, g_input_status, &i->status);
431         if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
432                 return ret;
433
434         i->type = V4L2_INPUT_TYPE_CAMERA;
435
436         if (v4l2_subdev_has_op(sd, pad, dv_timings_cap)) {
437                 i->capabilities = V4L2_IN_CAP_DV_TIMINGS;
438                 i->std = 0;
439         } else {
440                 i->capabilities = V4L2_IN_CAP_STD;
441                 i->std = vin->vdev.tvnorms;
442         }
443
444         strlcpy(i->name, "Camera", sizeof(i->name));
445
446         return 0;
447 }
448
449 static int rvin_g_input(struct file *file, void *priv, unsigned int *i)
450 {
451         *i = 0;
452         return 0;
453 }
454
455 static int rvin_s_input(struct file *file, void *priv, unsigned int i)
456 {
457         if (i > 0)
458                 return -EINVAL;
459         return 0;
460 }
461
462 static int rvin_querystd(struct file *file, void *priv, v4l2_std_id *a)
463 {
464         struct rvin_dev *vin = video_drvdata(file);
465         struct v4l2_subdev *sd = vin_to_source(vin);
466
467         return v4l2_subdev_call(sd, video, querystd, a);
468 }
469
470 static int rvin_s_std(struct file *file, void *priv, v4l2_std_id a)
471 {
472         struct rvin_dev *vin = video_drvdata(file);
473         int ret;
474
475         ret = v4l2_subdev_call(vin_to_source(vin), video, s_std, a);
476         if (ret < 0)
477                 return ret;
478
479         vin->std = a;
480
481         /* Changing the standard will change the width/height */
482         return rvin_reset_format(vin);
483 }
484
485 static int rvin_g_std(struct file *file, void *priv, v4l2_std_id *a)
486 {
487         struct rvin_dev *vin = video_drvdata(file);
488
489         if (v4l2_subdev_has_op(vin_to_source(vin), pad, dv_timings_cap))
490                 return -ENOIOCTLCMD;
491
492         *a = vin->std;
493
494         return 0;
495 }
496
497 static int rvin_subscribe_event(struct v4l2_fh *fh,
498                                 const struct v4l2_event_subscription *sub)
499 {
500         switch (sub->type) {
501         case V4L2_EVENT_SOURCE_CHANGE:
502                 return v4l2_event_subscribe(fh, sub, 4, NULL);
503         }
504         return v4l2_ctrl_subscribe_event(fh, sub);
505 }
506
507 static int rvin_enum_dv_timings(struct file *file, void *priv_fh,
508                                 struct v4l2_enum_dv_timings *timings)
509 {
510         struct rvin_dev *vin = video_drvdata(file);
511         struct v4l2_subdev *sd = vin_to_source(vin);
512         int ret;
513
514         if (timings->pad)
515                 return -EINVAL;
516
517         timings->pad = vin->parallel->sink_pad;
518
519         ret = v4l2_subdev_call(sd, pad, enum_dv_timings, timings);
520
521         timings->pad = 0;
522
523         return ret;
524 }
525
526 static int rvin_s_dv_timings(struct file *file, void *priv_fh,
527                              struct v4l2_dv_timings *timings)
528 {
529         struct rvin_dev *vin = video_drvdata(file);
530         struct v4l2_subdev *sd = vin_to_source(vin);
531         int ret;
532
533         ret = v4l2_subdev_call(sd, video, s_dv_timings, timings);
534         if (ret)
535                 return ret;
536
537         /* Changing the timings will change the width/height */
538         return rvin_reset_format(vin);
539 }
540
541 static int rvin_g_dv_timings(struct file *file, void *priv_fh,
542                              struct v4l2_dv_timings *timings)
543 {
544         struct rvin_dev *vin = video_drvdata(file);
545         struct v4l2_subdev *sd = vin_to_source(vin);
546
547         return v4l2_subdev_call(sd, video, g_dv_timings, timings);
548 }
549
550 static int rvin_query_dv_timings(struct file *file, void *priv_fh,
551                                  struct v4l2_dv_timings *timings)
552 {
553         struct rvin_dev *vin = video_drvdata(file);
554         struct v4l2_subdev *sd = vin_to_source(vin);
555
556         return v4l2_subdev_call(sd, video, query_dv_timings, timings);
557 }
558
559 static int rvin_dv_timings_cap(struct file *file, void *priv_fh,
560                                struct v4l2_dv_timings_cap *cap)
561 {
562         struct rvin_dev *vin = video_drvdata(file);
563         struct v4l2_subdev *sd = vin_to_source(vin);
564         int ret;
565
566         if (cap->pad)
567                 return -EINVAL;
568
569         cap->pad = vin->parallel->sink_pad;
570
571         ret = v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
572
573         cap->pad = 0;
574
575         return ret;
576 }
577
578 static int rvin_g_edid(struct file *file, void *fh, struct v4l2_edid *edid)
579 {
580         struct rvin_dev *vin = video_drvdata(file);
581         struct v4l2_subdev *sd = vin_to_source(vin);
582         int ret;
583
584         if (edid->pad)
585                 return -EINVAL;
586
587         edid->pad = vin->parallel->sink_pad;
588
589         ret = v4l2_subdev_call(sd, pad, get_edid, edid);
590
591         edid->pad = 0;
592
593         return ret;
594 }
595
596 static int rvin_s_edid(struct file *file, void *fh, struct v4l2_edid *edid)
597 {
598         struct rvin_dev *vin = video_drvdata(file);
599         struct v4l2_subdev *sd = vin_to_source(vin);
600         int ret;
601
602         if (edid->pad)
603                 return -EINVAL;
604
605         edid->pad = vin->parallel->sink_pad;
606
607         ret = v4l2_subdev_call(sd, pad, set_edid, edid);
608
609         edid->pad = 0;
610
611         return ret;
612 }
613
614 static const struct v4l2_ioctl_ops rvin_ioctl_ops = {
615         .vidioc_querycap                = rvin_querycap,
616         .vidioc_try_fmt_vid_cap         = rvin_try_fmt_vid_cap,
617         .vidioc_g_fmt_vid_cap           = rvin_g_fmt_vid_cap,
618         .vidioc_s_fmt_vid_cap           = rvin_s_fmt_vid_cap,
619         .vidioc_enum_fmt_vid_cap        = rvin_enum_fmt_vid_cap,
620
621         .vidioc_g_selection             = rvin_g_selection,
622         .vidioc_s_selection             = rvin_s_selection,
623
624         .vidioc_cropcap                 = rvin_cropcap,
625
626         .vidioc_enum_input              = rvin_enum_input,
627         .vidioc_g_input                 = rvin_g_input,
628         .vidioc_s_input                 = rvin_s_input,
629
630         .vidioc_dv_timings_cap          = rvin_dv_timings_cap,
631         .vidioc_enum_dv_timings         = rvin_enum_dv_timings,
632         .vidioc_g_dv_timings            = rvin_g_dv_timings,
633         .vidioc_s_dv_timings            = rvin_s_dv_timings,
634         .vidioc_query_dv_timings        = rvin_query_dv_timings,
635
636         .vidioc_g_edid                  = rvin_g_edid,
637         .vidioc_s_edid                  = rvin_s_edid,
638
639         .vidioc_querystd                = rvin_querystd,
640         .vidioc_g_std                   = rvin_g_std,
641         .vidioc_s_std                   = rvin_s_std,
642
643         .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
644         .vidioc_create_bufs             = vb2_ioctl_create_bufs,
645         .vidioc_querybuf                = vb2_ioctl_querybuf,
646         .vidioc_qbuf                    = vb2_ioctl_qbuf,
647         .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
648         .vidioc_expbuf                  = vb2_ioctl_expbuf,
649         .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
650         .vidioc_streamon                = vb2_ioctl_streamon,
651         .vidioc_streamoff               = vb2_ioctl_streamoff,
652
653         .vidioc_log_status              = v4l2_ctrl_log_status,
654         .vidioc_subscribe_event         = rvin_subscribe_event,
655         .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
656 };
657
658 /* -----------------------------------------------------------------------------
659  * V4L2 Media Controller
660  */
661
662 static void rvin_mc_try_format(struct rvin_dev *vin,
663                                struct v4l2_pix_format *pix)
664 {
665         /*
666          * The V4L2 specification clearly documents the colorspace fields
667          * as being set by drivers for capture devices. Using the values
668          * supplied by userspace thus wouldn't comply with the API. Until
669          * the API is updated force fixed vaules.
670          */
671         pix->colorspace = RVIN_DEFAULT_COLORSPACE;
672         pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
673         pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
674         pix->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, pix->colorspace,
675                                                           pix->ycbcr_enc);
676
677         rvin_format_align(vin, pix);
678 }
679
680 static int rvin_mc_try_fmt_vid_cap(struct file *file, void *priv,
681                                    struct v4l2_format *f)
682 {
683         struct rvin_dev *vin = video_drvdata(file);
684
685         rvin_mc_try_format(vin, &f->fmt.pix);
686
687         return 0;
688 }
689
690 static int rvin_mc_s_fmt_vid_cap(struct file *file, void *priv,
691                                  struct v4l2_format *f)
692 {
693         struct rvin_dev *vin = video_drvdata(file);
694
695         if (vb2_is_busy(&vin->queue))
696                 return -EBUSY;
697
698         rvin_mc_try_format(vin, &f->fmt.pix);
699
700         vin->format = f->fmt.pix;
701
702         vin->crop.top = 0;
703         vin->crop.left = 0;
704         vin->crop.width = vin->format.width;
705         vin->crop.height = vin->format.height;
706         vin->compose = vin->crop;
707
708         return 0;
709 }
710
711 static int rvin_mc_enum_input(struct file *file, void *priv,
712                               struct v4l2_input *i)
713 {
714         if (i->index != 0)
715                 return -EINVAL;
716
717         i->type = V4L2_INPUT_TYPE_CAMERA;
718         strlcpy(i->name, "Camera", sizeof(i->name));
719
720         return 0;
721 }
722
723 static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops = {
724         .vidioc_querycap                = rvin_querycap,
725         .vidioc_try_fmt_vid_cap         = rvin_mc_try_fmt_vid_cap,
726         .vidioc_g_fmt_vid_cap           = rvin_g_fmt_vid_cap,
727         .vidioc_s_fmt_vid_cap           = rvin_mc_s_fmt_vid_cap,
728         .vidioc_enum_fmt_vid_cap        = rvin_enum_fmt_vid_cap,
729
730         .vidioc_enum_input              = rvin_mc_enum_input,
731         .vidioc_g_input                 = rvin_g_input,
732         .vidioc_s_input                 = rvin_s_input,
733
734         .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
735         .vidioc_create_bufs             = vb2_ioctl_create_bufs,
736         .vidioc_querybuf                = vb2_ioctl_querybuf,
737         .vidioc_qbuf                    = vb2_ioctl_qbuf,
738         .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
739         .vidioc_expbuf                  = vb2_ioctl_expbuf,
740         .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
741         .vidioc_streamon                = vb2_ioctl_streamon,
742         .vidioc_streamoff               = vb2_ioctl_streamoff,
743
744         .vidioc_log_status              = v4l2_ctrl_log_status,
745         .vidioc_subscribe_event         = rvin_subscribe_event,
746         .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
747 };
748
749 /* -----------------------------------------------------------------------------
750  * File Operations
751  */
752
753 static int rvin_power_on(struct rvin_dev *vin)
754 {
755         int ret;
756         struct v4l2_subdev *sd = vin_to_source(vin);
757
758         pm_runtime_get_sync(vin->v4l2_dev.dev);
759
760         ret = v4l2_subdev_call(sd, core, s_power, 1);
761         if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
762                 return ret;
763         return 0;
764 }
765
766 static int rvin_power_off(struct rvin_dev *vin)
767 {
768         int ret;
769         struct v4l2_subdev *sd = vin_to_source(vin);
770
771         ret = v4l2_subdev_call(sd, core, s_power, 0);
772
773         pm_runtime_put(vin->v4l2_dev.dev);
774
775         if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
776                 return ret;
777
778         return 0;
779 }
780
781 static int rvin_initialize_device(struct file *file)
782 {
783         struct rvin_dev *vin = video_drvdata(file);
784         int ret;
785
786         struct v4l2_format f = {
787                 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
788                 .fmt.pix = {
789                         .width          = vin->format.width,
790                         .height         = vin->format.height,
791                         .field          = vin->format.field,
792                         .colorspace     = vin->format.colorspace,
793                         .pixelformat    = vin->format.pixelformat,
794                 },
795         };
796
797         ret = rvin_power_on(vin);
798         if (ret < 0)
799                 return ret;
800
801         pm_runtime_enable(&vin->vdev.dev);
802         ret = pm_runtime_resume(&vin->vdev.dev);
803         if (ret < 0 && ret != -ENOSYS)
804                 goto eresume;
805
806         /*
807          * Try to configure with default parameters. Notice: this is the
808          * very first open, so, we cannot race against other calls,
809          * apart from someone else calling open() simultaneously, but
810          * .host_lock is protecting us against it.
811          */
812         ret = rvin_s_fmt_vid_cap(file, NULL, &f);
813         if (ret < 0)
814                 goto esfmt;
815
816         v4l2_ctrl_handler_setup(&vin->ctrl_handler);
817
818         return 0;
819 esfmt:
820         pm_runtime_disable(&vin->vdev.dev);
821 eresume:
822         rvin_power_off(vin);
823
824         return ret;
825 }
826
827 static int rvin_open(struct file *file)
828 {
829         struct rvin_dev *vin = video_drvdata(file);
830         int ret;
831
832         mutex_lock(&vin->lock);
833
834         file->private_data = vin;
835
836         ret = v4l2_fh_open(file);
837         if (ret)
838                 goto unlock;
839
840         if (!v4l2_fh_is_singular_file(file))
841                 goto unlock;
842
843         if (rvin_initialize_device(file)) {
844                 v4l2_fh_release(file);
845                 ret = -ENODEV;
846         }
847
848 unlock:
849         mutex_unlock(&vin->lock);
850         return ret;
851 }
852
853 static int rvin_release(struct file *file)
854 {
855         struct rvin_dev *vin = video_drvdata(file);
856         bool fh_singular;
857         int ret;
858
859         mutex_lock(&vin->lock);
860
861         /* Save the singular status before we call the clean-up helper */
862         fh_singular = v4l2_fh_is_singular_file(file);
863
864         /* the release helper will cleanup any on-going streaming */
865         ret = _vb2_fop_release(file, NULL);
866
867         /*
868          * If this was the last open file.
869          * Then de-initialize hw module.
870          */
871         if (fh_singular) {
872                 pm_runtime_suspend(&vin->vdev.dev);
873                 pm_runtime_disable(&vin->vdev.dev);
874                 rvin_power_off(vin);
875         }
876
877         mutex_unlock(&vin->lock);
878
879         return ret;
880 }
881
882 static const struct v4l2_file_operations rvin_fops = {
883         .owner          = THIS_MODULE,
884         .unlocked_ioctl = video_ioctl2,
885         .open           = rvin_open,
886         .release        = rvin_release,
887         .poll           = vb2_fop_poll,
888         .mmap           = vb2_fop_mmap,
889         .read           = vb2_fop_read,
890 };
891
892 /* -----------------------------------------------------------------------------
893  * Media controller file operations
894  */
895
896 static int rvin_mc_open(struct file *file)
897 {
898         struct rvin_dev *vin = video_drvdata(file);
899         int ret;
900
901         ret = mutex_lock_interruptible(&vin->lock);
902         if (ret)
903                 return ret;
904
905         ret = pm_runtime_get_sync(vin->dev);
906         if (ret < 0)
907                 goto err_unlock;
908
909         ret = v4l2_pipeline_pm_use(&vin->vdev.entity, 1);
910         if (ret < 0)
911                 goto err_pm;
912
913         file->private_data = vin;
914
915         ret = v4l2_fh_open(file);
916         if (ret)
917                 goto err_v4l2pm;
918
919         mutex_unlock(&vin->lock);
920
921         return 0;
922 err_v4l2pm:
923         v4l2_pipeline_pm_use(&vin->vdev.entity, 0);
924 err_pm:
925         pm_runtime_put(vin->dev);
926 err_unlock:
927         mutex_unlock(&vin->lock);
928
929         return ret;
930 }
931
932 static int rvin_mc_release(struct file *file)
933 {
934         struct rvin_dev *vin = video_drvdata(file);
935         int ret;
936
937         mutex_lock(&vin->lock);
938
939         /* the release helper will cleanup any on-going streaming. */
940         ret = _vb2_fop_release(file, NULL);
941
942         v4l2_pipeline_pm_use(&vin->vdev.entity, 0);
943         pm_runtime_put(vin->dev);
944
945         mutex_unlock(&vin->lock);
946
947         return ret;
948 }
949
950 static const struct v4l2_file_operations rvin_mc_fops = {
951         .owner          = THIS_MODULE,
952         .unlocked_ioctl = video_ioctl2,
953         .open           = rvin_mc_open,
954         .release        = rvin_mc_release,
955         .poll           = vb2_fop_poll,
956         .mmap           = vb2_fop_mmap,
957         .read           = vb2_fop_read,
958 };
959
960 void rvin_v4l2_unregister(struct rvin_dev *vin)
961 {
962         if (!video_is_registered(&vin->vdev))
963                 return;
964
965         v4l2_info(&vin->v4l2_dev, "Removing %s\n",
966                   video_device_node_name(&vin->vdev));
967
968         /* Checks internaly if vdev have been init or not */
969         video_unregister_device(&vin->vdev);
970 }
971
972 static void rvin_notify(struct v4l2_subdev *sd,
973                         unsigned int notification, void *arg)
974 {
975         struct rvin_dev *vin =
976                 container_of(sd->v4l2_dev, struct rvin_dev, v4l2_dev);
977
978         switch (notification) {
979         case V4L2_DEVICE_NOTIFY_EVENT:
980                 v4l2_event_queue(&vin->vdev, arg);
981                 break;
982         default:
983                 break;
984         }
985 }
986
987 int rvin_v4l2_register(struct rvin_dev *vin)
988 {
989         struct video_device *vdev = &vin->vdev;
990         int ret;
991
992         vin->v4l2_dev.notify = rvin_notify;
993
994         /* video node */
995         vdev->v4l2_dev = &vin->v4l2_dev;
996         vdev->queue = &vin->queue;
997         snprintf(vdev->name, sizeof(vdev->name), "VIN%u output", vin->id);
998         vdev->release = video_device_release_empty;
999         vdev->lock = &vin->lock;
1000         vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
1001                 V4L2_CAP_READWRITE;
1002
1003         /* Set a default format */
1004         vin->format.pixelformat = RVIN_DEFAULT_FORMAT;
1005         vin->format.width = RVIN_DEFAULT_WIDTH;
1006         vin->format.height = RVIN_DEFAULT_HEIGHT;
1007         vin->format.field = RVIN_DEFAULT_FIELD;
1008         vin->format.colorspace = RVIN_DEFAULT_COLORSPACE;
1009
1010         if (vin->info->use_mc) {
1011                 vdev->fops = &rvin_mc_fops;
1012                 vdev->ioctl_ops = &rvin_mc_ioctl_ops;
1013         } else {
1014                 vdev->fops = &rvin_fops;
1015                 vdev->ioctl_ops = &rvin_ioctl_ops;
1016                 rvin_reset_format(vin);
1017         }
1018
1019         rvin_format_align(vin, &vin->format);
1020
1021         ret = video_register_device(&vin->vdev, VFL_TYPE_GRABBER, -1);
1022         if (ret) {
1023                 vin_err(vin, "Failed to register video device\n");
1024                 return ret;
1025         }
1026
1027         video_set_drvdata(&vin->vdev, vin);
1028
1029         v4l2_info(&vin->v4l2_dev, "Device registered as %s\n",
1030                   video_device_node_name(&vin->vdev));
1031
1032         return ret;
1033 }