xref: /linux/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c (revision 68a052239fc4b351e961f698b824f7654a346091)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * ISI V4L2 memory to memory 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 or memory to memory or DC
7  *
8  * Copyright (c) 2019 NXP Semiconductor
9  */
10 
11 #include <linux/container_of.h>
12 #include <linux/device.h>
13 #include <linux/errno.h>
14 #include <linux/kernel.h>
15 #include <linux/limits.h>
16 #include <linux/minmax.h>
17 #include <linux/mutex.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/slab.h>
20 #include <linux/spinlock.h>
21 #include <linux/string.h>
22 #include <linux/types.h>
23 #include <linux/videodev2.h>
24 
25 #include <media/media-entity.h>
26 #include <media/v4l2-ctrls.h>
27 #include <media/v4l2-device.h>
28 #include <media/v4l2-event.h>
29 #include <media/v4l2-fh.h>
30 #include <media/v4l2-ioctl.h>
31 #include <media/v4l2-mem2mem.h>
32 #include <media/videobuf2-core.h>
33 #include <media/videobuf2-dma-contig.h>
34 
35 #include "imx8-isi-core.h"
36 
37 struct mxc_isi_m2m_buffer {
38 	struct v4l2_m2m_buffer buf;
39 	dma_addr_t dma_addrs[3];
40 };
41 
42 struct mxc_isi_m2m_ctx_queue_data {
43 	struct v4l2_pix_format_mplane format;
44 	const struct mxc_isi_format_info *info;
45 	u32 sequence;
46 };
47 
48 struct mxc_isi_m2m_ctx {
49 	struct v4l2_fh fh;
50 	struct mxc_isi_m2m *m2m;
51 
52 	/* Protects the m2m vb2 queues */
53 	struct mutex vb2_lock;
54 
55 	struct {
56 		struct mxc_isi_m2m_ctx_queue_data out;
57 		struct mxc_isi_m2m_ctx_queue_data cap;
58 	} queues;
59 
60 	struct {
61 		struct v4l2_ctrl_handler handler;
62 		unsigned int alpha;
63 		bool hflip;
64 		bool vflip;
65 	} ctrls;
66 
67 	bool chained;
68 };
69 
70 static inline struct mxc_isi_m2m_buffer *
71 to_isi_m2m_buffer(struct vb2_v4l2_buffer *buf)
72 {
73 	return container_of(buf, struct mxc_isi_m2m_buffer, buf.vb);
74 }
75 
76 static inline struct mxc_isi_m2m_ctx *file_to_isi_m2m_ctx(struct file *filp)
77 {
78 	return container_of(file_to_v4l2_fh(filp), struct mxc_isi_m2m_ctx, fh);
79 }
80 
81 static inline struct mxc_isi_m2m_ctx_queue_data *
82 mxc_isi_m2m_ctx_qdata(struct mxc_isi_m2m_ctx *ctx, enum v4l2_buf_type type)
83 {
84 	if (V4L2_TYPE_IS_OUTPUT(type))
85 		return &ctx->queues.out;
86 	else
87 		return &ctx->queues.cap;
88 }
89 
90 /* -----------------------------------------------------------------------------
91  * V4L2 M2M device operations
92  */
93 
94 static void mxc_isi_m2m_frame_write_done(struct mxc_isi_pipe *pipe, u32 status)
95 {
96 	struct mxc_isi_m2m *m2m = &pipe->isi->m2m;
97 	struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf;
98 	struct mxc_isi_m2m_ctx *ctx;
99 
100 	ctx = v4l2_m2m_get_curr_priv(m2m->m2m_dev);
101 	if (!ctx) {
102 		dev_err(m2m->isi->dev,
103 			"Instance released before the end of transaction\n");
104 		return;
105 	}
106 
107 	src_vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
108 	dst_vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
109 
110 	v4l2_m2m_buf_copy_metadata(src_vbuf, dst_vbuf, false);
111 
112 	src_vbuf->sequence = ctx->queues.out.sequence++;
113 	dst_vbuf->sequence = ctx->queues.cap.sequence++;
114 
115 	v4l2_m2m_buf_done(src_vbuf, VB2_BUF_STATE_DONE);
116 	v4l2_m2m_buf_done(dst_vbuf, VB2_BUF_STATE_DONE);
117 
118 	v4l2_m2m_job_finish(m2m->m2m_dev, ctx->fh.m2m_ctx);
119 }
120 
121 static void mxc_isi_m2m_device_run(void *priv)
122 {
123 	struct mxc_isi_m2m_ctx *ctx = priv;
124 	struct mxc_isi_m2m *m2m = ctx->m2m;
125 	struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf;
126 	struct mxc_isi_m2m_buffer *src_buf, *dst_buf;
127 
128 	mxc_isi_channel_disable(m2m->pipe);
129 
130 	mutex_lock(&m2m->lock);
131 
132 	/* If the context has changed, reconfigure the channel. */
133 	if (m2m->last_ctx != ctx) {
134 		const struct v4l2_area in_size = {
135 			.width = ctx->queues.out.format.width,
136 			.height = ctx->queues.out.format.height,
137 		};
138 		const struct v4l2_area scale = {
139 			.width = ctx->queues.cap.format.width,
140 			.height = ctx->queues.cap.format.height,
141 		};
142 		const struct v4l2_rect crop = {
143 			.width = ctx->queues.cap.format.width,
144 			.height = ctx->queues.cap.format.height,
145 		};
146 
147 		mxc_isi_channel_config(m2m->pipe, MXC_ISI_INPUT_MEM,
148 				       &in_size, &scale, &crop,
149 				       ctx->queues.out.info->encoding,
150 				       ctx->queues.cap.info->encoding);
151 		mxc_isi_channel_set_input_format(m2m->pipe,
152 						 ctx->queues.out.info,
153 						 &ctx->queues.out.format);
154 		mxc_isi_channel_set_output_format(m2m->pipe,
155 						  ctx->queues.cap.info,
156 						  &ctx->queues.cap.format);
157 
158 		m2m->last_ctx = ctx;
159 	}
160 
161 	mutex_unlock(&m2m->lock);
162 
163 	mutex_lock(ctx->ctrls.handler.lock);
164 	mxc_isi_channel_set_alpha(m2m->pipe, ctx->ctrls.alpha);
165 	mxc_isi_channel_set_flip(m2m->pipe, ctx->ctrls.hflip, ctx->ctrls.vflip);
166 	mutex_unlock(ctx->ctrls.handler.lock);
167 
168 	src_vbuf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
169 	dst_vbuf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
170 
171 	src_buf = to_isi_m2m_buffer(src_vbuf);
172 	dst_buf = to_isi_m2m_buffer(dst_vbuf);
173 
174 	mxc_isi_channel_set_inbuf(m2m->pipe, src_buf->dma_addrs[0]);
175 	mxc_isi_channel_set_outbuf(m2m->pipe, dst_buf->dma_addrs, MXC_ISI_BUF1);
176 	mxc_isi_channel_set_outbuf(m2m->pipe, dst_buf->dma_addrs, MXC_ISI_BUF2);
177 
178 	mxc_isi_channel_enable(m2m->pipe);
179 
180 	mxc_isi_channel_m2m_start(m2m->pipe);
181 }
182 
183 static const struct v4l2_m2m_ops mxc_isi_m2m_ops = {
184 	.device_run = mxc_isi_m2m_device_run,
185 };
186 
187 /* -----------------------------------------------------------------------------
188  * videobuf2 queue operations
189  */
190 
191 static int mxc_isi_m2m_vb2_queue_setup(struct vb2_queue *q,
192 				       unsigned int *num_buffers,
193 				       unsigned int *num_planes,
194 				       unsigned int sizes[],
195 				       struct device *alloc_devs[])
196 {
197 	struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q);
198 	const struct mxc_isi_m2m_ctx_queue_data *qdata =
199 		mxc_isi_m2m_ctx_qdata(ctx, q->type);
200 
201 	return mxc_isi_video_queue_setup(&qdata->format, qdata->info,
202 					 num_buffers, num_planes, sizes);
203 }
204 
205 static int mxc_isi_m2m_vb2_buffer_init(struct vb2_buffer *vb2)
206 {
207 	struct vb2_queue *vq = vb2->vb2_queue;
208 	struct mxc_isi_m2m_buffer *buf = to_isi_m2m_buffer(to_vb2_v4l2_buffer(vb2));
209 	struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(vb2->vb2_queue);
210 	const struct mxc_isi_m2m_ctx_queue_data *qdata =
211 		mxc_isi_m2m_ctx_qdata(ctx, vq->type);
212 
213 	mxc_isi_video_buffer_init(vb2, buf->dma_addrs, qdata->info,
214 				  &qdata->format);
215 
216 	return 0;
217 }
218 
219 static int mxc_isi_m2m_vb2_buffer_prepare(struct vb2_buffer *vb2)
220 {
221 	struct vb2_queue *vq = vb2->vb2_queue;
222 	struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(vq);
223 	const struct mxc_isi_m2m_ctx_queue_data *qdata =
224 		mxc_isi_m2m_ctx_qdata(ctx, vq->type);
225 
226 	return mxc_isi_video_buffer_prepare(ctx->m2m->isi, vb2, qdata->info,
227 					    &qdata->format);
228 }
229 
230 static void mxc_isi_m2m_vb2_buffer_queue(struct vb2_buffer *vb2)
231 {
232 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
233 	struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(vb2->vb2_queue);
234 
235 	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
236 }
237 
238 static int mxc_isi_m2m_vb2_prepare_streaming(struct vb2_queue *q)
239 {
240 	struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q);
241 	const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format;
242 	const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format;
243 	const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info;
244 	const struct mxc_isi_format_info *out_info = ctx->queues.out.info;
245 	struct mxc_isi_m2m *m2m = ctx->m2m;
246 	int ret;
247 
248 	guard(mutex)(&m2m->lock);
249 
250 	if (m2m->usage_count == INT_MAX)
251 		return -EOVERFLOW;
252 
253 	ret = pm_runtime_resume_and_get(m2m->isi->dev);
254 	if (ret)
255 		return ret;
256 
257 	/*
258 	 * Acquire the pipe and initialize the channel with the first user of
259 	 * the M2M device.
260 	 */
261 	if (m2m->usage_count == 0) {
262 		bool bypass = cap_pix->width == out_pix->width &&
263 			      cap_pix->height == out_pix->height &&
264 			      cap_info->encoding == out_info->encoding;
265 
266 		ret = mxc_isi_channel_acquire(m2m->pipe,
267 					      &mxc_isi_m2m_frame_write_done,
268 					      bypass);
269 		if (ret)
270 			goto err_pm;
271 
272 		mxc_isi_channel_get(m2m->pipe);
273 	}
274 
275 	m2m->usage_count++;
276 
277 	/*
278 	 * Allocate resources for the channel, counting how many users require
279 	 * buffer chaining.
280 	 */
281 	if (!ctx->chained && out_pix->width > MXC_ISI_MAX_WIDTH_UNCHAINED) {
282 		ret = mxc_isi_channel_chain(m2m->pipe);
283 		if (ret)
284 			goto err_deinit;
285 
286 		m2m->chained_count++;
287 		ctx->chained = true;
288 	}
289 
290 	return 0;
291 
292 err_deinit:
293 	if (--m2m->usage_count == 0) {
294 		mxc_isi_channel_put(m2m->pipe);
295 		mxc_isi_channel_release(m2m->pipe);
296 	}
297 err_pm:
298 	pm_runtime_put(m2m->isi->dev);
299 	return ret;
300 }
301 
302 static int mxc_isi_m2m_vb2_start_streaming(struct vb2_queue *q,
303 					   unsigned int count)
304 {
305 	struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q);
306 	struct mxc_isi_m2m_ctx_queue_data *qdata =
307 		mxc_isi_m2m_ctx_qdata(ctx, q->type);
308 
309 	qdata->sequence = 0;
310 
311 	return 0;
312 }
313 
314 static void mxc_isi_m2m_vb2_stop_streaming(struct vb2_queue *q)
315 {
316 	struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q);
317 	struct vb2_v4l2_buffer *vbuf;
318 
319 	for (;;) {
320 		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
321 			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
322 		else
323 			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
324 		if (!vbuf)
325 			break;
326 
327 		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
328 	}
329 }
330 
331 static void mxc_isi_m2m_vb2_unprepare_streaming(struct vb2_queue *q)
332 {
333 	struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q);
334 	struct mxc_isi_m2m *m2m = ctx->m2m;
335 
336 	guard(mutex)(&m2m->lock);
337 
338 	/*
339 	 * If the last context is this one, reset it to make sure the device
340 	 * will be reconfigured when streaming is restarted.
341 	 */
342 	if (m2m->last_ctx == ctx)
343 		m2m->last_ctx = NULL;
344 
345 	/* Free the channel resources if this is the last chained context. */
346 	if (ctx->chained && --m2m->chained_count == 0)
347 		mxc_isi_channel_unchain(m2m->pipe);
348 	ctx->chained = false;
349 
350 	/* Turn off the light with the last user. */
351 	if (--m2m->usage_count == 0) {
352 		mxc_isi_channel_disable(m2m->pipe);
353 		mxc_isi_channel_put(m2m->pipe);
354 		mxc_isi_channel_release(m2m->pipe);
355 	}
356 
357 	WARN_ON(m2m->usage_count < 0);
358 
359 	pm_runtime_put(m2m->isi->dev);
360 }
361 
362 static const struct vb2_ops mxc_isi_m2m_vb2_qops = {
363 	.queue_setup		= mxc_isi_m2m_vb2_queue_setup,
364 	.buf_init		= mxc_isi_m2m_vb2_buffer_init,
365 	.buf_prepare		= mxc_isi_m2m_vb2_buffer_prepare,
366 	.buf_queue		= mxc_isi_m2m_vb2_buffer_queue,
367 	.prepare_streaming	= mxc_isi_m2m_vb2_prepare_streaming,
368 	.start_streaming	= mxc_isi_m2m_vb2_start_streaming,
369 	.stop_streaming		= mxc_isi_m2m_vb2_stop_streaming,
370 	.unprepare_streaming	= mxc_isi_m2m_vb2_unprepare_streaming,
371 };
372 
373 static int mxc_isi_m2m_queue_init(void *priv, struct vb2_queue *src_vq,
374 				  struct vb2_queue *dst_vq)
375 {
376 	struct mxc_isi_m2m_ctx *ctx = priv;
377 	struct mxc_isi_m2m *m2m = ctx->m2m;
378 	int ret;
379 
380 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
381 	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
382 	src_vq->drv_priv = ctx;
383 	src_vq->buf_struct_size = sizeof(struct mxc_isi_m2m_buffer);
384 	src_vq->ops = &mxc_isi_m2m_vb2_qops;
385 	src_vq->mem_ops = &vb2_dma_contig_memops;
386 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
387 	src_vq->lock = &ctx->vb2_lock;
388 	src_vq->dev = m2m->isi->dev;
389 
390 	ret = vb2_queue_init(src_vq);
391 	if (ret)
392 		return ret;
393 
394 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
395 	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
396 	dst_vq->drv_priv = ctx;
397 	dst_vq->buf_struct_size = sizeof(struct mxc_isi_m2m_buffer);
398 	dst_vq->ops = &mxc_isi_m2m_vb2_qops;
399 	dst_vq->mem_ops = &vb2_dma_contig_memops;
400 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
401 	dst_vq->lock = &ctx->vb2_lock;
402 	dst_vq->dev = m2m->isi->dev;
403 
404 	return vb2_queue_init(dst_vq);
405 }
406 
407 /* -----------------------------------------------------------------------------
408  * V4L2 controls
409  */
410 
411 static inline struct mxc_isi_m2m_ctx *
412 ctrl_to_mxc_isi_m2m_ctx(struct v4l2_ctrl *ctrl)
413 {
414 	return container_of(ctrl->handler, struct mxc_isi_m2m_ctx, ctrls.handler);
415 }
416 
417 static int mxc_isi_m2m_ctx_s_ctrl(struct v4l2_ctrl *ctrl)
418 {
419 	struct mxc_isi_m2m_ctx *ctx = ctrl_to_mxc_isi_m2m_ctx(ctrl);
420 
421 	switch (ctrl->id) {
422 	case V4L2_CID_HFLIP:
423 		ctx->ctrls.hflip = ctrl->val;
424 		break;
425 
426 	case V4L2_CID_VFLIP:
427 		ctx->ctrls.vflip = ctrl->val;
428 		break;
429 
430 	case V4L2_CID_ALPHA_COMPONENT:
431 		ctx->ctrls.alpha = ctrl->val;
432 		break;
433 	}
434 
435 	return 0;
436 }
437 
438 static const struct v4l2_ctrl_ops mxc_isi_m2m_ctx_ctrl_ops = {
439 	.s_ctrl = mxc_isi_m2m_ctx_s_ctrl,
440 };
441 
442 static int mxc_isi_m2m_ctx_ctrls_create(struct mxc_isi_m2m_ctx *ctx)
443 {
444 	struct v4l2_ctrl_handler *handler = &ctx->ctrls.handler;
445 	int ret;
446 
447 	v4l2_ctrl_handler_init(handler, 3);
448 
449 	v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctx_ctrl_ops,
450 			  V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
451 	v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctx_ctrl_ops,
452 			  V4L2_CID_HFLIP, 0, 1, 1, 0);
453 	v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctx_ctrl_ops,
454 			  V4L2_CID_VFLIP, 0, 1, 1, 0);
455 
456 	if (handler->error) {
457 		ret = handler->error;
458 		v4l2_ctrl_handler_free(handler);
459 		return ret;
460 	}
461 
462 	ctx->fh.ctrl_handler = handler;
463 
464 	return 0;
465 }
466 
467 static void mxc_isi_m2m_ctx_ctrls_delete(struct mxc_isi_m2m_ctx *ctx)
468 {
469 	v4l2_ctrl_handler_free(&ctx->ctrls.handler);
470 }
471 
472 /* -----------------------------------------------------------------------------
473  * V4L2 ioctls
474  */
475 
476 static int mxc_isi_m2m_querycap(struct file *file, void *fh,
477 				struct v4l2_capability *cap)
478 {
479 	strscpy(cap->driver, MXC_ISI_DRIVER_NAME, sizeof(cap->driver));
480 	strscpy(cap->card, MXC_ISI_M2M, sizeof(cap->card));
481 	cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
482 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
483 
484 	return 0;
485 }
486 
487 static int mxc_isi_m2m_enum_fmt_vid(struct file *file, void *fh,
488 				    struct v4l2_fmtdesc *f)
489 {
490 	const enum mxc_isi_video_type type =
491 		f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
492 		MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP;
493 	const struct mxc_isi_format_info *info;
494 
495 	info = mxc_isi_format_enum(f->index, type);
496 	if (!info)
497 		return -EINVAL;
498 
499 	f->pixelformat = info->fourcc;
500 	f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE | V4L2_FMT_FLAG_CSC_YCBCR_ENC
501 		 |  V4L2_FMT_FLAG_CSC_QUANTIZATION | V4L2_FMT_FLAG_CSC_XFER_FUNC;
502 
503 	return 0;
504 }
505 
506 static const struct mxc_isi_format_info *
507 __mxc_isi_m2m_try_fmt_vid(struct mxc_isi_m2m_ctx *ctx,
508 			  struct v4l2_pix_format_mplane *pix,
509 			  const enum mxc_isi_video_type type)
510 {
511 	if (type == MXC_ISI_VIDEO_M2M_CAP) {
512 		/* Downscaling only  */
513 		pix->width = min(pix->width, ctx->queues.out.format.width);
514 		pix->height = min(pix->height, ctx->queues.out.format.height);
515 	}
516 
517 	return mxc_isi_format_try(ctx->m2m->pipe, pix, type);
518 }
519 
520 static int mxc_isi_m2m_try_fmt_vid(struct file *file, void *fh,
521 				   struct v4l2_format *f)
522 {
523 	const enum mxc_isi_video_type type =
524 		f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
525 		MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP;
526 	struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file);
527 
528 	__mxc_isi_m2m_try_fmt_vid(ctx, &f->fmt.pix_mp, type);
529 
530 	return 0;
531 }
532 
533 static int mxc_isi_m2m_g_fmt_vid(struct file *file, void *fh,
534 				 struct v4l2_format *f)
535 {
536 	struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file);
537 	const struct mxc_isi_m2m_ctx_queue_data *qdata =
538 		mxc_isi_m2m_ctx_qdata(ctx, f->type);
539 
540 	f->fmt.pix_mp = qdata->format;
541 
542 	return 0;
543 }
544 
545 static int mxc_isi_m2m_s_fmt_vid(struct file *file, void *fh,
546 				 struct v4l2_format *f)
547 {
548 	const enum mxc_isi_video_type type =
549 		f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
550 		MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP;
551 	struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file);
552 	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
553 	const struct mxc_isi_format_info *info;
554 	struct vb2_queue *vq;
555 
556 	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
557 	if (!vq)
558 		return -EINVAL;
559 
560 	if (vb2_is_busy(vq))
561 		return -EBUSY;
562 
563 	info = __mxc_isi_m2m_try_fmt_vid(ctx, pix, type);
564 
565 	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
566 		ctx->queues.out.format = *pix;
567 		ctx->queues.out.info = info;
568 	}
569 
570 	/*
571 	 * Always set the format on the capture side, due to either format
572 	 * propagation or direct setting.
573 	 */
574 	ctx->queues.cap.format = *pix;
575 	ctx->queues.cap.info = info;
576 
577 	return 0;
578 }
579 
580 static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = {
581 	.vidioc_querycap		= mxc_isi_m2m_querycap,
582 
583 	.vidioc_enum_fmt_vid_cap	= mxc_isi_m2m_enum_fmt_vid,
584 	.vidioc_enum_fmt_vid_out	= mxc_isi_m2m_enum_fmt_vid,
585 	.vidioc_g_fmt_vid_cap_mplane	= mxc_isi_m2m_g_fmt_vid,
586 	.vidioc_g_fmt_vid_out_mplane	= mxc_isi_m2m_g_fmt_vid,
587 	.vidioc_s_fmt_vid_cap_mplane	= mxc_isi_m2m_s_fmt_vid,
588 	.vidioc_s_fmt_vid_out_mplane	= mxc_isi_m2m_s_fmt_vid,
589 	.vidioc_try_fmt_vid_cap_mplane	= mxc_isi_m2m_try_fmt_vid,
590 	.vidioc_try_fmt_vid_out_mplane	= mxc_isi_m2m_try_fmt_vid,
591 
592 	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
593 	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
594 	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
595 	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
596 	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
597 	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
598 	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
599 
600 	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
601 	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
602 
603 	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
604 	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
605 };
606 
607 /* -----------------------------------------------------------------------------
608  * Video device file operations
609  */
610 
611 static void mxc_isi_m2m_init_format(struct mxc_isi_m2m_ctx *ctx,
612 				    struct mxc_isi_m2m_ctx_queue_data *qdata,
613 				    enum mxc_isi_video_type type)
614 {
615 	qdata->format.width = MXC_ISI_DEF_WIDTH;
616 	qdata->format.height = MXC_ISI_DEF_HEIGHT;
617 	qdata->format.pixelformat = MXC_ISI_DEF_PIXEL_FORMAT;
618 
619 	qdata->info = mxc_isi_format_try(ctx->m2m->pipe, &qdata->format, type);
620 }
621 
622 static int mxc_isi_m2m_open(struct file *file)
623 {
624 	struct video_device *vdev = video_devdata(file);
625 	struct mxc_isi_m2m *m2m = video_drvdata(file);
626 	struct mxc_isi_m2m_ctx *ctx;
627 	int ret;
628 
629 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
630 	if (!ctx)
631 		return -ENOMEM;
632 
633 	ctx->m2m = m2m;
634 	mutex_init(&ctx->vb2_lock);
635 
636 	v4l2_fh_init(&ctx->fh, vdev);
637 
638 	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(m2m->m2m_dev, ctx,
639 					    &mxc_isi_m2m_queue_init);
640 	if (IS_ERR(ctx->fh.m2m_ctx)) {
641 		ret = PTR_ERR(ctx->fh.m2m_ctx);
642 		ctx->fh.m2m_ctx = NULL;
643 		goto err_fh;
644 	}
645 
646 	mxc_isi_m2m_init_format(ctx, &ctx->queues.out, MXC_ISI_VIDEO_M2M_OUT);
647 	mxc_isi_m2m_init_format(ctx, &ctx->queues.cap, MXC_ISI_VIDEO_M2M_CAP);
648 
649 	ret = mxc_isi_m2m_ctx_ctrls_create(ctx);
650 	if (ret)
651 		goto err_ctx;
652 
653 	v4l2_fh_add(&ctx->fh, file);
654 
655 	return 0;
656 
657 err_ctx:
658 	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
659 err_fh:
660 	v4l2_fh_exit(&ctx->fh);
661 	mutex_destroy(&ctx->vb2_lock);
662 	kfree(ctx);
663 	return ret;
664 }
665 
666 static int mxc_isi_m2m_release(struct file *file)
667 {
668 	struct mxc_isi_m2m_ctx *ctx = file_to_isi_m2m_ctx(file);
669 
670 	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
671 	mxc_isi_m2m_ctx_ctrls_delete(ctx);
672 
673 	v4l2_fh_del(&ctx->fh, file);
674 	v4l2_fh_exit(&ctx->fh);
675 
676 	mutex_destroy(&ctx->vb2_lock);
677 	kfree(ctx);
678 
679 	return 0;
680 }
681 
682 static const struct v4l2_file_operations mxc_isi_m2m_fops = {
683 	.owner		= THIS_MODULE,
684 	.open		= mxc_isi_m2m_open,
685 	.release	= mxc_isi_m2m_release,
686 	.poll		= v4l2_m2m_fop_poll,
687 	.unlocked_ioctl	= video_ioctl2,
688 	.mmap		= v4l2_m2m_fop_mmap,
689 };
690 
691 /* -----------------------------------------------------------------------------
692  * Suspend & resume
693  */
694 
695 void mxc_isi_m2m_suspend(struct mxc_isi_m2m *m2m)
696 {
697 	if (m2m->usage_count == 0)
698 		return;
699 
700 	v4l2_m2m_suspend(m2m->m2m_dev);
701 
702 	if (m2m->chained_count > 0)
703 		mxc_isi_channel_unchain(m2m->pipe);
704 
705 	mxc_isi_channel_disable(m2m->pipe);
706 	mxc_isi_channel_put(m2m->pipe);
707 }
708 
709 int mxc_isi_m2m_resume(struct mxc_isi_m2m *m2m)
710 {
711 	if (m2m->usage_count == 0)
712 		return 0;
713 
714 	mxc_isi_channel_get(m2m->pipe);
715 
716 	if (m2m->chained_count > 0)
717 		mxc_isi_channel_chain(m2m->pipe);
718 
719 	m2m->last_ctx = NULL;
720 	v4l2_m2m_resume(m2m->m2m_dev);
721 
722 	return 0;
723 }
724 
725 /* -----------------------------------------------------------------------------
726  * Registration
727  */
728 
729 int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev)
730 {
731 	struct mxc_isi_m2m *m2m = &isi->m2m;
732 	struct video_device *vdev = &m2m->vdev;
733 	struct media_link *link;
734 	int ret;
735 
736 	m2m->isi = isi;
737 	m2m->pipe = &isi->pipes[0];
738 
739 	mutex_init(&m2m->lock);
740 
741 	/* Initialize the video device and create controls. */
742 	snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.m2m");
743 
744 	vdev->fops	= &mxc_isi_m2m_fops;
745 	vdev->ioctl_ops	= &mxc_isi_m2m_ioctl_ops;
746 	vdev->v4l2_dev	= v4l2_dev;
747 	vdev->minor	= -1;
748 	vdev->release	= video_device_release_empty;
749 	vdev->vfl_dir	= VFL_DIR_M2M;
750 
751 	vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
752 	video_set_drvdata(vdev, m2m);
753 
754 	/* Create the M2M device. */
755 	m2m->m2m_dev = v4l2_m2m_init(&mxc_isi_m2m_ops);
756 	if (IS_ERR(m2m->m2m_dev)) {
757 		dev_err(isi->dev, "failed to initialize m2m device\n");
758 		ret = PTR_ERR(m2m->m2m_dev);
759 		goto err_mutex;
760 	}
761 
762 	/* Register the video device. */
763 	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
764 	if (ret < 0) {
765 		dev_err(isi->dev, "failed to register m2m device\n");
766 		goto err_m2m;
767 	}
768 
769 	/*
770 	 * Populate the media graph. We can't use the mem2mem helper
771 	 * v4l2_m2m_register_media_controller() as the M2M interface needs to
772 	 * be connected to the existing entities in the graph, so we have to
773 	 * wire things up manually:
774 	 *
775 	 * - The entity in the video_device, which isn't touched by the V4L2
776 	 *   core for M2M devices, is used as the source I/O entity in the
777 	 *   graph, connected to the crossbar switch.
778 	 *
779 	 * - The video device at the end of the pipeline provides the sink
780 	 *   entity, and is already wired up in the graph.
781 	 *
782 	 * - A new interface is created, pointing at both entities. The sink
783 	 *   entity will thus have two interfaces pointing to it.
784 	 */
785 	m2m->pad.flags = MEDIA_PAD_FL_SOURCE;
786 	vdev->entity.name = "mxc_isi.output";
787 	vdev->entity.function = MEDIA_ENT_F_IO_V4L;
788 	ret = media_entity_pads_init(&vdev->entity, 1, &m2m->pad);
789 	if (ret)
790 		goto err_video;
791 
792 	ret = media_device_register_entity(v4l2_dev->mdev, &vdev->entity);
793 	if (ret)
794 		goto err_entity_cleanup;
795 
796 	ret = media_create_pad_link(&vdev->entity, 0,
797 				    &m2m->isi->crossbar.sd.entity,
798 				    m2m->isi->crossbar.num_sinks - 1,
799 				    MEDIA_LNK_FL_IMMUTABLE |
800 				    MEDIA_LNK_FL_ENABLED);
801 	if (ret)
802 		goto err_entity_unreg;
803 
804 	m2m->intf = media_devnode_create(v4l2_dev->mdev, MEDIA_INTF_T_V4L_VIDEO,
805 					 0, VIDEO_MAJOR, vdev->minor);
806 	if (!m2m->intf) {
807 		ret = -ENOMEM;
808 		goto err_entity_unreg;
809 	}
810 
811 	link = media_create_intf_link(&vdev->entity, &m2m->intf->intf,
812 				      MEDIA_LNK_FL_IMMUTABLE |
813 				      MEDIA_LNK_FL_ENABLED);
814 	if (!link) {
815 		ret = -ENOMEM;
816 		goto err_devnode;
817 	}
818 
819 	link = media_create_intf_link(&m2m->pipe->video.vdev.entity,
820 				      &m2m->intf->intf,
821 				      MEDIA_LNK_FL_IMMUTABLE |
822 				      MEDIA_LNK_FL_ENABLED);
823 	if (!link) {
824 		ret = -ENOMEM;
825 		goto err_devnode;
826 	}
827 
828 	return 0;
829 
830 err_devnode:
831 	media_devnode_remove(m2m->intf);
832 err_entity_unreg:
833 	media_device_unregister_entity(&vdev->entity);
834 err_entity_cleanup:
835 	media_entity_cleanup(&vdev->entity);
836 err_video:
837 	video_unregister_device(vdev);
838 err_m2m:
839 	v4l2_m2m_release(m2m->m2m_dev);
840 err_mutex:
841 	mutex_destroy(&m2m->lock);
842 	return ret;
843 }
844 
845 int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi)
846 {
847 	struct mxc_isi_m2m *m2m = &isi->m2m;
848 	struct video_device *vdev = &m2m->vdev;
849 
850 	video_unregister_device(vdev);
851 
852 	v4l2_m2m_release(m2m->m2m_dev);
853 	media_devnode_remove(m2m->intf);
854 	media_entity_cleanup(&vdev->entity);
855 	mutex_destroy(&m2m->lock);
856 
857 	return 0;
858 }
859