]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/media/platform/rcar-vin/rcar-v4l2.c
Merge tag 'media/v4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[linux.git] / drivers / media / platform / rcar-vin / rcar-v4l2.c
1 /*
2  * Driver for Renesas R-Car VIN
3  *
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
8  *
9  * Based on the soc-camera rcar_vin driver
10  *
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.
15  */
16
17 #include <linux/pm_runtime.h>
18
19 #include <media/v4l2-event.h>
20 #include <media/v4l2-ioctl.h>
21 #include <media/v4l2-rect.h>
22
23 #include "rcar-vin.h"
24
25 #define RVIN_DEFAULT_FORMAT     V4L2_PIX_FMT_YUYV
26 #define RVIN_MAX_WIDTH          2048
27 #define RVIN_MAX_HEIGHT         2048
28
29 /* -----------------------------------------------------------------------------
30  * Format Conversions
31  */
32
33 static const struct rvin_video_format rvin_formats[] = {
34         {
35                 .fourcc                 = V4L2_PIX_FMT_NV16,
36                 .bpp                    = 1,
37         },
38         {
39                 .fourcc                 = V4L2_PIX_FMT_YUYV,
40                 .bpp                    = 2,
41         },
42         {
43                 .fourcc                 = V4L2_PIX_FMT_UYVY,
44                 .bpp                    = 2,
45         },
46         {
47                 .fourcc                 = V4L2_PIX_FMT_RGB565,
48                 .bpp                    = 2,
49         },
50         {
51                 .fourcc                 = V4L2_PIX_FMT_XRGB555,
52                 .bpp                    = 2,
53         },
54         {
55                 .fourcc                 = V4L2_PIX_FMT_XBGR32,
56                 .bpp                    = 4,
57         },
58 };
59
60 const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat)
61 {
62         int i;
63
64         for (i = 0; i < ARRAY_SIZE(rvin_formats); i++)
65                 if (rvin_formats[i].fourcc == pixelformat)
66                         return rvin_formats + i;
67
68         return NULL;
69 }
70
71 static u32 rvin_format_bytesperline(struct v4l2_pix_format *pix)
72 {
73         const struct rvin_video_format *fmt;
74
75         fmt = rvin_format_from_pixel(pix->pixelformat);
76
77         if (WARN_ON(!fmt))
78                 return -EINVAL;
79
80         return pix->width * fmt->bpp;
81 }
82
83 static u32 rvin_format_sizeimage(struct v4l2_pix_format *pix)
84 {
85         if (pix->pixelformat == V4L2_PIX_FMT_NV16)
86                 return pix->bytesperline * pix->height * 2;
87
88         return pix->bytesperline * pix->height;
89 }
90
91 /* -----------------------------------------------------------------------------
92  * V4L2
93  */
94
95 static int __rvin_try_format_source(struct rvin_dev *vin,
96                                         u32 which,
97                                         struct v4l2_pix_format *pix,
98                                         struct rvin_source_fmt *source)
99 {
100         struct v4l2_subdev *sd;
101         struct v4l2_subdev_pad_config *pad_cfg;
102         struct v4l2_subdev_format format = {
103                 .which = which,
104         };
105         int ret;
106
107         sd = vin_to_source(vin);
108
109         v4l2_fill_mbus_format(&format.format, pix, vin->source.code);
110
111         pad_cfg = v4l2_subdev_alloc_pad_config(sd);
112         if (pad_cfg == NULL)
113                 return -ENOMEM;
114
115         format.pad = vin->src_pad_idx;
116
117         ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, pad, set_fmt,
118                                          pad_cfg, &format);
119         if (ret < 0)
120                 goto cleanup;
121
122         v4l2_fill_pix_format(pix, &format.format);
123
124         source->width = pix->width;
125         source->height = pix->height;
126
127         vin_dbg(vin, "Source resolution: %ux%u\n", source->width,
128                 source->height);
129
130 cleanup:
131         v4l2_subdev_free_pad_config(pad_cfg);
132         return 0;
133 }
134
135 static int __rvin_try_format(struct rvin_dev *vin,
136                                  u32 which,
137                                  struct v4l2_pix_format *pix,
138                                  struct rvin_source_fmt *source)
139 {
140         const struct rvin_video_format *info;
141         u32 rwidth, rheight, walign;
142
143         /* Requested */
144         rwidth = pix->width;
145         rheight = pix->height;
146
147         /*
148          * Retrieve format information and select the current format if the
149          * requested format isn't supported.
150          */
151         info = rvin_format_from_pixel(pix->pixelformat);
152         if (!info) {
153                 vin_dbg(vin, "Format %x not found, keeping %x\n",
154                         pix->pixelformat, vin->format.pixelformat);
155                 *pix = vin->format;
156                 pix->width = rwidth;
157                 pix->height = rheight;
158         }
159
160         /* Always recalculate */
161         pix->bytesperline = 0;
162         pix->sizeimage = 0;
163
164         /* Limit to source capabilities */
165         __rvin_try_format_source(vin, which, pix, source);
166
167         /* If source can't match format try if VIN can scale */
168         if (source->width != rwidth || source->height != rheight)
169                 rvin_scale_try(vin, pix, rwidth, rheight);
170
171         /* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
172         walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
173
174         /* Limit to VIN capabilities */
175         v4l_bound_align_image(&pix->width, 2, RVIN_MAX_WIDTH, walign,
176                               &pix->height, 4, RVIN_MAX_HEIGHT, 2, 0);
177
178         switch (pix->field) {
179         case V4L2_FIELD_NONE:
180         case V4L2_FIELD_TOP:
181         case V4L2_FIELD_BOTTOM:
182         case V4L2_FIELD_INTERLACED_TB:
183         case V4L2_FIELD_INTERLACED_BT:
184         case V4L2_FIELD_INTERLACED:
185                 break;
186         default:
187                 pix->field = V4L2_FIELD_NONE;
188                 break;
189         }
190
191         pix->bytesperline = max_t(u32, pix->bytesperline,
192                                   rvin_format_bytesperline(pix));
193         pix->sizeimage = max_t(u32, pix->sizeimage,
194                                rvin_format_sizeimage(pix));
195
196         vin_dbg(vin, "Requested %ux%u Got %ux%u bpl: %d size: %d\n",
197                 rwidth, rheight, pix->width, pix->height,
198                 pix->bytesperline, pix->sizeimage);
199
200         return 0;
201 }
202
203 static int rvin_querycap(struct file *file, void *priv,
204                          struct v4l2_capability *cap)
205 {
206         struct rvin_dev *vin = video_drvdata(file);
207
208         strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
209         strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
210         snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
211                  dev_name(vin->dev));
212         return 0;
213 }
214
215 static int rvin_try_fmt_vid_cap(struct file *file, void *priv,
216                                 struct v4l2_format *f)
217 {
218         struct rvin_dev *vin = video_drvdata(file);
219         struct rvin_source_fmt source;
220
221         return __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix,
222                                      &source);
223 }
224
225 static int rvin_s_fmt_vid_cap(struct file *file, void *priv,
226                               struct v4l2_format *f)
227 {
228         struct rvin_dev *vin = video_drvdata(file);
229         struct rvin_source_fmt source;
230         int ret;
231
232         if (vb2_is_busy(&vin->queue))
233                 return -EBUSY;
234
235         ret = __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
236                                     &source);
237         if (ret)
238                 return ret;
239
240         vin->source.width = source.width;
241         vin->source.height = source.height;
242
243         vin->format = f->fmt.pix;
244
245         return 0;
246 }
247
248 static int rvin_g_fmt_vid_cap(struct file *file, void *priv,
249                               struct v4l2_format *f)
250 {
251         struct rvin_dev *vin = video_drvdata(file);
252
253         f->fmt.pix = vin->format;
254
255         return 0;
256 }
257
258 static int rvin_enum_fmt_vid_cap(struct file *file, void *priv,
259                                  struct v4l2_fmtdesc *f)
260 {
261         if (f->index >= ARRAY_SIZE(rvin_formats))
262                 return -EINVAL;
263
264         f->pixelformat = rvin_formats[f->index].fourcc;
265
266         return 0;
267 }
268
269 static int rvin_g_selection(struct file *file, void *fh,
270                             struct v4l2_selection *s)
271 {
272         struct rvin_dev *vin = video_drvdata(file);
273
274         if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
275                 return -EINVAL;
276
277         switch (s->target) {
278         case V4L2_SEL_TGT_CROP_BOUNDS:
279         case V4L2_SEL_TGT_CROP_DEFAULT:
280                 s->r.left = s->r.top = 0;
281                 s->r.width = vin->source.width;
282                 s->r.height = vin->source.height;
283                 break;
284         case V4L2_SEL_TGT_CROP:
285                 s->r = vin->crop;
286                 break;
287         case V4L2_SEL_TGT_COMPOSE_BOUNDS:
288         case V4L2_SEL_TGT_COMPOSE_DEFAULT:
289                 s->r.left = s->r.top = 0;
290                 s->r.width = vin->format.width;
291                 s->r.height = vin->format.height;
292                 break;
293         case V4L2_SEL_TGT_COMPOSE:
294                 s->r = vin->compose;
295                 break;
296         default:
297                 return -EINVAL;
298         }
299
300         return 0;
301 }
302
303 static int rvin_s_selection(struct file *file, void *fh,
304                             struct v4l2_selection *s)
305 {
306         struct rvin_dev *vin = video_drvdata(file);
307         const struct rvin_video_format *fmt;
308         struct v4l2_rect r = s->r;
309         struct v4l2_rect max_rect;
310         struct v4l2_rect min_rect = {
311                 .width = 6,
312                 .height = 2,
313         };
314
315         if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
316                 return -EINVAL;
317
318         v4l2_rect_set_min_size(&r, &min_rect);
319
320         switch (s->target) {
321         case V4L2_SEL_TGT_CROP:
322                 /* Can't crop outside of source input */
323                 max_rect.top = max_rect.left = 0;
324                 max_rect.width = vin->source.width;
325                 max_rect.height = vin->source.height;
326                 v4l2_rect_map_inside(&r, &max_rect);
327
328                 v4l_bound_align_image(&r.width, 2, vin->source.width, 1,
329                                       &r.height, 4, vin->source.height, 2, 0);
330
331                 r.top  = clamp_t(s32, r.top, 0, vin->source.height - r.height);
332                 r.left = clamp_t(s32, r.left, 0, vin->source.width - r.width);
333
334                 vin->crop = s->r = r;
335
336                 vin_dbg(vin, "Cropped %dx%d@%d:%d of %dx%d\n",
337                          r.width, r.height, r.left, r.top,
338                          vin->source.width, vin->source.height);
339                 break;
340         case V4L2_SEL_TGT_COMPOSE:
341                 /* Make sure compose rect fits inside output format */
342                 max_rect.top = max_rect.left = 0;
343                 max_rect.width = vin->format.width;
344                 max_rect.height = vin->format.height;
345                 v4l2_rect_map_inside(&r, &max_rect);
346
347                 /*
348                  * Composing is done by adding a offset to the buffer address,
349                  * the HW wants this address to be aligned to HW_BUFFER_MASK.
350                  * Make sure the top and left values meets this requirement.
351                  */
352                 while ((r.top * vin->format.bytesperline) & HW_BUFFER_MASK)
353                         r.top--;
354
355                 fmt = rvin_format_from_pixel(vin->format.pixelformat);
356                 while ((r.left * fmt->bpp) & HW_BUFFER_MASK)
357                         r.left--;
358
359                 vin->compose = s->r = r;
360
361                 vin_dbg(vin, "Compose %dx%d@%d:%d in %dx%d\n",
362                          r.width, r.height, r.left, r.top,
363                          vin->format.width, vin->format.height);
364                 break;
365         default:
366                 return -EINVAL;
367         }
368
369         /* HW supports modifying configuration while running */
370         rvin_crop_scale_comp(vin);
371
372         return 0;
373 }
374
375 static int rvin_cropcap(struct file *file, void *priv,
376                         struct v4l2_cropcap *crop)
377 {
378         struct rvin_dev *vin = video_drvdata(file);
379         struct v4l2_subdev *sd = vin_to_source(vin);
380
381         if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
382                 return -EINVAL;
383
384         return v4l2_subdev_call(sd, video, cropcap, crop);
385 }
386
387 static int rvin_enum_input(struct file *file, void *priv,
388                            struct v4l2_input *i)
389 {
390         struct rvin_dev *vin = video_drvdata(file);
391         struct v4l2_subdev *sd = vin_to_source(vin);
392         int ret;
393
394         if (i->index != 0)
395                 return -EINVAL;
396
397         ret = v4l2_subdev_call(sd, video, g_input_status, &i->status);
398         if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
399                 return ret;
400
401         i->type = V4L2_INPUT_TYPE_CAMERA;
402         i->std = vin->vdev.tvnorms;
403
404         if (v4l2_subdev_has_op(sd, pad, dv_timings_cap))
405                 i->capabilities = V4L2_IN_CAP_DV_TIMINGS;
406
407         strlcpy(i->name, "Camera", sizeof(i->name));
408
409         return 0;
410 }
411
412 static int rvin_g_input(struct file *file, void *priv, unsigned int *i)
413 {
414         *i = 0;
415         return 0;
416 }
417
418 static int rvin_s_input(struct file *file, void *priv, unsigned int i)
419 {
420         if (i > 0)
421                 return -EINVAL;
422         return 0;
423 }
424
425 static int rvin_querystd(struct file *file, void *priv, v4l2_std_id *a)
426 {
427         struct rvin_dev *vin = video_drvdata(file);
428         struct v4l2_subdev *sd = vin_to_source(vin);
429
430         return v4l2_subdev_call(sd, video, querystd, a);
431 }
432
433 static int rvin_s_std(struct file *file, void *priv, v4l2_std_id a)
434 {
435         struct rvin_dev *vin = video_drvdata(file);
436         struct v4l2_subdev *sd = vin_to_source(vin);
437         struct v4l2_subdev_format fmt = {
438                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
439         };
440         struct v4l2_mbus_framefmt *mf = &fmt.format;
441         int ret = v4l2_subdev_call(sd, video, s_std, a);
442
443         if (ret < 0)
444                 return ret;
445
446         /* Changing the standard will change the width/height */
447         ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
448         if (ret) {
449                 vin_err(vin, "Failed to get initial format\n");
450                 return ret;
451         }
452
453         vin->format.width = mf->width;
454         vin->format.height = mf->height;
455
456         vin->crop.top = vin->crop.left = 0;
457         vin->crop.width = mf->width;
458         vin->crop.height = mf->height;
459
460         vin->compose.top = vin->compose.left = 0;
461         vin->compose.width = mf->width;
462         vin->compose.height = mf->height;
463
464         return 0;
465 }
466
467 static int rvin_g_std(struct file *file, void *priv, v4l2_std_id *a)
468 {
469         struct rvin_dev *vin = video_drvdata(file);
470         struct v4l2_subdev *sd = vin_to_source(vin);
471
472         return v4l2_subdev_call(sd, video, g_std, a);
473 }
474
475 static int rvin_subscribe_event(struct v4l2_fh *fh,
476                                 const struct v4l2_event_subscription *sub)
477 {
478         switch (sub->type) {
479         case V4L2_EVENT_SOURCE_CHANGE:
480                 return v4l2_event_subscribe(fh, sub, 4, NULL);
481         }
482         return v4l2_ctrl_subscribe_event(fh, sub);
483 }
484
485 static int rvin_enum_dv_timings(struct file *file, void *priv_fh,
486                                     struct v4l2_enum_dv_timings *timings)
487 {
488         struct rvin_dev *vin = video_drvdata(file);
489         struct v4l2_subdev *sd = vin_to_source(vin);
490         int pad, ret;
491
492         pad = timings->pad;
493         timings->pad = vin->src_pad_idx;
494
495         ret = v4l2_subdev_call(sd, pad, enum_dv_timings, timings);
496
497         timings->pad = pad;
498
499         return ret;
500 }
501
502 static int rvin_s_dv_timings(struct file *file, void *priv_fh,
503                                     struct v4l2_dv_timings *timings)
504 {
505         struct rvin_dev *vin = video_drvdata(file);
506         struct v4l2_subdev *sd = vin_to_source(vin);
507         int err;
508
509         err = v4l2_subdev_call(sd,
510                         video, s_dv_timings, timings);
511         if (!err) {
512                 vin->source.width = timings->bt.width;
513                 vin->source.height = timings->bt.height;
514                 vin->format.width = timings->bt.width;
515                 vin->format.height = timings->bt.height;
516         }
517         return err;
518 }
519
520 static int rvin_g_dv_timings(struct file *file, void *priv_fh,
521                                     struct v4l2_dv_timings *timings)
522 {
523         struct rvin_dev *vin = video_drvdata(file);
524         struct v4l2_subdev *sd = vin_to_source(vin);
525
526         return v4l2_subdev_call(sd,
527                         video, g_dv_timings, timings);
528 }
529
530 static int rvin_query_dv_timings(struct file *file, void *priv_fh,
531                                     struct v4l2_dv_timings *timings)
532 {
533         struct rvin_dev *vin = video_drvdata(file);
534         struct v4l2_subdev *sd = vin_to_source(vin);
535
536         return v4l2_subdev_call(sd,
537                         video, query_dv_timings, timings);
538 }
539
540 static int rvin_dv_timings_cap(struct file *file, void *priv_fh,
541                                     struct v4l2_dv_timings_cap *cap)
542 {
543         struct rvin_dev *vin = video_drvdata(file);
544         struct v4l2_subdev *sd = vin_to_source(vin);
545         int pad, ret;
546
547         pad = cap->pad;
548         cap->pad = vin->src_pad_idx;
549
550         ret = v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
551
552         cap->pad = pad;
553
554         return ret;
555 }
556
557 static const struct v4l2_ioctl_ops rvin_ioctl_ops = {
558         .vidioc_querycap                = rvin_querycap,
559         .vidioc_try_fmt_vid_cap         = rvin_try_fmt_vid_cap,
560         .vidioc_g_fmt_vid_cap           = rvin_g_fmt_vid_cap,
561         .vidioc_s_fmt_vid_cap           = rvin_s_fmt_vid_cap,
562         .vidioc_enum_fmt_vid_cap        = rvin_enum_fmt_vid_cap,
563
564         .vidioc_g_selection             = rvin_g_selection,
565         .vidioc_s_selection             = rvin_s_selection,
566
567         .vidioc_cropcap                 = rvin_cropcap,
568
569         .vidioc_enum_input              = rvin_enum_input,
570         .vidioc_g_input                 = rvin_g_input,
571         .vidioc_s_input                 = rvin_s_input,
572
573         .vidioc_dv_timings_cap          = rvin_dv_timings_cap,
574         .vidioc_enum_dv_timings         = rvin_enum_dv_timings,
575         .vidioc_g_dv_timings            = rvin_g_dv_timings,
576         .vidioc_s_dv_timings            = rvin_s_dv_timings,
577         .vidioc_query_dv_timings        = rvin_query_dv_timings,
578
579         .vidioc_querystd                = rvin_querystd,
580         .vidioc_g_std                   = rvin_g_std,
581         .vidioc_s_std                   = rvin_s_std,
582
583         .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
584         .vidioc_create_bufs             = vb2_ioctl_create_bufs,
585         .vidioc_querybuf                = vb2_ioctl_querybuf,
586         .vidioc_qbuf                    = vb2_ioctl_qbuf,
587         .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
588         .vidioc_expbuf                  = vb2_ioctl_expbuf,
589         .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
590         .vidioc_streamon                = vb2_ioctl_streamon,
591         .vidioc_streamoff               = vb2_ioctl_streamoff,
592
593         .vidioc_log_status              = v4l2_ctrl_log_status,
594         .vidioc_subscribe_event         = rvin_subscribe_event,
595         .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
596 };
597
598 /* -----------------------------------------------------------------------------
599  * File Operations
600  */
601
602 static int rvin_power_on(struct rvin_dev *vin)
603 {
604         int ret;
605         struct v4l2_subdev *sd = vin_to_source(vin);
606
607         pm_runtime_get_sync(vin->v4l2_dev.dev);
608
609         ret = v4l2_subdev_call(sd, core, s_power, 1);
610         if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
611                 return ret;
612         return 0;
613 }
614
615 static int rvin_power_off(struct rvin_dev *vin)
616 {
617         int ret;
618         struct v4l2_subdev *sd = vin_to_source(vin);
619
620         ret = v4l2_subdev_call(sd, core, s_power, 0);
621
622         pm_runtime_put(vin->v4l2_dev.dev);
623
624         if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
625                 return ret;
626
627         return 0;
628 }
629
630 static int rvin_initialize_device(struct file *file)
631 {
632         struct rvin_dev *vin = video_drvdata(file);
633         int ret;
634
635         struct v4l2_format f = {
636                 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
637                 .fmt.pix = {
638                         .width          = vin->format.width,
639                         .height         = vin->format.height,
640                         .field          = vin->format.field,
641                         .colorspace     = vin->format.colorspace,
642                         .pixelformat    = vin->format.pixelformat,
643                 },
644         };
645
646         ret = rvin_power_on(vin);
647         if (ret < 0)
648                 return ret;
649
650         pm_runtime_enable(&vin->vdev.dev);
651         ret = pm_runtime_resume(&vin->vdev.dev);
652         if (ret < 0 && ret != -ENOSYS)
653                 goto eresume;
654
655         /*
656          * Try to configure with default parameters. Notice: this is the
657          * very first open, so, we cannot race against other calls,
658          * apart from someone else calling open() simultaneously, but
659          * .host_lock is protecting us against it.
660          */
661         ret = rvin_s_fmt_vid_cap(file, NULL, &f);
662         if (ret < 0)
663                 goto esfmt;
664
665         v4l2_ctrl_handler_setup(&vin->ctrl_handler);
666
667         return 0;
668 esfmt:
669         pm_runtime_disable(&vin->vdev.dev);
670 eresume:
671         rvin_power_off(vin);
672
673         return ret;
674 }
675
676 static int rvin_open(struct file *file)
677 {
678         struct rvin_dev *vin = video_drvdata(file);
679         int ret;
680
681         mutex_lock(&vin->lock);
682
683         file->private_data = vin;
684
685         ret = v4l2_fh_open(file);
686         if (ret)
687                 goto unlock;
688
689         if (!v4l2_fh_is_singular_file(file))
690                 goto unlock;
691
692         if (rvin_initialize_device(file)) {
693                 v4l2_fh_release(file);
694                 ret = -ENODEV;
695         }
696
697 unlock:
698         mutex_unlock(&vin->lock);
699         return ret;
700 }
701
702 static int rvin_release(struct file *file)
703 {
704         struct rvin_dev *vin = video_drvdata(file);
705         bool fh_singular;
706         int ret;
707
708         mutex_lock(&vin->lock);
709
710         /* Save the singular status before we call the clean-up helper */
711         fh_singular = v4l2_fh_is_singular_file(file);
712
713         /* the release helper will cleanup any on-going streaming */
714         ret = _vb2_fop_release(file, NULL);
715
716         /*
717          * If this was the last open file.
718          * Then de-initialize hw module.
719          */
720         if (fh_singular) {
721                 pm_runtime_suspend(&vin->vdev.dev);
722                 pm_runtime_disable(&vin->vdev.dev);
723                 rvin_power_off(vin);
724         }
725
726         mutex_unlock(&vin->lock);
727
728         return ret;
729 }
730
731 static const struct v4l2_file_operations rvin_fops = {
732         .owner          = THIS_MODULE,
733         .unlocked_ioctl = video_ioctl2,
734         .open           = rvin_open,
735         .release        = rvin_release,
736         .poll           = vb2_fop_poll,
737         .mmap           = vb2_fop_mmap,
738         .read           = vb2_fop_read,
739 };
740
741 void rvin_v4l2_remove(struct rvin_dev *vin)
742 {
743         v4l2_info(&vin->v4l2_dev, "Removing %s\n",
744                   video_device_node_name(&vin->vdev));
745
746         /* Checks internaly if handlers have been init or not */
747         v4l2_ctrl_handler_free(&vin->ctrl_handler);
748
749         /* Checks internaly if vdev have been init or not */
750         video_unregister_device(&vin->vdev);
751 }
752
753 static void rvin_notify(struct v4l2_subdev *sd,
754                         unsigned int notification, void *arg)
755 {
756         struct rvin_dev *vin =
757                 container_of(sd->v4l2_dev, struct rvin_dev, v4l2_dev);
758
759         switch (notification) {
760         case V4L2_DEVICE_NOTIFY_EVENT:
761                 v4l2_event_queue(&vin->vdev, arg);
762                 break;
763         default:
764                 break;
765         }
766 }
767
768 int rvin_v4l2_probe(struct rvin_dev *vin)
769 {
770         struct v4l2_subdev_format fmt = {
771                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
772         };
773         struct v4l2_mbus_framefmt *mf = &fmt.format;
774         struct video_device *vdev = &vin->vdev;
775         struct v4l2_subdev *sd = vin_to_source(vin);
776 #if defined(CONFIG_MEDIA_CONTROLLER)
777         int pad_idx;
778 #endif
779         int ret;
780
781         v4l2_set_subdev_hostdata(sd, vin);
782
783         vin->v4l2_dev.notify = rvin_notify;
784
785         ret = v4l2_subdev_call(sd, video, g_tvnorms, &vin->vdev.tvnorms);
786         if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
787                 return ret;
788
789         if (vin->vdev.tvnorms == 0) {
790                 /* Disable the STD API if there are no tvnorms defined */
791                 v4l2_disable_ioctl(&vin->vdev, VIDIOC_G_STD);
792                 v4l2_disable_ioctl(&vin->vdev, VIDIOC_S_STD);
793                 v4l2_disable_ioctl(&vin->vdev, VIDIOC_QUERYSTD);
794                 v4l2_disable_ioctl(&vin->vdev, VIDIOC_ENUMSTD);
795         }
796
797         /* Add the controls */
798         /*
799          * Currently the subdev with the largest number of controls (13) is
800          * ov6550. So let's pick 16 as a hint for the control handler. Note
801          * that this is a hint only: too large and you waste some memory, too
802          * small and there is a (very) small performance hit when looking up
803          * controls in the internal hash.
804          */
805         ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16);
806         if (ret < 0)
807                 return ret;
808
809         ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, sd->ctrl_handler, NULL);
810         if (ret < 0)
811                 return ret;
812
813         /* video node */
814         vdev->fops = &rvin_fops;
815         vdev->v4l2_dev = &vin->v4l2_dev;
816         vdev->queue = &vin->queue;
817         strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
818         vdev->release = video_device_release_empty;
819         vdev->ioctl_ops = &rvin_ioctl_ops;
820         vdev->lock = &vin->lock;
821         vdev->ctrl_handler = &vin->ctrl_handler;
822         vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
823                 V4L2_CAP_READWRITE;
824
825         vin->src_pad_idx = 0;
826 #if defined(CONFIG_MEDIA_CONTROLLER)
827         for (pad_idx = 0; pad_idx < sd->entity.num_pads; pad_idx++)
828                 if (sd->entity.pads[pad_idx].flags
829                                 == MEDIA_PAD_FL_SOURCE)
830                         break;
831         if (pad_idx >= sd->entity.num_pads)
832                 return -EINVAL;
833
834         vin->src_pad_idx = pad_idx;
835 #endif
836         fmt.pad = vin->src_pad_idx;
837
838         /* Try to improve our guess of a reasonable window format */
839         ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
840         if (ret) {
841                 vin_err(vin, "Failed to get initial format\n");
842                 return ret;
843         }
844
845         /* Set default format */
846         vin->format.width       = mf->width;
847         vin->format.height      = mf->height;
848         vin->format.colorspace  = mf->colorspace;
849         vin->format.field       = mf->field;
850         vin->format.pixelformat = RVIN_DEFAULT_FORMAT;
851
852
853         /* Set initial crop and compose */
854         vin->crop.top = vin->crop.left = 0;
855         vin->crop.width = mf->width;
856         vin->crop.height = mf->height;
857
858         vin->compose.top = vin->compose.left = 0;
859         vin->compose.width = mf->width;
860         vin->compose.height = mf->height;
861
862         ret = video_register_device(&vin->vdev, VFL_TYPE_GRABBER, -1);
863         if (ret) {
864                 vin_err(vin, "Failed to register video device\n");
865                 return ret;
866         }
867
868         video_set_drvdata(&vin->vdev, vin);
869
870         v4l2_info(&vin->v4l2_dev, "Device registered as %s\n",
871                   video_device_node_name(&vin->vdev));
872
873         return ret;
874 }