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