• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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