cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rcar-v4l2.c (25645B)


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