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