File Index
Files and directories
Sign in
FILE

imx8-isi-video.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * V4L2 Capture ISI subdev driver for i.MX8QXP/QM platform
   4 *
   5 * ISI is a Image Sensor Interface of i.MX8QXP/QM platform, which
   6 * used to process image from camera sensor to memory or DC
   7 *
   8 * Copyright (c) 2019 NXP Semiconductor
   9 */
  10
  11#include <linux/device.h>
  12#include <linux/dma-mapping.h>
  13#include <linux/errno.h>
  14#include <linux/kernel.h>
  15#include <linux/media-bus-format.h>
  16#include <linux/minmax.h>
  17#include <linux/pm_runtime.h>
  18#include <linux/string.h>
  19#include <linux/types.h>
  20#include <linux/videodev2.h>
  21
  22#include <media/media-entity.h>
  23#include <media/v4l2-ctrls.h>
  24#include <media/v4l2-dev.h>
  25#include <media/v4l2-event.h>
  26#include <media/v4l2-fh.h>
  27#include <media/v4l2-ioctl.h>
  28#include <media/v4l2-subdev.h>
  29#include <media/videobuf2-core.h>
  30#include <media/videobuf2-dma-contig.h>
  31#include <media/videobuf2-v4l2.h>
  32
  33#include "imx8-isi-core.h"
  34#include "imx8-isi-regs.h"
  35
  36/* Keep the first entry matching MXC_ISI_DEF_PIXEL_FORMAT */
  37static const struct mxc_isi_format_info mxc_isi_formats[] = {
  38	/* YUV formats */
  39	{
  40		.mbus_code	= MEDIA_BUS_FMT_YUV8_1X24,
  41		.fourcc		= V4L2_PIX_FMT_YUYV,
  42		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
  43				| MXC_ISI_VIDEO_M2M_CAP,
  44		.isi_in_format	= CHNL_MEM_RD_CTRL_IMG_TYPE_YUV422_1P8P,
  45		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_YUV422_1P8P,
  46		.mem_planes	= 1,
  47		.color_planes	= 1,
  48		.depth		= { 16 },
  49		.encoding	= MXC_ISI_ENC_YUV,
  50	}, {
  51		.mbus_code	= MEDIA_BUS_FMT_YUV8_1X24,
  52		.fourcc		= V4L2_PIX_FMT_YUVA32,
  53		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
  54		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_YUV444_1P8,
  55		.mem_planes	= 1,
  56		.color_planes	= 1,
  57		.depth		= { 32 },
  58		.encoding	= MXC_ISI_ENC_YUV,
  59	}, {
  60		.mbus_code	= MEDIA_BUS_FMT_YUV8_1X24,
  61		.fourcc		= V4L2_PIX_FMT_NV12,
  62		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
  63		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_YUV420_2P8P,
  64		.color_planes	= 2,
  65		.mem_planes	= 1,
  66		.depth		= { 8, 16 },
  67		.hsub		= 2,
  68		.vsub		= 2,
  69		.encoding	= MXC_ISI_ENC_YUV,
  70	}, {
  71		.mbus_code	= MEDIA_BUS_FMT_YUV8_1X24,
  72		.fourcc		= V4L2_PIX_FMT_NV12M,
  73		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
  74		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_YUV420_2P8P,
  75		.mem_planes	= 2,
  76		.color_planes	= 2,
  77		.depth		= { 8, 16 },
  78		.hsub		= 2,
  79		.vsub		= 2,
  80		.encoding	= MXC_ISI_ENC_YUV,
  81	}, {
  82		.mbus_code	= MEDIA_BUS_FMT_YUV8_1X24,
  83		.fourcc		= V4L2_PIX_FMT_NV16,
  84		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
  85		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_YUV422_2P8P,
  86		.color_planes	= 2,
  87		.mem_planes	= 1,
  88		.depth		= { 8, 16 },
  89		.hsub		= 2,
  90		.vsub		= 1,
  91		.encoding	= MXC_ISI_ENC_YUV,
  92	}, {
  93		.mbus_code	= MEDIA_BUS_FMT_YUV8_1X24,
  94		.fourcc		= V4L2_PIX_FMT_NV16M,
  95		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
  96		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_YUV422_2P8P,
  97		.mem_planes	= 2,
  98		.color_planes	= 2,
  99		.depth		= { 8, 16 },
 100		.hsub		= 2,
 101		.vsub		= 1,
 102		.encoding	= MXC_ISI_ENC_YUV,
 103	}, {
 104		.mbus_code	= MEDIA_BUS_FMT_YUV8_1X24,
 105		.fourcc		= V4L2_PIX_FMT_YUV444M,
 106		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
 107		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_YUV444_3P8P,
 108		.mem_planes	= 3,
 109		.color_planes	= 3,
 110		.depth		= { 8, 8, 8 },
 111		.hsub		= 1,
 112		.vsub		= 1,
 113		.encoding	= MXC_ISI_ENC_YUV,
 114	},
 115	/* RGB formats */
 116	{
 117		.mbus_code	= MEDIA_BUS_FMT_RGB888_1X24,
 118		.fourcc		= V4L2_PIX_FMT_RGB565,
 119		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
 120				| MXC_ISI_VIDEO_M2M_CAP,
 121		.isi_in_format	= CHNL_MEM_RD_CTRL_IMG_TYPE_RGB565,
 122		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RGB565,
 123		.mem_planes	= 1,
 124		.color_planes	= 1,
 125		.depth		= { 16 },
 126		.encoding	= MXC_ISI_ENC_RGB,
 127	}, {
 128		.mbus_code	= MEDIA_BUS_FMT_RGB888_1X24,
 129		.fourcc		= V4L2_PIX_FMT_RGB24,
 130		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
 131				| MXC_ISI_VIDEO_M2M_CAP,
 132		.isi_in_format	= CHNL_MEM_RD_CTRL_IMG_TYPE_BGR8P,
 133		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_BGR888P,
 134		.mem_planes	= 1,
 135		.color_planes	= 1,
 136		.depth		= { 24 },
 137		.encoding	= MXC_ISI_ENC_RGB,
 138	}, {
 139		.mbus_code	= MEDIA_BUS_FMT_RGB888_1X24,
 140		.fourcc		= V4L2_PIX_FMT_BGR24,
 141		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
 142				| MXC_ISI_VIDEO_M2M_CAP,
 143		.isi_in_format	= CHNL_MEM_RD_CTRL_IMG_TYPE_RGB8P,
 144		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RGB888P,
 145		.mem_planes	= 1,
 146		.color_planes	= 1,
 147		.depth		= { 24 },
 148		.encoding	= MXC_ISI_ENC_RGB,
 149	}, {
 150		.mbus_code	= MEDIA_BUS_FMT_RGB888_1X24,
 151		.fourcc		= V4L2_PIX_FMT_XBGR32,
 152		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
 153				| MXC_ISI_VIDEO_M2M_CAP,
 154		.isi_in_format	= CHNL_MEM_RD_CTRL_IMG_TYPE_XBGR8,
 155		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_XRGB888,
 156		.mem_planes	= 1,
 157		.color_planes	= 1,
 158		.depth		= { 32 },
 159		.encoding	= MXC_ISI_ENC_RGB,
 160	}, {
 161		.mbus_code	= MEDIA_BUS_FMT_RGB888_1X24,
 162		.fourcc		= V4L2_PIX_FMT_ABGR32,
 163		.type		= MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
 164		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_ARGB8888,
 165		.mem_planes	= 1,
 166		.color_planes	= 1,
 167		.depth		= { 32 },
 168		.encoding	= MXC_ISI_ENC_RGB,
 169	},
 170	/*
 171	 * RAW formats
 172	 *
 173	 * The ISI shifts the 10-bit and 12-bit formats left by 6 and 4 bits
 174	 * when using CHNL_IMG_CTRL_FORMAT_RAW10 or MXC_ISI_OUT_FMT_RAW12
 175	 * respectively, to align the bits to the left and pad with zeros in
 176	 * the LSBs. The corresponding V4L2 formats are however right-aligned,
 177	 * we have to use CHNL_IMG_CTRL_FORMAT_RAW16 to avoid the left shift.
 178	 */
 179	{
 180		.mbus_code	= MEDIA_BUS_FMT_Y8_1X8,
 181		.fourcc		= V4L2_PIX_FMT_GREY,
 182		.type		= MXC_ISI_VIDEO_CAP,
 183		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW8,
 184		.mem_planes	= 1,
 185		.color_planes	= 1,
 186		.depth		= { 8 },
 187		.encoding	= MXC_ISI_ENC_RAW,
 188	}, {
 189		.mbus_code	= MEDIA_BUS_FMT_Y10_1X10,
 190		.fourcc		= V4L2_PIX_FMT_Y10,
 191		.type		= MXC_ISI_VIDEO_CAP,
 192		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 193		.mem_planes	= 1,
 194		.color_planes	= 1,
 195		.depth		= { 16 },
 196		.encoding	= MXC_ISI_ENC_RAW,
 197	}, {
 198		.mbus_code	= MEDIA_BUS_FMT_Y12_1X12,
 199		.fourcc		= V4L2_PIX_FMT_Y12,
 200		.type		= MXC_ISI_VIDEO_CAP,
 201		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 202		.mem_planes	= 1,
 203		.color_planes	= 1,
 204		.depth		= { 16 },
 205		.encoding	= MXC_ISI_ENC_RAW,
 206	}, {
 207		.mbus_code	= MEDIA_BUS_FMT_Y14_1X14,
 208		.fourcc		= V4L2_PIX_FMT_Y14,
 209		.type		= MXC_ISI_VIDEO_CAP,
 210		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 211		.mem_planes	= 1,
 212		.color_planes	= 1,
 213		.depth		= { 16 },
 214		.encoding	= MXC_ISI_ENC_RAW,
 215	}, {
 216		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
 217		.fourcc		= V4L2_PIX_FMT_SBGGR8,
 218		.type		= MXC_ISI_VIDEO_CAP,
 219		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW8,
 220		.mem_planes	= 1,
 221		.color_planes	= 1,
 222		.depth		= { 8 },
 223		.encoding	= MXC_ISI_ENC_RAW,
 224	}, {
 225		.mbus_code	= MEDIA_BUS_FMT_SGBRG8_1X8,
 226		.fourcc		= V4L2_PIX_FMT_SGBRG8,
 227		.type		= MXC_ISI_VIDEO_CAP,
 228		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW8,
 229		.mem_planes	= 1,
 230		.color_planes	= 1,
 231		.depth		= { 8 },
 232		.encoding	= MXC_ISI_ENC_RAW,
 233	}, {
 234		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
 235		.fourcc		= V4L2_PIX_FMT_SGRBG8,
 236		.type		= MXC_ISI_VIDEO_CAP,
 237		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW8,
 238		.mem_planes	= 1,
 239		.color_planes	= 1,
 240		.depth		= { 8 },
 241		.encoding	= MXC_ISI_ENC_RAW,
 242	}, {
 243		.mbus_code	= MEDIA_BUS_FMT_SRGGB8_1X8,
 244		.fourcc		= V4L2_PIX_FMT_SRGGB8,
 245		.type		= MXC_ISI_VIDEO_CAP,
 246		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW8,
 247		.mem_planes	= 1,
 248		.color_planes	= 1,
 249		.depth		= { 8 },
 250		.encoding	= MXC_ISI_ENC_RAW,
 251	}, {
 252		.mbus_code	= MEDIA_BUS_FMT_SBGGR10_1X10,
 253		.fourcc		= V4L2_PIX_FMT_SBGGR10,
 254		.type		= MXC_ISI_VIDEO_CAP,
 255		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 256		.mem_planes	= 1,
 257		.color_planes	= 1,
 258		.depth		= { 16 },
 259		.encoding	= MXC_ISI_ENC_RAW,
 260	}, {
 261		.mbus_code	= MEDIA_BUS_FMT_SGBRG10_1X10,
 262		.fourcc		= V4L2_PIX_FMT_SGBRG10,
 263		.type		= MXC_ISI_VIDEO_CAP,
 264		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 265		.mem_planes	= 1,
 266		.color_planes	= 1,
 267		.depth		= { 16 },
 268		.encoding	= MXC_ISI_ENC_RAW,
 269	}, {
 270		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
 271		.fourcc		= V4L2_PIX_FMT_SGRBG10,
 272		.type		= MXC_ISI_VIDEO_CAP,
 273		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 274		.mem_planes	= 1,
 275		.color_planes	= 1,
 276		.depth		= { 16 },
 277		.encoding	= MXC_ISI_ENC_RAW,
 278	}, {
 279		.mbus_code	= MEDIA_BUS_FMT_SRGGB10_1X10,
 280		.fourcc		= V4L2_PIX_FMT_SRGGB10,
 281		.type		= MXC_ISI_VIDEO_CAP,
 282		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 283		.mem_planes	= 1,
 284		.color_planes	= 1,
 285		.depth		= { 16 },
 286		.encoding	= MXC_ISI_ENC_RAW,
 287	}, {
 288		.mbus_code	= MEDIA_BUS_FMT_SBGGR12_1X12,
 289		.fourcc		= V4L2_PIX_FMT_SBGGR12,
 290		.type		= MXC_ISI_VIDEO_CAP,
 291		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 292		.mem_planes	= 1,
 293		.color_planes	= 1,
 294		.depth		= { 16 },
 295		.encoding	= MXC_ISI_ENC_RAW,
 296	}, {
 297		.mbus_code	= MEDIA_BUS_FMT_SGBRG12_1X12,
 298		.fourcc		= V4L2_PIX_FMT_SGBRG12,
 299		.type		= MXC_ISI_VIDEO_CAP,
 300		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 301		.mem_planes	= 1,
 302		.color_planes	= 1,
 303		.depth		= { 16 },
 304		.encoding	= MXC_ISI_ENC_RAW,
 305	}, {
 306		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
 307		.fourcc		= V4L2_PIX_FMT_SGRBG12,
 308		.type		= MXC_ISI_VIDEO_CAP,
 309		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 310		.mem_planes	= 1,
 311		.color_planes	= 1,
 312		.depth		= { 16 },
 313		.encoding	= MXC_ISI_ENC_RAW,
 314	}, {
 315		.mbus_code	= MEDIA_BUS_FMT_SRGGB12_1X12,
 316		.fourcc		= V4L2_PIX_FMT_SRGGB12,
 317		.type		= MXC_ISI_VIDEO_CAP,
 318		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 319		.mem_planes	= 1,
 320		.color_planes	= 1,
 321		.depth		= { 16 },
 322		.encoding	= MXC_ISI_ENC_RAW,
 323	}, {
 324		.mbus_code	= MEDIA_BUS_FMT_SBGGR14_1X14,
 325		.fourcc		= V4L2_PIX_FMT_SBGGR14,
 326		.type		= MXC_ISI_VIDEO_CAP,
 327		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 328		.mem_planes	= 1,
 329		.color_planes	= 1,
 330		.depth		= { 16 },
 331		.encoding	= MXC_ISI_ENC_RAW,
 332	}, {
 333		.mbus_code	= MEDIA_BUS_FMT_SGBRG14_1X14,
 334		.fourcc		= V4L2_PIX_FMT_SGBRG14,
 335		.type		= MXC_ISI_VIDEO_CAP,
 336		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 337		.mem_planes	= 1,
 338		.color_planes	= 1,
 339		.depth		= { 16 },
 340		.encoding	= MXC_ISI_ENC_RAW,
 341	}, {
 342		.mbus_code	= MEDIA_BUS_FMT_SGRBG14_1X14,
 343		.fourcc		= V4L2_PIX_FMT_SGRBG14,
 344		.type		= MXC_ISI_VIDEO_CAP,
 345		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 346		.mem_planes	= 1,
 347		.color_planes	= 1,
 348		.depth		= { 16 },
 349		.encoding	= MXC_ISI_ENC_RAW,
 350	}, {
 351		.mbus_code	= MEDIA_BUS_FMT_SRGGB14_1X14,
 352		.fourcc		= V4L2_PIX_FMT_SRGGB14,
 353		.type		= MXC_ISI_VIDEO_CAP,
 354		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW16,
 355		.mem_planes	= 1,
 356		.color_planes	= 1,
 357		.depth		= { 16 },
 358		.encoding	= MXC_ISI_ENC_RAW,
 359	},
 360	/* JPEG */
 361	{
 362		.mbus_code	= MEDIA_BUS_FMT_JPEG_1X8,
 363		.fourcc		= V4L2_PIX_FMT_MJPEG,
 364		.type		= MXC_ISI_VIDEO_CAP,
 365		.isi_out_format	= CHNL_IMG_CTRL_FORMAT_RAW8,
 366		.mem_planes	= 1,
 367		.color_planes	= 1,
 368		.depth		= { 8 },
 369		.encoding	= MXC_ISI_ENC_RAW,
 370	}
 371};
 372
 373const struct mxc_isi_format_info *
 374mxc_isi_format_by_fourcc(u32 fourcc, enum mxc_isi_video_type type)
 375{
 376	unsigned int i;
 377
 378	for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
 379		const struct mxc_isi_format_info *fmt = &mxc_isi_formats[i];
 380
 381		if (fmt->fourcc == fourcc && fmt->type & type)
 382			return fmt;
 383	}
 384
 385	return NULL;
 386}
 387
 388const struct mxc_isi_format_info *
 389mxc_isi_format_enum(unsigned int index, enum mxc_isi_video_type type)
 390{
 391	unsigned int i;
 392
 393	for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
 394		const struct mxc_isi_format_info *fmt = &mxc_isi_formats[i];
 395
 396		if (!(fmt->type & type))
 397			continue;
 398
 399		if (!index)
 400			return fmt;
 401
 402		index--;
 403	}
 404
 405	return NULL;
 406}
 407
 408const struct mxc_isi_format_info *
 409mxc_isi_format_try(struct mxc_isi_pipe *pipe, struct v4l2_pix_format_mplane *pix,
 410		   enum mxc_isi_video_type type)
 411{
 412	const struct mxc_isi_format_info *fmt;
 413	unsigned int max_width;
 414	unsigned int i;
 415
 416	max_width = pipe->id == pipe->isi->pdata->num_channels - 1
 417		  ? MXC_ISI_MAX_WIDTH_UNCHAINED
 418		  : MXC_ISI_MAX_WIDTH_CHAINED;
 419
 420	fmt = mxc_isi_format_by_fourcc(pix->pixelformat, type);
 421	if (!fmt)
 422		fmt = &mxc_isi_formats[0];
 423
 424	pix->width = clamp(pix->width, MXC_ISI_MIN_WIDTH, max_width);
 425	pix->height = clamp(pix->height, MXC_ISI_MIN_HEIGHT, MXC_ISI_MAX_HEIGHT);
 426	pix->pixelformat = fmt->fourcc;
 427	pix->field = V4L2_FIELD_NONE;
 428
 429	if (pix->colorspace == V4L2_COLORSPACE_DEFAULT) {
 430		pix->colorspace = MXC_ISI_DEF_COLOR_SPACE;
 431		pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC;
 432		pix->quantization = MXC_ISI_DEF_QUANTIZATION;
 433		pix->xfer_func = MXC_ISI_DEF_XFER_FUNC;
 434	}
 435
 436	if (pix->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
 437		pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
 438	if (pix->quantization == V4L2_QUANTIZATION_DEFAULT) {
 439		bool is_rgb = fmt->encoding == MXC_ISI_ENC_RGB;
 440
 441		pix->quantization =
 442			V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, pix->colorspace,
 443						      pix->ycbcr_enc);
 444	}
 445	if (pix->xfer_func == V4L2_XFER_FUNC_DEFAULT)
 446		pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
 447
 448	pix->num_planes = fmt->mem_planes;
 449
 450	for (i = 0; i < fmt->color_planes; ++i) {
 451		struct v4l2_plane_pix_format *plane = &pix->plane_fmt[i];
 452		unsigned int bpl;
 453
 454		/* The pitch must be identical for all planes. */
 455		if (i == 0)
 456			bpl = clamp(plane->bytesperline,
 457				    pix->width * fmt->depth[0] / 8,
 458				    65535U);
 459		else
 460			bpl = pix->plane_fmt[0].bytesperline;
 461
 462		plane->bytesperline = bpl;
 463
 464		plane->sizeimage = plane->bytesperline * pix->height;
 465		if (i >= 1)
 466			plane->sizeimage /= fmt->vsub;
 467	}
 468
 469	/*
 470	 * For single-planar pixel formats with multiple color planes,
 471	 * concatenate the size of all planes and clear all planes but the
 472	 * first one.
 473	 */
 474	if (fmt->color_planes != fmt->mem_planes) {
 475		for (i = 1; i < fmt->color_planes; ++i) {
 476			struct v4l2_plane_pix_format *plane = &pix->plane_fmt[i];
 477
 478			pix->plane_fmt[0].sizeimage += plane->sizeimage;
 479			plane->bytesperline = 0;
 480			plane->sizeimage = 0;
 481		}
 482	}
 483
 484	return fmt;
 485}
 486
 487/* -----------------------------------------------------------------------------
 488 * videobuf2 queue operations
 489 */
 490
 491static void mxc_isi_video_frame_write_done(struct mxc_isi_pipe *pipe,
 492					   u32 status)
 493{
 494	struct mxc_isi_video *video = &pipe->video;
 495	struct device *dev = pipe->isi->dev;
 496	struct mxc_isi_buffer *next_buf;
 497	struct mxc_isi_buffer *buf;
 498	enum mxc_isi_buf_id buf_id;
 499
 500	spin_lock(&video->buf_lock);
 501
 502	/*
 503	 * The ISI hardware handles buffers using a ping-pong mechanism with
 504	 * two sets of destination addresses (with shadow registers to allow
 505	 * programming addresses for all planes atomically) named BUF1 and
 506	 * BUF2. Addresses can be loaded and copied to shadow registers at any
 507	 * at any time.
 508	 *
 509	 * The hardware keeps track of which buffer is being written to and
 510	 * automatically switches to the other buffer at frame end, copying the
 511	 * corresponding address to another set of shadow registers that track
 512	 * the address being written to. The active buffer tracking bits are
 513	 * accessible through the CHNL_STS register.
 514	 *
 515	 *  BUF1        BUF2  |   Event   | Action
 516	 *                    |           |
 517	 *                    |           | Program initial buffers
 518	 *                    |           | B0 in BUF1, B1 in BUF2
 519	 *                    | Start ISI |
 520	 * +----+             |           |
 521	 * | B0 |             |           |
 522	 * +----+             |           |
 523	 *             +----+ | FRM IRQ 0 | B0 complete, BUF2 now active
 524	 *             | B1 | |           | Program B2 in BUF1
 525	 *             +----+ |           |
 526	 * +----+             | FRM IRQ 1 | B1 complete, BUF1 now active
 527	 * | B2 |             |           | Program B3 in BUF2
 528	 * +----+             |           |
 529	 *             +----+ | FRM IRQ 2 | B2 complete, BUF2 now active
 530	 *             | B3 | |           | Program B4 in BUF1
 531	 *             +----+ |           |
 532	 * +----+             | FRM IRQ 3 | B3 complete, BUF1 now active
 533	 * | B4 |             |           | Program B5 in BUF2
 534	 * +----+             |           |
 535	 *        ...         |           |
 536	 *
 537	 * Races between address programming and buffer switching can be
 538	 * detected by checking if a frame end interrupt occurred after
 539	 * programming the addresses.
 540	 *
 541	 * As none of the shadow registers are accessible, races can occur
 542	 * between address programming and buffer switching. It is possible to
 543	 * detect the race condition by checking if a frame end interrupt
 544	 * occurred after programming the addresses, but impossible to
 545	 * determine if the race has been won or lost.
 546	 *
 547	 * In addition to this, we need to use discard buffers if no pending
 548	 * buffers are available. To simplify handling of discard buffer, we
 549	 * need to allocate three of them, as two can be active concurrently
 550	 * and we need to still be able to get hold of a next buffer. The logic
 551	 * could be improved to use two buffers only, but as all discard
 552	 * buffers share the same memory, an additional buffer is cheap.
 553	 */
 554
 555	/* Check which buffer has just completed. */
 556	buf_id = pipe->isi->pdata->buf_active_reverse
 557	       ? (status & CHNL_STS_BUF1_ACTIVE ? MXC_ISI_BUF2 : MXC_ISI_BUF1)
 558	       : (status & CHNL_STS_BUF1_ACTIVE ? MXC_ISI_BUF1 : MXC_ISI_BUF2);
 559
 560	buf = list_first_entry_or_null(&video->out_active,
 561				       struct mxc_isi_buffer, list);
 562
 563	/* Safety check, this should really never happen. */
 564	if (!buf) {
 565		dev_warn(dev, "trying to access empty active list\n");
 566		goto done;
 567	}
 568
 569	/*
 570	 * If the buffer that has completed doesn't match the buffer on the
 571	 * front of the active list, it means we have lost one frame end
 572	 * interrupt (or possibly a large odd number of interrupts, although
 573	 * quite unlikely).
 574	 *
 575	 * For instance, if IRQ1 is lost and we handle IRQ2, both B1 and B2
 576	 * have been completed, but B3 hasn't been programmed, BUF2 still
 577	 * addresses B1 and the ISI is now writing in B1 instead of B3. We
 578	 * can't complete B2 as that would result in out-of-order completion.
 579	 *
 580	 * The only option is to ignore this interrupt and try again. When IRQ3
 581	 * will be handled, we will complete B1 and be in sync again.
 582	 */
 583	if (buf->id != buf_id) {
 584		dev_dbg(dev, "buffer ID mismatch (expected %u, got %u), skipping\n",
 585			buf->id, buf_id);
 586
 587		/*
 588		 * Increment the frame count by two to account for the missed
 589		 * and the ignored interrupts.
 590		 */
 591		video->frame_count += 2;
 592		goto done;
 593	}
 594
 595	/* Pick the next buffer and queue it to the hardware. */
 596	next_buf = list_first_entry_or_null(&video->out_pending,
 597					    struct mxc_isi_buffer, list);
 598	if (!next_buf) {
 599		next_buf = list_first_entry_or_null(&video->out_discard,
 600						    struct mxc_isi_buffer, list);
 601
 602		/* Safety check, this should never happen. */
 603		if (!next_buf) {
 604			dev_warn(dev, "trying to access empty discard list\n");
 605			goto done;
 606		}
 607	}
 608
 609	mxc_isi_channel_set_outbuf(pipe, next_buf->dma_addrs, buf_id);
 610	next_buf->id = buf_id;
 611
 612	/*
 613	 * Check if we have raced with the end of frame interrupt. If so, we
 614	 * can't tell if the ISI has recorded the new address, or is still
 615	 * using the previous buffer. We must assume the latter as that is the
 616	 * worst case.
 617	 *
 618	 * For instance, if we are handling IRQ1 and now detect the FRM
 619	 * interrupt, assume B2 has completed and the ISI has switched to BUF2
 620	 * using B1 just before we programmed B3. Unlike in the previous race
 621	 * condition, B3 has been programmed and will be written to the next
 622	 * time the ISI switches to BUF2. We can however handle this exactly as
 623	 * the first race condition, as we'll program B3 (still at the head of
 624	 * the pending list) when handling IRQ3.
 625	 */
 626	status = mxc_isi_channel_irq_status(pipe, false);
 627	if (status & CHNL_STS_FRM_STRD) {
 628		dev_dbg(dev, "raced with frame end interrupt\n");
 629		video->frame_count += 2;
 630		goto done;
 631	}
 632
 633	/*
 634	 * The next buffer has been queued successfully, move it to the active
 635	 * list, and complete the current buffer.
 636	 */
 637	list_move_tail(&next_buf->list, &video->out_active);
 638
 639	if (!buf->discard) {
 640		list_del_init(&buf->list);
 641		buf->v4l2_buf.sequence = video->frame_count;
 642		buf->v4l2_buf.vb2_buf.timestamp = ktime_get_ns();
 643		vb2_buffer_done(&buf->v4l2_buf.vb2_buf, VB2_BUF_STATE_DONE);
 644	} else {
 645		list_move_tail(&buf->list, &video->out_discard);
 646	}
 647
 648	video->frame_count++;
 649
 650done:
 651	spin_unlock(&video->buf_lock);
 652}
 653
 654static void mxc_isi_video_free_discard_buffers(struct mxc_isi_video *video)
 655{
 656	unsigned int i;
 657
 658	for (i = 0; i < video->pix.num_planes; i++) {
 659		struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i];
 660
 661		if (!buf->addr)
 662			continue;
 663
 664		dma_free_coherent(video->pipe->isi->dev, buf->size, buf->addr,
 665				  buf->dma);
 666		buf->addr = NULL;
 667	}
 668}
 669
 670static int mxc_isi_video_alloc_discard_buffers(struct mxc_isi_video *video)
 671{
 672	unsigned int i, j;
 673
 674	/* Allocate memory for each plane. */
 675	for (i = 0; i < video->pix.num_planes; i++) {
 676		struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i];
 677
 678		buf->size = PAGE_ALIGN(video->pix.plane_fmt[i].sizeimage);
 679		buf->addr = dma_alloc_coherent(video->pipe->isi->dev, buf->size,
 680					       &buf->dma, GFP_DMA | GFP_KERNEL);
 681		if (!buf->addr) {
 682			mxc_isi_video_free_discard_buffers(video);
 683			return -ENOMEM;
 684		}
 685
 686		dev_dbg(video->pipe->isi->dev,
 687			"discard buffer plane %u: %zu bytes @%pad (CPU address %p)\n",
 688			i, buf->size, &buf->dma, buf->addr);
 689	}
 690
 691	/* Fill the DMA addresses in the discard buffers. */
 692	for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) {
 693		struct mxc_isi_buffer *buf = &video->buf_discard[i];
 694
 695		buf->discard = true;
 696
 697		for (j = 0; j < video->pix.num_planes; ++j)
 698			buf->dma_addrs[j] = video->discard_buffer[j].dma;
 699	}
 700
 701	return 0;
 702}
 703
 704static int mxc_isi_video_validate_format(struct mxc_isi_video *video)
 705{
 706	const struct v4l2_mbus_framefmt *format;
 707	const struct mxc_isi_format_info *info;
 708	struct v4l2_subdev_state *state;
 709	struct v4l2_subdev *sd = &video->pipe->sd;
 710	int ret = 0;
 711
 712	state = v4l2_subdev_lock_and_get_active_state(sd);
 713
 714	info = mxc_isi_format_by_fourcc(video->pix.pixelformat,
 715					MXC_ISI_VIDEO_CAP);
 716	format = v4l2_subdev_state_get_format(state, MXC_ISI_PIPE_PAD_SOURCE);
 717
 718	if (format->code != info->mbus_code ||
 719	    format->width != video->pix.width ||
 720	    format->height != video->pix.height) {
 721		dev_dbg(video->pipe->isi->dev,
 722			"%s: configuration mismatch, 0x%04x/%ux%u != 0x%04x/%ux%u\n",
 723			__func__, format->code, format->width, format->height,
 724			info->mbus_code, video->pix.width, video->pix.height);
 725		ret = -EINVAL;
 726	}
 727
 728	v4l2_subdev_unlock_state(state);
 729
 730	return ret;
 731}
 732
 733static void mxc_isi_video_return_buffers(struct mxc_isi_video *video,
 734					 enum vb2_buffer_state state)
 735{
 736	struct mxc_isi_buffer *buf;
 737
 738	spin_lock_irq(&video->buf_lock);
 739
 740	while (!list_empty(&video->out_active)) {
 741		buf = list_first_entry(&video->out_active,
 742				       struct mxc_isi_buffer, list);
 743		list_del_init(&buf->list);
 744		if (buf->discard)
 745			continue;
 746
 747		vb2_buffer_done(&buf->v4l2_buf.vb2_buf, state);
 748	}
 749
 750	while (!list_empty(&video->out_pending)) {
 751		buf = list_first_entry(&video->out_pending,
 752				       struct mxc_isi_buffer, list);
 753		list_del_init(&buf->list);
 754		vb2_buffer_done(&buf->v4l2_buf.vb2_buf, state);
 755	}
 756
 757	while (!list_empty(&video->out_discard)) {
 758		buf = list_first_entry(&video->out_discard,
 759				       struct mxc_isi_buffer, list);
 760		list_del_init(&buf->list);
 761	}
 762
 763	INIT_LIST_HEAD(&video->out_active);
 764	INIT_LIST_HEAD(&video->out_pending);
 765	INIT_LIST_HEAD(&video->out_discard);
 766
 767	spin_unlock_irq(&video->buf_lock);
 768}
 769
 770static void mxc_isi_video_queue_first_buffers(struct mxc_isi_video *video)
 771{
 772	unsigned int discard;
 773	unsigned int i;
 774
 775	lockdep_assert_held(&video->buf_lock);
 776
 777	/*
 778	 * Queue two ISI channel output buffers. We are not guaranteed to have
 779	 * any buffer in the pending list when this function is called from the
 780	 * system resume handler. Use pending buffers as much as possible, and
 781	 * use discard buffers to fill the remaining slots.
 782	 */
 783
 784	/* How many discard buffers do we need to queue first ? */
 785	discard = list_empty(&video->out_pending) ? 2
 786		: list_is_singular(&video->out_pending) ? 1
 787		: 0;
 788
 789	for (i = 0; i < 2; ++i) {
 790		enum mxc_isi_buf_id buf_id = i == 0 ? MXC_ISI_BUF1
 791					   : MXC_ISI_BUF2;
 792		struct mxc_isi_buffer *buf;
 793		struct list_head *list;
 794
 795		list = i < discard ? &video->out_discard : &video->out_pending;
 796		buf = list_first_entry(list, struct mxc_isi_buffer, list);
 797
 798		mxc_isi_channel_set_outbuf(video->pipe, buf->dma_addrs, buf_id);
 799		buf->id = buf_id;
 800		list_move_tail(&buf->list, &video->out_active);
 801	}
 802}
 803
 804static inline struct mxc_isi_buffer *to_isi_buffer(struct vb2_v4l2_buffer *v4l2_buf)
 805{
 806	return container_of(v4l2_buf, struct mxc_isi_buffer, v4l2_buf);
 807}
 808
 809int mxc_isi_video_queue_setup(const struct v4l2_pix_format_mplane *format,
 810			      const struct mxc_isi_format_info *info,
 811			      unsigned int *num_buffers,
 812			      unsigned int *num_planes, unsigned int sizes[])
 813{
 814	unsigned int i;
 815
 816	if (*num_planes) {
 817		if (*num_planes != info->mem_planes)
 818			return -EINVAL;
 819
 820		for (i = 0; i < info->mem_planes; ++i) {
 821			if (sizes[i] < format->plane_fmt[i].sizeimage)
 822				return -EINVAL;
 823		}
 824
 825		return 0;
 826	}
 827
 828	*num_planes = info->mem_planes;
 829
 830	for (i = 0; i < info->mem_planes; ++i)
 831		sizes[i] = format->plane_fmt[i].sizeimage;
 832
 833	return 0;
 834}
 835
 836void mxc_isi_video_buffer_init(struct vb2_buffer *vb2, dma_addr_t dma_addrs[3],
 837			       const struct mxc_isi_format_info *info,
 838			       const struct v4l2_pix_format_mplane *pix)
 839{
 840	unsigned int i;
 841
 842	for (i = 0; i < info->mem_planes; ++i)
 843		dma_addrs[i] = vb2_dma_contig_plane_dma_addr(vb2, i);
 844
 845	/*
 846	 * For single-planar pixel formats with multiple color planes, split
 847	 * the buffer into color planes.
 848	 */
 849	if (info->color_planes != info->mem_planes) {
 850		unsigned int size = pix->plane_fmt[0].bytesperline * pix->height;
 851
 852		for (i = 1; i < info->color_planes; ++i) {
 853			unsigned int vsub = i > 1 ? info->vsub : 1;
 854
 855			dma_addrs[i] = dma_addrs[i - 1] + size / vsub;
 856		}
 857	}
 858}
 859
 860int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2,
 861				 const struct mxc_isi_format_info *info,
 862				 const struct v4l2_pix_format_mplane *pix)
 863{
 864	struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2);
 865	unsigned int i;
 866
 867	for (i = 0; i < info->mem_planes; i++) {
 868		unsigned long size = pix->plane_fmt[i].sizeimage;
 869
 870		if (vb2_plane_size(vb2, i) < size) {
 871			dev_err(isi->dev, "User buffer too small (%ld < %ld)\n",
 872				vb2_plane_size(vb2, i), size);
 873			return -EINVAL;
 874		}
 875
 876		vb2_set_plane_payload(vb2, i, size);
 877	}
 878
 879	v4l2_buf->field = pix->field;
 880
 881	return 0;
 882}
 883
 884static int mxc_isi_vb2_queue_setup(struct vb2_queue *q,
 885				   unsigned int *num_buffers,
 886				   unsigned int *num_planes,
 887				   unsigned int sizes[],
 888				   struct device *alloc_devs[])
 889{
 890	struct mxc_isi_video *video = vb2_get_drv_priv(q);
 891
 892	return mxc_isi_video_queue_setup(&video->pix, video->fmtinfo,
 893					 num_buffers, num_planes, sizes);
 894}
 895
 896static int mxc_isi_vb2_buffer_init(struct vb2_buffer *vb2)
 897{
 898	struct mxc_isi_buffer *buf = to_isi_buffer(to_vb2_v4l2_buffer(vb2));
 899	struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
 900
 901	mxc_isi_video_buffer_init(vb2, buf->dma_addrs, video->fmtinfo,
 902				  &video->pix);
 903
 904	return 0;
 905}
 906
 907static int mxc_isi_vb2_buffer_prepare(struct vb2_buffer *vb2)
 908{
 909	struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
 910
 911	return mxc_isi_video_buffer_prepare(video->pipe->isi, vb2,
 912					    video->fmtinfo, &video->pix);
 913}
 914
 915static void mxc_isi_vb2_buffer_queue(struct vb2_buffer *vb2)
 916{
 917	struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2);
 918	struct mxc_isi_buffer *buf = to_isi_buffer(v4l2_buf);
 919	struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
 920
 921	spin_lock_irq(&video->buf_lock);
 922	list_add_tail(&buf->list, &video->out_pending);
 923	spin_unlock_irq(&video->buf_lock);
 924}
 925
 926static void mxc_isi_video_init_channel(struct mxc_isi_video *video)
 927{
 928	struct mxc_isi_pipe *pipe = video->pipe;
 929
 930	mxc_isi_channel_get(pipe);
 931
 932	mutex_lock(video->ctrls.handler.lock);
 933	mxc_isi_channel_set_alpha(pipe, video->ctrls.alpha);
 934	mxc_isi_channel_set_flip(pipe, video->ctrls.hflip, video->ctrls.vflip);
 935	mutex_unlock(video->ctrls.handler.lock);
 936
 937	mxc_isi_channel_set_output_format(pipe, video->fmtinfo, &video->pix);
 938}
 939
 940static int mxc_isi_vb2_prepare_streaming(struct vb2_queue *q)
 941{
 942	struct mxc_isi_video *video = vb2_get_drv_priv(q);
 943	struct media_device *mdev = &video->pipe->isi->media_dev;
 944	struct media_pipeline *pipe;
 945	int ret;
 946
 947	/* Get a pipeline for the video node and start it. */
 948	scoped_guard(mutex, &mdev->graph_mutex) {
 949		ret = mxc_isi_pipe_acquire(video->pipe,
 950					   &mxc_isi_video_frame_write_done);
 951		if (ret)
 952			return ret;
 953
 954		pipe = media_entity_pipeline(&video->vdev.entity)
 955		     ? : &video->pipe->pipe;
 956
 957		ret = __video_device_pipeline_start(&video->vdev, pipe);
 958		if (ret)
 959			goto err_release;
 960	}
 961
 962	/* Verify that the video format matches the output of the subdev. */
 963	ret = mxc_isi_video_validate_format(video);
 964	if (ret)
 965		goto err_stop;
 966
 967	/* Allocate buffers for discard operation. */
 968	ret = mxc_isi_video_alloc_discard_buffers(video);
 969	if (ret)
 970		goto err_stop;
 971
 972	return 0;
 973
 974err_stop:
 975	video_device_pipeline_stop(&video->vdev);
 976err_release:
 977	mxc_isi_pipe_release(video->pipe);
 978	return ret;
 979}
 980
 981static int mxc_isi_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
 982{
 983	struct mxc_isi_video *video = vb2_get_drv_priv(q);
 984	unsigned int i;
 985	int ret;
 986
 987	/* Initialize the ISI channel. */
 988	mxc_isi_video_init_channel(video);
 989
 990	spin_lock_irq(&video->buf_lock);
 991
 992	/* Add the discard buffers to the out_discard list. */
 993	for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) {
 994		struct mxc_isi_buffer *buf = &video->buf_discard[i];
 995
 996		list_add_tail(&buf->list, &video->out_discard);
 997	}
 998
 999	/* Queue the first buffers. */
1000	mxc_isi_video_queue_first_buffers(video);
1001
1002	/* Clear frame count */
1003	video->frame_count = 0;
1004
1005	spin_unlock_irq(&video->buf_lock);
1006
1007	ret = mxc_isi_pipe_enable(video->pipe);
1008	if (ret)
1009		goto error;
1010
1011	return 0;
1012
1013error:
1014	mxc_isi_channel_put(video->pipe);
1015	mxc_isi_video_return_buffers(video, VB2_BUF_STATE_QUEUED);
1016	return ret;
1017}
1018
1019static void mxc_isi_vb2_stop_streaming(struct vb2_queue *q)
1020{
1021	struct mxc_isi_video *video = vb2_get_drv_priv(q);
1022
1023	mxc_isi_pipe_disable(video->pipe);
1024	mxc_isi_channel_put(video->pipe);
1025
1026	mxc_isi_video_return_buffers(video, VB2_BUF_STATE_ERROR);
1027}
1028
1029static void mxc_isi_vb2_unprepare_streaming(struct vb2_queue *q)
1030{
1031	struct mxc_isi_video *video = vb2_get_drv_priv(q);
1032
1033	mxc_isi_video_free_discard_buffers(video);
1034	video_device_pipeline_stop(&video->vdev);
1035	mxc_isi_pipe_release(video->pipe);
1036}
1037
1038static const struct vb2_ops mxc_isi_vb2_qops = {
1039	.queue_setup		= mxc_isi_vb2_queue_setup,
1040	.buf_init		= mxc_isi_vb2_buffer_init,
1041	.buf_prepare		= mxc_isi_vb2_buffer_prepare,
1042	.buf_queue		= mxc_isi_vb2_buffer_queue,
1043	.prepare_streaming	= mxc_isi_vb2_prepare_streaming,
1044	.start_streaming	= mxc_isi_vb2_start_streaming,
1045	.stop_streaming		= mxc_isi_vb2_stop_streaming,
1046	.unprepare_streaming	= mxc_isi_vb2_unprepare_streaming,
1047};
1048
1049/* -----------------------------------------------------------------------------
1050 * V4L2 controls
1051 */
1052
1053static inline struct mxc_isi_video *ctrl_to_isi_video(struct v4l2_ctrl *ctrl)
1054{
1055	return container_of(ctrl->handler, struct mxc_isi_video, ctrls.handler);
1056}
1057
1058static int mxc_isi_video_s_ctrl(struct v4l2_ctrl *ctrl)
1059{
1060	struct mxc_isi_video *video = ctrl_to_isi_video(ctrl);
1061
1062	switch (ctrl->id) {
1063	case V4L2_CID_ALPHA_COMPONENT:
1064		video->ctrls.alpha = ctrl->val;
1065		break;
1066	case V4L2_CID_VFLIP:
1067		video->ctrls.vflip = ctrl->val;
1068		break;
1069	case V4L2_CID_HFLIP:
1070		video->ctrls.hflip = ctrl->val;
1071		break;
1072	}
1073
1074	return 0;
1075}
1076
1077static const struct v4l2_ctrl_ops mxc_isi_video_ctrl_ops = {
1078	.s_ctrl = mxc_isi_video_s_ctrl,
1079};
1080
1081static int mxc_isi_video_ctrls_create(struct mxc_isi_video *video)
1082{
1083	struct v4l2_ctrl_handler *handler = &video->ctrls.handler;
1084	int ret;
1085
1086	v4l2_ctrl_handler_init(handler, 3);
1087
1088	v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
1089			  V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
1090
1091	v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
1092			  V4L2_CID_VFLIP, 0, 1, 1, 0);
1093
1094	v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
1095			  V4L2_CID_HFLIP, 0, 1, 1, 0);
1096
1097	if (handler->error) {
1098		ret = handler->error;
1099		v4l2_ctrl_handler_free(handler);
1100		return ret;
1101	}
1102
1103	video->vdev.ctrl_handler = handler;
1104
1105	return 0;
1106}
1107
1108static void mxc_isi_video_ctrls_delete(struct mxc_isi_video *video)
1109{
1110	v4l2_ctrl_handler_free(&video->ctrls.handler);
1111}
1112
1113/* -----------------------------------------------------------------------------
1114 * V4L2 ioctls
1115 */
1116
1117static int mxc_isi_video_querycap(struct file *file, void *priv,
1118				  struct v4l2_capability *cap)
1119{
1120	strscpy(cap->driver, MXC_ISI_DRIVER_NAME, sizeof(cap->driver));
1121	strscpy(cap->card, MXC_ISI_CAPTURE, sizeof(cap->card));
1122
1123	return 0;
1124}
1125
1126static int mxc_isi_video_enum_fmt(struct file *file, void *priv,
1127				  struct v4l2_fmtdesc *f)
1128{
1129	const struct mxc_isi_format_info *fmt;
1130	unsigned int index = f->index;
1131	unsigned int i;
1132
1133	if (f->mbus_code) {
1134		/*
1135		 * If a media bus code is specified, only enumerate formats
1136		 * compatible with it.
1137		 */
1138		for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
1139			fmt = &mxc_isi_formats[i];
1140			if (fmt->mbus_code != f->mbus_code)
1141				continue;
1142
1143			if (index == 0)
1144				break;
1145
1146			index--;
1147		}
1148
1149		if (i == ARRAY_SIZE(mxc_isi_formats))
1150			return -EINVAL;
1151	} else {
1152		/* Otherwise, enumerate all formatS. */
1153		if (f->index >= ARRAY_SIZE(mxc_isi_formats))
1154			return -EINVAL;
1155
1156		fmt = &mxc_isi_formats[f->index];
1157	}
1158
1159	f->pixelformat = fmt->fourcc;
1160	f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE | V4L2_FMT_FLAG_CSC_YCBCR_ENC
1161		 |  V4L2_FMT_FLAG_CSC_QUANTIZATION | V4L2_FMT_FLAG_CSC_XFER_FUNC;
1162
1163	return 0;
1164}
1165
1166static int mxc_isi_video_g_fmt(struct file *file, void *fh,
1167			       struct v4l2_format *f)
1168{
1169	struct mxc_isi_video *video = video_drvdata(file);
1170
1171	f->fmt.pix_mp = video->pix;
1172
1173	return 0;
1174}
1175
1176static int mxc_isi_video_try_fmt(struct file *file, void *fh,
1177				 struct v4l2_format *f)
1178{
1179	struct mxc_isi_video *video = video_drvdata(file);
1180
1181	mxc_isi_format_try(video->pipe, &f->fmt.pix_mp, MXC_ISI_VIDEO_CAP);
1182	return 0;
1183}
1184
1185static int mxc_isi_video_s_fmt(struct file *file, void *priv,
1186			       struct v4l2_format *f)
1187{
1188	struct mxc_isi_video *video = video_drvdata(file);
1189	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
1190
1191	if (vb2_is_busy(&video->vb2_q))
1192		return -EBUSY;
1193
1194	video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP);
1195	video->pix = *pix;
1196
1197	return 0;
1198}
1199
1200static int mxc_isi_video_enum_framesizes(struct file *file, void *priv,
1201					 struct v4l2_frmsizeenum *fsize)
1202{
1203	struct mxc_isi_video *video = video_drvdata(file);
1204	const struct mxc_isi_format_info *info;
1205	unsigned int max_width;
1206	unsigned int h_align;
1207	unsigned int v_align;
1208
1209	if (fsize->index)
1210		return -EINVAL;
1211
1212	info = mxc_isi_format_by_fourcc(fsize->pixel_format, MXC_ISI_VIDEO_CAP);
1213	if (!info)
1214		return -EINVAL;
1215
1216	h_align = max_t(unsigned int, info->hsub, 1);
1217	v_align = max_t(unsigned int, info->vsub, 1);
1218
1219	max_width = video->pipe->id == video->pipe->isi->pdata->num_channels - 1
1220		  ? MXC_ISI_MAX_WIDTH_UNCHAINED
1221		  : MXC_ISI_MAX_WIDTH_CHAINED;
1222
1223	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1224	fsize->stepwise.min_width = ALIGN(MXC_ISI_MIN_WIDTH, h_align);
1225	fsize->stepwise.min_height = ALIGN(MXC_ISI_MIN_HEIGHT, v_align);
1226	fsize->stepwise.max_width = ALIGN_DOWN(max_width, h_align);
1227	fsize->stepwise.max_height = ALIGN_DOWN(MXC_ISI_MAX_HEIGHT, v_align);
1228	fsize->stepwise.step_width = h_align;
1229	fsize->stepwise.step_height = v_align;
1230
1231	/*
1232	 * The width can be further restricted due to line buffer sharing
1233	 * between pipelines when scaling, but we have no way to know here if
1234	 * the scaler will be used.
1235	 */
1236
1237	return 0;
1238}
1239
1240static const struct v4l2_ioctl_ops mxc_isi_video_ioctl_ops = {
1241	.vidioc_querycap		= mxc_isi_video_querycap,
1242
1243	.vidioc_enum_fmt_vid_cap	= mxc_isi_video_enum_fmt,
1244	.vidioc_try_fmt_vid_cap_mplane	= mxc_isi_video_try_fmt,
1245	.vidioc_s_fmt_vid_cap_mplane	= mxc_isi_video_s_fmt,
1246	.vidioc_g_fmt_vid_cap_mplane	= mxc_isi_video_g_fmt,
1247
1248	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
1249	.vidioc_querybuf		= vb2_ioctl_querybuf,
1250	.vidioc_qbuf			= vb2_ioctl_qbuf,
1251	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
1252	.vidioc_expbuf			= vb2_ioctl_expbuf,
1253	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
1254	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
1255	.vidioc_streamon		= vb2_ioctl_streamon,
1256	.vidioc_streamoff		= vb2_ioctl_streamoff,
1257
1258	.vidioc_enum_framesizes		= mxc_isi_video_enum_framesizes,
1259
1260	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
1261	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
1262};
1263
1264/* -----------------------------------------------------------------------------
1265 * Video device file operations
1266 */
1267
1268static int mxc_isi_video_open(struct file *file)
1269{
1270	struct mxc_isi_video *video = video_drvdata(file);
1271	int ret;
1272
1273	ret = v4l2_fh_open(file);
1274	if (ret)
1275		return ret;
1276
1277	ret = pm_runtime_resume_and_get(video->pipe->isi->dev);
1278	if (ret) {
1279		v4l2_fh_release(file);
1280		return ret;
1281	}
1282
1283	return 0;
1284}
1285
1286static int mxc_isi_video_release(struct file *file)
1287{
1288	struct mxc_isi_video *video = video_drvdata(file);
1289	int ret;
1290
1291	ret = vb2_fop_release(file);
1292	if (ret)
1293		dev_err(video->pipe->isi->dev, "%s fail\n", __func__);
1294
1295	pm_runtime_put(video->pipe->isi->dev);
1296	return ret;
1297}
1298
1299static const struct v4l2_file_operations mxc_isi_video_fops = {
1300	.owner		= THIS_MODULE,
1301	.open		= mxc_isi_video_open,
1302	.release	= mxc_isi_video_release,
1303	.poll		= vb2_fop_poll,
1304	.unlocked_ioctl	= video_ioctl2,
1305	.mmap		= vb2_fop_mmap,
1306};
1307
1308/* -----------------------------------------------------------------------------
1309 * Suspend & resume
1310 */
1311
1312void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe)
1313{
1314	struct mxc_isi_video *video = &pipe->video;
1315
1316	if (!vb2_is_streaming(&video->vb2_q))
1317		return;
1318
1319	mxc_isi_pipe_disable(pipe);
1320	mxc_isi_channel_put(pipe);
1321
1322	spin_lock_irq(&video->buf_lock);
1323
1324	/*
1325	 * Move the active buffers back to the pending or discard list. We must
1326	 * iterate the active list backward and move the buffers to the head of
1327	 * the pending list to preserve the buffer queueing order.
1328	 */
1329	while (!list_empty(&video->out_active)) {
1330		struct mxc_isi_buffer *buf =
1331			list_last_entry(&video->out_active,
1332					struct mxc_isi_buffer, list);
1333
1334		if (buf->discard)
1335			list_move(&buf->list, &video->out_discard);
1336		else
1337			list_move(&buf->list, &video->out_pending);
1338	}
1339
1340	spin_unlock_irq(&video->buf_lock);
1341}
1342
1343int mxc_isi_video_resume(struct mxc_isi_pipe *pipe)
1344{
1345	struct mxc_isi_video *video = &pipe->video;
1346
1347	if (!vb2_is_streaming(&video->vb2_q))
1348		return 0;
1349
1350	mxc_isi_video_init_channel(video);
1351
1352	spin_lock_irq(&video->buf_lock);
1353	mxc_isi_video_queue_first_buffers(video);
1354	spin_unlock_irq(&video->buf_lock);
1355
1356	return mxc_isi_pipe_enable(pipe);
1357}
1358
1359/* -----------------------------------------------------------------------------
1360 * Registration
1361 */
1362
1363int mxc_isi_video_register(struct mxc_isi_pipe *pipe,
1364			   struct v4l2_device *v4l2_dev)
1365{
1366	struct mxc_isi_video *video = &pipe->video;
1367	struct v4l2_pix_format_mplane *pix = &video->pix;
1368	struct video_device *vdev = &video->vdev;
1369	struct vb2_queue *q = &video->vb2_q;
1370	int ret = -ENOMEM;
1371
1372	video->pipe = pipe;
1373
1374	mutex_init(&video->lock);
1375	spin_lock_init(&video->buf_lock);
1376
1377	pix->width = MXC_ISI_DEF_WIDTH;
1378	pix->height = MXC_ISI_DEF_HEIGHT;
1379	pix->pixelformat = MXC_ISI_DEF_PIXEL_FORMAT;
1380	pix->colorspace = MXC_ISI_DEF_COLOR_SPACE;
1381	pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC;
1382	pix->quantization = MXC_ISI_DEF_QUANTIZATION;
1383	pix->xfer_func = MXC_ISI_DEF_XFER_FUNC;
1384	video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP);
1385
1386	memset(vdev, 0, sizeof(*vdev));
1387	snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.%d.capture", pipe->id);
1388
1389	vdev->fops	= &mxc_isi_video_fops;
1390	vdev->ioctl_ops	= &mxc_isi_video_ioctl_ops;
1391	vdev->v4l2_dev	= v4l2_dev;
1392	vdev->minor	= -1;
1393	vdev->release	= video_device_release_empty;
1394	vdev->queue	= q;
1395	vdev->lock	= &video->lock;
1396
1397	vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE
1398			  | V4L2_CAP_IO_MC;
1399	video_set_drvdata(vdev, video);
1400
1401	INIT_LIST_HEAD(&video->out_pending);
1402	INIT_LIST_HEAD(&video->out_active);
1403	INIT_LIST_HEAD(&video->out_discard);
1404
1405	memset(q, 0, sizeof(*q));
1406	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1407	q->io_modes = VB2_MMAP | VB2_DMABUF;
1408	q->drv_priv = video;
1409	q->ops = &mxc_isi_vb2_qops;
1410	q->mem_ops = &vb2_dma_contig_memops;
1411	q->buf_struct_size = sizeof(struct mxc_isi_buffer);
1412	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1413	q->min_queued_buffers = 2;
1414	q->lock = &video->lock;
1415	q->dev = pipe->isi->dev;
1416
1417	ret = vb2_queue_init(q);
1418	if (ret)
1419		goto err_free_ctx;
1420
1421	video->pad.flags = MEDIA_PAD_FL_SINK;
1422	vdev->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
1423	ret = media_entity_pads_init(&vdev->entity, 1, &video->pad);
1424	if (ret)
1425		goto err_free_ctx;
1426
1427	ret = mxc_isi_video_ctrls_create(video);
1428	if (ret)
1429		goto err_me_cleanup;
1430
1431	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1432	if (ret)
1433		goto err_ctrl_free;
1434
1435	ret = media_create_pad_link(&pipe->sd.entity,
1436				    MXC_ISI_PIPE_PAD_SOURCE,
1437				    &vdev->entity, 0,
1438				    MEDIA_LNK_FL_IMMUTABLE |
1439				    MEDIA_LNK_FL_ENABLED);
1440	if (ret)
1441		goto err_video_unreg;
1442
1443	return 0;
1444
1445err_video_unreg:
1446	video_unregister_device(vdev);
1447err_ctrl_free:
1448	mxc_isi_video_ctrls_delete(video);
1449err_me_cleanup:
1450	media_entity_cleanup(&vdev->entity);
1451err_free_ctx:
1452	return ret;
1453}
1454
1455void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe)
1456{
1457	struct mxc_isi_video *video = &pipe->video;
1458	struct video_device *vdev = &video->vdev;
1459
1460	mutex_lock(&video->lock);
1461
1462	if (video_is_registered(vdev)) {
1463		video_unregister_device(vdev);
1464		mxc_isi_video_ctrls_delete(video);
1465		media_entity_cleanup(&vdev->entity);
1466	}
1467
1468	mutex_unlock(&video->lock);
1469}
~/ Read-only file preview.