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