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