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	unsigned int i;
865
866	for (i = 0; i < info->mem_planes; i++) {
867		unsigned long size = pix->plane_fmt[i].sizeimage;
868
869		if (vb2_plane_size(vb2, i) < size) {
870			dev_err(isi->dev, "User buffer too small (%ld < %ld)\n",
871				vb2_plane_size(vb2, i), size);
872			return -EINVAL;
873		}
874
875		vb2_set_plane_payload(vb2, i, size);
876	}
877
878	return 0;
879}
880
881static int mxc_isi_vb2_queue_setup(struct vb2_queue *q,
882				   unsigned int *num_buffers,
883				   unsigned int *num_planes,
884				   unsigned int sizes[],
885				   struct device *alloc_devs[])
886{
887	struct mxc_isi_video *video = vb2_get_drv_priv(q);
888
889	return mxc_isi_video_queue_setup(&video->pix, video->fmtinfo,
890					 num_buffers, num_planes, sizes);
891}
892
893static int mxc_isi_vb2_buffer_init(struct vb2_buffer *vb2)
894{
895	struct mxc_isi_buffer *buf = to_isi_buffer(to_vb2_v4l2_buffer(vb2));
896	struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
897
898	mxc_isi_video_buffer_init(vb2, buf->dma_addrs, video->fmtinfo,
899				  &video->pix);
900
901	return 0;
902}
903
904static int mxc_isi_vb2_buffer_prepare(struct vb2_buffer *vb2)
905{
906	struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
907
908	return mxc_isi_video_buffer_prepare(video->pipe->isi, vb2,
909					    video->fmtinfo, &video->pix);
910}
911
912static void mxc_isi_vb2_buffer_queue(struct vb2_buffer *vb2)
913{
914	struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2);
915	struct mxc_isi_buffer *buf = to_isi_buffer(v4l2_buf);
916	struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
917
918	spin_lock_irq(&video->buf_lock);
919	list_add_tail(&buf->list, &video->out_pending);
920	spin_unlock_irq(&video->buf_lock);
921}
922
923static void mxc_isi_video_init_channel(struct mxc_isi_video *video)
924{
925	struct mxc_isi_pipe *pipe = video->pipe;
926
927	mxc_isi_channel_get(pipe);
928
929	mutex_lock(video->ctrls.handler.lock);
930	mxc_isi_channel_set_alpha(pipe, video->ctrls.alpha);
931	mxc_isi_channel_set_flip(pipe, video->ctrls.hflip, video->ctrls.vflip);
932	mutex_unlock(video->ctrls.handler.lock);
933
934	mxc_isi_channel_set_output_format(pipe, video->fmtinfo, &video->pix);
935}
936
937static int mxc_isi_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
938{
939	struct mxc_isi_video *video = vb2_get_drv_priv(q);
940	unsigned int i;
941	int ret;
942
943	/* Initialize the ISI channel. */
944	mxc_isi_video_init_channel(video);
945
946	spin_lock_irq(&video->buf_lock);
947
948	/* Add the discard buffers to the out_discard list. */
949	for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) {
950		struct mxc_isi_buffer *buf = &video->buf_discard[i];
951
952		list_add_tail(&buf->list, &video->out_discard);
953	}
954
955	/* Queue the first buffers. */
956	mxc_isi_video_queue_first_buffers(video);
957
958	/* Clear frame count */
959	video->frame_count = 0;
960
961	spin_unlock_irq(&video->buf_lock);
962
963	ret = mxc_isi_pipe_enable(video->pipe);
964	if (ret)
965		goto error;
966
967	return 0;
968
969error:
970	mxc_isi_channel_put(video->pipe);
971	mxc_isi_video_return_buffers(video, VB2_BUF_STATE_QUEUED);
972	return ret;
973}
974
975static void mxc_isi_vb2_stop_streaming(struct vb2_queue *q)
976{
977	struct mxc_isi_video *video = vb2_get_drv_priv(q);
978
979	mxc_isi_pipe_disable(video->pipe);
980	mxc_isi_channel_put(video->pipe);
981
982	mxc_isi_video_return_buffers(video, VB2_BUF_STATE_ERROR);
983}
984
985static const struct vb2_ops mxc_isi_vb2_qops = {
986	.queue_setup		= mxc_isi_vb2_queue_setup,
987	.buf_init		= mxc_isi_vb2_buffer_init,
988	.buf_prepare		= mxc_isi_vb2_buffer_prepare,
989	.buf_queue		= mxc_isi_vb2_buffer_queue,
990	.wait_prepare		= vb2_ops_wait_prepare,
991	.wait_finish		= vb2_ops_wait_finish,
992	.start_streaming	= mxc_isi_vb2_start_streaming,
993	.stop_streaming		= mxc_isi_vb2_stop_streaming,
994};
995
996/* -----------------------------------------------------------------------------
997 * V4L2 controls
998 */
999
1000static inline struct mxc_isi_video *ctrl_to_isi_video(struct v4l2_ctrl *ctrl)
1001{
1002	return container_of(ctrl->handler, struct mxc_isi_video, ctrls.handler);
1003}
1004
1005static int mxc_isi_video_s_ctrl(struct v4l2_ctrl *ctrl)
1006{
1007	struct mxc_isi_video *video = ctrl_to_isi_video(ctrl);
1008
1009	switch (ctrl->id) {
1010	case V4L2_CID_ALPHA_COMPONENT:
1011		video->ctrls.alpha = ctrl->val;
1012		break;
1013	case V4L2_CID_VFLIP:
1014		video->ctrls.vflip = ctrl->val;
1015		break;
1016	case V4L2_CID_HFLIP:
1017		video->ctrls.hflip = ctrl->val;
1018		break;
1019	}
1020
1021	return 0;
1022}
1023
1024static const struct v4l2_ctrl_ops mxc_isi_video_ctrl_ops = {
1025	.s_ctrl = mxc_isi_video_s_ctrl,
1026};
1027
1028static int mxc_isi_video_ctrls_create(struct mxc_isi_video *video)
1029{
1030	struct v4l2_ctrl_handler *handler = &video->ctrls.handler;
1031	int ret;
1032
1033	v4l2_ctrl_handler_init(handler, 3);
1034
1035	v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
1036			  V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
1037
1038	v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
1039			  V4L2_CID_VFLIP, 0, 1, 1, 0);
1040
1041	v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
1042			  V4L2_CID_HFLIP, 0, 1, 1, 0);
1043
1044	if (handler->error) {
1045		ret = handler->error;
1046		v4l2_ctrl_handler_free(handler);
1047		return ret;
1048	}
1049
1050	video->vdev.ctrl_handler = handler;
1051
1052	return 0;
1053}
1054
1055static void mxc_isi_video_ctrls_delete(struct mxc_isi_video *video)
1056{
1057	v4l2_ctrl_handler_free(&video->ctrls.handler);
1058}
1059
1060/* -----------------------------------------------------------------------------
1061 * V4L2 ioctls
1062 */
1063
1064static int mxc_isi_video_querycap(struct file *file, void *priv,
1065				  struct v4l2_capability *cap)
1066{
1067	strscpy(cap->driver, MXC_ISI_DRIVER_NAME, sizeof(cap->driver));
1068	strscpy(cap->card, MXC_ISI_CAPTURE, sizeof(cap->card));
1069
1070	return 0;
1071}
1072
1073static int mxc_isi_video_enum_fmt(struct file *file, void *priv,
1074				  struct v4l2_fmtdesc *f)
1075{
1076	const struct mxc_isi_format_info *fmt;
1077	unsigned int index = f->index;
1078	unsigned int i;
1079
1080	if (f->mbus_code) {
1081		/*
1082		 * If a media bus code is specified, only enumerate formats
1083		 * compatible with it.
1084		 */
1085		for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
1086			fmt = &mxc_isi_formats[i];
1087			if (fmt->mbus_code != f->mbus_code)
1088				continue;
1089
1090			if (index == 0)
1091				break;
1092
1093			index--;
1094		}
1095
1096		if (i == ARRAY_SIZE(mxc_isi_formats))
1097			return -EINVAL;
1098	} else {
1099		/* Otherwise, enumerate all formatS. */
1100		if (f->index >= ARRAY_SIZE(mxc_isi_formats))
1101			return -EINVAL;
1102
1103		fmt = &mxc_isi_formats[f->index];
1104	}
1105
1106	f->pixelformat = fmt->fourcc;
1107	f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE | V4L2_FMT_FLAG_CSC_YCBCR_ENC
1108		 |  V4L2_FMT_FLAG_CSC_QUANTIZATION | V4L2_FMT_FLAG_CSC_XFER_FUNC;
1109
1110	return 0;
1111}
1112
1113static int mxc_isi_video_g_fmt(struct file *file, void *fh,
1114			       struct v4l2_format *f)
1115{
1116	struct mxc_isi_video *video = video_drvdata(file);
1117
1118	f->fmt.pix_mp = video->pix;
1119
1120	return 0;
1121}
1122
1123static int mxc_isi_video_try_fmt(struct file *file, void *fh,
1124				 struct v4l2_format *f)
1125{
1126	struct mxc_isi_video *video = video_drvdata(file);
1127
1128	mxc_isi_format_try(video->pipe, &f->fmt.pix_mp, MXC_ISI_VIDEO_CAP);
1129	return 0;
1130}
1131
1132static int mxc_isi_video_s_fmt(struct file *file, void *priv,
1133			       struct v4l2_format *f)
1134{
1135	struct mxc_isi_video *video = video_drvdata(file);
1136	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
1137
1138	if (vb2_is_busy(&video->vb2_q))
1139		return -EBUSY;
1140
1141	video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP);
1142	video->pix = *pix;
1143
1144	return 0;
1145}
1146
1147static int mxc_isi_video_streamon(struct file *file, void *priv,
1148				  enum v4l2_buf_type type)
1149{
1150	struct mxc_isi_video *video = video_drvdata(file);
1151	struct media_device *mdev = &video->pipe->isi->media_dev;
1152	struct media_pipeline *pipe;
1153	int ret;
1154
1155	if (vb2_queue_is_busy(&video->vb2_q, file))
1156		return -EBUSY;
1157
1158	/*
1159	 * Get a pipeline for the video node and start it. This must be done
1160	 * here and not in the queue .start_streaming() handler, so that
1161	 * pipeline start errors can be reported from VIDIOC_STREAMON and not
1162	 * delayed until subsequent VIDIOC_QBUF calls.
1163	 */
1164	mutex_lock(&mdev->graph_mutex);
1165
1166	ret = mxc_isi_pipe_acquire(video->pipe, &mxc_isi_video_frame_write_done);
1167	if (ret) {
1168		mutex_unlock(&mdev->graph_mutex);
1169		return ret;
1170	}
1171
1172	pipe = media_entity_pipeline(&video->vdev.entity) ? : &video->pipe->pipe;
1173
1174	ret = __video_device_pipeline_start(&video->vdev, pipe);
1175	if (ret) {
1176		mutex_unlock(&mdev->graph_mutex);
1177		goto err_release;
1178	}
1179
1180	mutex_unlock(&mdev->graph_mutex);
1181
1182	/* Verify that the video format matches the output of the subdev. */
1183	ret = mxc_isi_video_validate_format(video);
1184	if (ret)
1185		goto err_stop;
1186
1187	/* Allocate buffers for discard operation. */
1188	ret = mxc_isi_video_alloc_discard_buffers(video);
1189	if (ret)
1190		goto err_stop;
1191
1192	ret = vb2_streamon(&video->vb2_q, type);
1193	if (ret)
1194		goto err_free;
1195
1196	video->is_streaming = true;
1197
1198	return 0;
1199
1200err_free:
1201	mxc_isi_video_free_discard_buffers(video);
1202err_stop:
1203	video_device_pipeline_stop(&video->vdev);
1204err_release:
1205	mxc_isi_pipe_release(video->pipe);
1206	return ret;
1207}
1208
1209static void mxc_isi_video_cleanup_streaming(struct mxc_isi_video *video)
1210{
1211	lockdep_assert_held(&video->lock);
1212
1213	if (!video->is_streaming)
1214		return;
1215
1216	mxc_isi_video_free_discard_buffers(video);
1217	video_device_pipeline_stop(&video->vdev);
1218	mxc_isi_pipe_release(video->pipe);
1219
1220	video->is_streaming = false;
1221}
1222
1223static int mxc_isi_video_streamoff(struct file *file, void *priv,
1224				   enum v4l2_buf_type type)
1225{
1226	struct mxc_isi_video *video = video_drvdata(file);
1227	int ret;
1228
1229	ret = vb2_ioctl_streamoff(file, priv, type);
1230	if (ret)
1231		return ret;
1232
1233	mxc_isi_video_cleanup_streaming(video);
1234
1235	return 0;
1236}
1237
1238static int mxc_isi_video_enum_framesizes(struct file *file, void *priv,
1239					 struct v4l2_frmsizeenum *fsize)
1240{
1241	struct mxc_isi_video *video = video_drvdata(file);
1242	const struct mxc_isi_format_info *info;
1243	unsigned int max_width;
1244	unsigned int h_align;
1245	unsigned int v_align;
1246
1247	if (fsize->index)
1248		return -EINVAL;
1249
1250	info = mxc_isi_format_by_fourcc(fsize->pixel_format, MXC_ISI_VIDEO_CAP);
1251	if (!info)
1252		return -EINVAL;
1253
1254	h_align = max_t(unsigned int, info->hsub, 1);
1255	v_align = max_t(unsigned int, info->vsub, 1);
1256
1257	max_width = video->pipe->id == video->pipe->isi->pdata->num_channels - 1
1258		  ? MXC_ISI_MAX_WIDTH_UNCHAINED
1259		  : MXC_ISI_MAX_WIDTH_CHAINED;
1260
1261	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1262	fsize->stepwise.min_width = ALIGN(MXC_ISI_MIN_WIDTH, h_align);
1263	fsize->stepwise.min_height = ALIGN(MXC_ISI_MIN_HEIGHT, v_align);
1264	fsize->stepwise.max_width = ALIGN_DOWN(max_width, h_align);
1265	fsize->stepwise.max_height = ALIGN_DOWN(MXC_ISI_MAX_HEIGHT, v_align);
1266	fsize->stepwise.step_width = h_align;
1267	fsize->stepwise.step_height = v_align;
1268
1269	/*
1270	 * The width can be further restricted due to line buffer sharing
1271	 * between pipelines when scaling, but we have no way to know here if
1272	 * the scaler will be used.
1273	 */
1274
1275	return 0;
1276}
1277
1278static const struct v4l2_ioctl_ops mxc_isi_video_ioctl_ops = {
1279	.vidioc_querycap		= mxc_isi_video_querycap,
1280
1281	.vidioc_enum_fmt_vid_cap	= mxc_isi_video_enum_fmt,
1282	.vidioc_try_fmt_vid_cap_mplane	= mxc_isi_video_try_fmt,
1283	.vidioc_s_fmt_vid_cap_mplane	= mxc_isi_video_s_fmt,
1284	.vidioc_g_fmt_vid_cap_mplane	= mxc_isi_video_g_fmt,
1285
1286	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
1287	.vidioc_querybuf		= vb2_ioctl_querybuf,
1288	.vidioc_qbuf			= vb2_ioctl_qbuf,
1289	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
1290	.vidioc_expbuf			= vb2_ioctl_expbuf,
1291	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
1292	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
1293
1294	.vidioc_streamon		= mxc_isi_video_streamon,
1295	.vidioc_streamoff		= mxc_isi_video_streamoff,
1296
1297	.vidioc_enum_framesizes		= mxc_isi_video_enum_framesizes,
1298
1299	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
1300	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
1301};
1302
1303/* -----------------------------------------------------------------------------
1304 * Video device file operations
1305 */
1306
1307static int mxc_isi_video_open(struct file *file)
1308{
1309	struct mxc_isi_video *video = video_drvdata(file);
1310	int ret;
1311
1312	ret = v4l2_fh_open(file);
1313	if (ret)
1314		return ret;
1315
1316	ret = pm_runtime_resume_and_get(video->pipe->isi->dev);
1317	if (ret) {
1318		v4l2_fh_release(file);
1319		return ret;
1320	}
1321
1322	return 0;
1323}
1324
1325static int mxc_isi_video_release(struct file *file)
1326{
1327	struct mxc_isi_video *video = video_drvdata(file);
1328	int ret;
1329
1330	ret = vb2_fop_release(file);
1331	if (ret)
1332		dev_err(video->pipe->isi->dev, "%s fail\n", __func__);
1333
1334	mutex_lock(&video->lock);
1335	mxc_isi_video_cleanup_streaming(video);
1336	mutex_unlock(&video->lock);
1337
1338	pm_runtime_put(video->pipe->isi->dev);
1339	return ret;
1340}
1341
1342static const struct v4l2_file_operations mxc_isi_video_fops = {
1343	.owner		= THIS_MODULE,
1344	.open		= mxc_isi_video_open,
1345	.release	= mxc_isi_video_release,
1346	.poll		= vb2_fop_poll,
1347	.unlocked_ioctl	= video_ioctl2,
1348	.mmap		= vb2_fop_mmap,
1349};
1350
1351/* -----------------------------------------------------------------------------
1352 * Suspend & resume
1353 */
1354
1355void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe)
1356{
1357	struct mxc_isi_video *video = &pipe->video;
1358
1359	if (!video->is_streaming)
1360		return;
1361
1362	mxc_isi_pipe_disable(pipe);
1363	mxc_isi_channel_put(pipe);
1364
1365	spin_lock_irq(&video->buf_lock);
1366
1367	/*
1368	 * Move the active buffers back to the pending or discard list. We must
1369	 * iterate the active list backward and move the buffers to the head of
1370	 * the pending list to preserve the buffer queueing order.
1371	 */
1372	while (!list_empty(&video->out_active)) {
1373		struct mxc_isi_buffer *buf =
1374			list_last_entry(&video->out_active,
1375					struct mxc_isi_buffer, list);
1376
1377		if (buf->discard)
1378			list_move(&buf->list, &video->out_discard);
1379		else
1380			list_move(&buf->list, &video->out_pending);
1381	}
1382
1383	spin_unlock_irq(&video->buf_lock);
1384}
1385
1386int mxc_isi_video_resume(struct mxc_isi_pipe *pipe)
1387{
1388	struct mxc_isi_video *video = &pipe->video;
1389
1390	if (!video->is_streaming)
1391		return 0;
1392
1393	mxc_isi_video_init_channel(video);
1394
1395	spin_lock_irq(&video->buf_lock);
1396	mxc_isi_video_queue_first_buffers(video);
1397	spin_unlock_irq(&video->buf_lock);
1398
1399	return mxc_isi_pipe_enable(pipe);
1400}
1401
1402/* -----------------------------------------------------------------------------
1403 * Registration
1404 */
1405
1406int mxc_isi_video_register(struct mxc_isi_pipe *pipe,
1407			   struct v4l2_device *v4l2_dev)
1408{
1409	struct mxc_isi_video *video = &pipe->video;
1410	struct v4l2_pix_format_mplane *pix = &video->pix;
1411	struct video_device *vdev = &video->vdev;
1412	struct vb2_queue *q = &video->vb2_q;
1413	int ret = -ENOMEM;
1414
1415	video->pipe = pipe;
1416
1417	mutex_init(&video->lock);
1418	spin_lock_init(&video->buf_lock);
1419
1420	pix->width = MXC_ISI_DEF_WIDTH;
1421	pix->height = MXC_ISI_DEF_HEIGHT;
1422	pix->pixelformat = MXC_ISI_DEF_PIXEL_FORMAT;
1423	pix->colorspace = MXC_ISI_DEF_COLOR_SPACE;
1424	pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC;
1425	pix->quantization = MXC_ISI_DEF_QUANTIZATION;
1426	pix->xfer_func = MXC_ISI_DEF_XFER_FUNC;
1427	video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP);
1428
1429	memset(vdev, 0, sizeof(*vdev));
1430	snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.%d.capture", pipe->id);
1431
1432	vdev->fops	= &mxc_isi_video_fops;
1433	vdev->ioctl_ops	= &mxc_isi_video_ioctl_ops;
1434	vdev->v4l2_dev	= v4l2_dev;
1435	vdev->minor	= -1;
1436	vdev->release	= video_device_release_empty;
1437	vdev->queue	= q;
1438	vdev->lock	= &video->lock;
1439
1440	vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE
1441			  | V4L2_CAP_IO_MC;
1442	video_set_drvdata(vdev, video);
1443
1444	INIT_LIST_HEAD(&video->out_pending);
1445	INIT_LIST_HEAD(&video->out_active);
1446	INIT_LIST_HEAD(&video->out_discard);
1447
1448	memset(q, 0, sizeof(*q));
1449	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1450	q->io_modes = VB2_MMAP | VB2_DMABUF;
1451	q->drv_priv = video;
1452	q->ops = &mxc_isi_vb2_qops;
1453	q->mem_ops = &vb2_dma_contig_memops;
1454	q->buf_struct_size = sizeof(struct mxc_isi_buffer);
1455	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1456	q->min_queued_buffers = 2;
1457	q->lock = &video->lock;
1458	q->dev = pipe->isi->dev;
1459
1460	ret = vb2_queue_init(q);
1461	if (ret)
1462		goto err_free_ctx;
1463
1464	video->pad.flags = MEDIA_PAD_FL_SINK;
1465	vdev->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
1466	ret = media_entity_pads_init(&vdev->entity, 1, &video->pad);
1467	if (ret)
1468		goto err_free_ctx;
1469
1470	ret = mxc_isi_video_ctrls_create(video);
1471	if (ret)
1472		goto err_me_cleanup;
1473
1474	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1475	if (ret)
1476		goto err_ctrl_free;
1477
1478	ret = media_create_pad_link(&pipe->sd.entity,
1479				    MXC_ISI_PIPE_PAD_SOURCE,
1480				    &vdev->entity, 0,
1481				    MEDIA_LNK_FL_IMMUTABLE |
1482				    MEDIA_LNK_FL_ENABLED);
1483	if (ret)
1484		goto err_video_unreg;
1485
1486	return 0;
1487
1488err_video_unreg:
1489	video_unregister_device(vdev);
1490err_ctrl_free:
1491	mxc_isi_video_ctrls_delete(video);
1492err_me_cleanup:
1493	media_entity_cleanup(&vdev->entity);
1494err_free_ctx:
1495	return ret;
1496}
1497
1498void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe)
1499{
1500	struct mxc_isi_video *video = &pipe->video;
1501	struct video_device *vdev = &video->vdev;
1502
1503	mutex_lock(&video->lock);
1504
1505	if (video_is_registered(vdev)) {
1506		video_unregister_device(vdev);
1507		mxc_isi_video_ctrls_delete(video);
1508		media_entity_cleanup(&vdev->entity);
1509	}
1510
1511	mutex_unlock(&video->lock);
1512}
1513