1 /*
2  * A virtual v4l2-mem2mem example device.
3  *
4  * This is a virtual device driver for testing mem-to-mem videobuf framework.
5  * It simulates a device that uses memory buffers for both source and
6  * destination, processes the data and issues an "irq" (simulated by a timer).
7  * The device is capable of multi-instance, multi-buffer-per-transaction
8  * operation (via the mem2mem framework).
9  *
10  * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
11  * Pawel Osciak, <pawel@osciak.com>
12  * Marek Szyprowski, <m.szyprowski@samsung.com>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by the
16  * Free Software Foundation; either version 2 of the
17  * License, or (at your option) any later version
18  */
19 #include <linux/module.h>
20 #include <linux/delay.h>
21 #include <linux/fs.h>
22 #include <linux/timer.h>
23 #include <linux/sched.h>
24 #include <linux/slab.h>
25 
26 #include <linux/platform_device.h>
27 #include <media/v4l2-mem2mem.h>
28 #include <media/v4l2-device.h>
29 #include <media/v4l2-ioctl.h>
30 #include <media/v4l2-ctrls.h>
31 #include <media/v4l2-event.h>
32 #include <media/videobuf2-vmalloc.h>
33 
34 MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
35 MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
36 MODULE_LICENSE("GPL");
37 MODULE_VERSION("0.1.1");
38 MODULE_ALIAS("mem2mem_testdev");
39 
40 static unsigned debug;
41 module_param(debug, uint, 0644);
42 MODULE_PARM_DESC(debug, "activates debug info");
43 
44 #define MIN_W 32
45 #define MIN_H 32
46 #define MAX_W 640
47 #define MAX_H 480
48 #define DIM_ALIGN_MASK 7 /* 8-byte alignment for line length */
49 
50 /* Flags that indicate a format can be used for capture/output */
51 #define MEM2MEM_CAPTURE	(1 << 0)
52 #define MEM2MEM_OUTPUT	(1 << 1)
53 
54 #define MEM2MEM_NAME		"vim2m"
55 
56 /* Per queue */
57 #define MEM2MEM_DEF_NUM_BUFS	VIDEO_MAX_FRAME
58 /* In bytes, per queue */
59 #define MEM2MEM_VID_MEM_LIMIT	(16 * 1024 * 1024)
60 
61 /* Default transaction time in msec */
62 #define MEM2MEM_DEF_TRANSTIME	40
63 #define MEM2MEM_COLOR_STEP	(0xff >> 4)
64 #define MEM2MEM_NUM_TILES	8
65 
66 /* Flags that indicate processing mode */
67 #define MEM2MEM_HFLIP	(1 << 0)
68 #define MEM2MEM_VFLIP	(1 << 1)
69 
70 #define dprintk(dev, fmt, arg...) \
71 	v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
72 
73 
vim2m_dev_release(struct device * dev)74 static void vim2m_dev_release(struct device *dev)
75 {}
76 
77 static struct platform_device vim2m_pdev = {
78 	.name		= MEM2MEM_NAME,
79 	.dev.release	= vim2m_dev_release,
80 };
81 
82 struct vim2m_fmt {
83 	u32	fourcc;
84 	int	depth;
85 	/* Types the format can be used for */
86 	u32	types;
87 };
88 
89 static struct vim2m_fmt formats[] = {
90 	{
91 		.fourcc	= V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
92 		.depth	= 16,
93 		/* Both capture and output format */
94 		.types	= MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
95 	},
96 	{
97 		.fourcc	= V4L2_PIX_FMT_YUYV,
98 		.depth	= 16,
99 		/* Output-only format */
100 		.types	= MEM2MEM_OUTPUT,
101 	},
102 };
103 
104 #define NUM_FORMATS ARRAY_SIZE(formats)
105 
106 /* Per-queue, driver-specific private data */
107 struct vim2m_q_data {
108 	unsigned int		width;
109 	unsigned int		height;
110 	unsigned int		sizeimage;
111 	unsigned int		sequence;
112 	struct vim2m_fmt	*fmt;
113 };
114 
115 enum {
116 	V4L2_M2M_SRC = 0,
117 	V4L2_M2M_DST = 1,
118 };
119 
120 #define V4L2_CID_TRANS_TIME_MSEC	(V4L2_CID_USER_BASE + 0x1000)
121 #define V4L2_CID_TRANS_NUM_BUFS		(V4L2_CID_USER_BASE + 0x1001)
122 
find_format(struct v4l2_format * f)123 static struct vim2m_fmt *find_format(struct v4l2_format *f)
124 {
125 	struct vim2m_fmt *fmt;
126 	unsigned int k;
127 
128 	for (k = 0; k < NUM_FORMATS; k++) {
129 		fmt = &formats[k];
130 		if (fmt->fourcc == f->fmt.pix.pixelformat)
131 			break;
132 	}
133 
134 	if (k == NUM_FORMATS)
135 		return NULL;
136 
137 	return &formats[k];
138 }
139 
140 struct vim2m_dev {
141 	struct v4l2_device	v4l2_dev;
142 	struct video_device	vfd;
143 #ifdef CONFIG_MEDIA_CONTROLLER
144 	struct media_device	mdev;
145 #endif
146 
147 	atomic_t		num_inst;
148 	struct mutex		dev_mutex;
149 	spinlock_t		irqlock;
150 
151 	struct timer_list	timer;
152 
153 	struct v4l2_m2m_dev	*m2m_dev;
154 };
155 
156 struct vim2m_ctx {
157 	struct v4l2_fh		fh;
158 	struct vim2m_dev	*dev;
159 
160 	struct v4l2_ctrl_handler hdl;
161 
162 	/* Processed buffers in this transaction */
163 	u8			num_processed;
164 
165 	/* Transaction length (i.e. how many buffers per transaction) */
166 	u32			translen;
167 	/* Transaction time (i.e. simulated processing time) in milliseconds */
168 	u32			transtime;
169 
170 	/* Abort requested by m2m */
171 	int			aborting;
172 
173 	/* Processing mode */
174 	int			mode;
175 
176 	enum v4l2_colorspace	colorspace;
177 	enum v4l2_ycbcr_encoding ycbcr_enc;
178 	enum v4l2_xfer_func	xfer_func;
179 	enum v4l2_quantization	quant;
180 
181 	/* Source and destination queue data */
182 	struct vim2m_q_data   q_data[2];
183 };
184 
file2ctx(struct file * file)185 static inline struct vim2m_ctx *file2ctx(struct file *file)
186 {
187 	return container_of(file->private_data, struct vim2m_ctx, fh);
188 }
189 
get_q_data(struct vim2m_ctx * ctx,enum v4l2_buf_type type)190 static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx,
191 					 enum v4l2_buf_type type)
192 {
193 	switch (type) {
194 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
195 		return &ctx->q_data[V4L2_M2M_SRC];
196 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
197 		return &ctx->q_data[V4L2_M2M_DST];
198 	default:
199 		BUG();
200 	}
201 	return NULL;
202 }
203 
204 
device_process(struct vim2m_ctx * ctx,struct vb2_v4l2_buffer * in_vb,struct vb2_v4l2_buffer * out_vb)205 static int device_process(struct vim2m_ctx *ctx,
206 			  struct vb2_v4l2_buffer *in_vb,
207 			  struct vb2_v4l2_buffer *out_vb)
208 {
209 	struct vim2m_dev *dev = ctx->dev;
210 	struct vim2m_q_data *q_data;
211 	u8 *p_in, *p_out;
212 	int x, y, t, w;
213 	int tile_w, bytes_left;
214 	int width, height, bytesperline;
215 
216 	q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
217 
218 	width	= q_data->width;
219 	height	= q_data->height;
220 	bytesperline	= (q_data->width * q_data->fmt->depth) >> 3;
221 
222 	p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0);
223 	p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0);
224 	if (!p_in || !p_out) {
225 		v4l2_err(&dev->v4l2_dev,
226 			 "Acquiring kernel pointers to buffers failed\n");
227 		return -EFAULT;
228 	}
229 
230 	if (vb2_plane_size(&in_vb->vb2_buf, 0) >
231 			vb2_plane_size(&out_vb->vb2_buf, 0)) {
232 		v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
233 		return -EINVAL;
234 	}
235 
236 	tile_w = (width * (q_data[V4L2_M2M_DST].fmt->depth >> 3))
237 		/ MEM2MEM_NUM_TILES;
238 	bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES;
239 	w = 0;
240 
241 	out_vb->sequence =
242 		get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++;
243 	in_vb->sequence = q_data->sequence++;
244 	out_vb->vb2_buf.timestamp = in_vb->vb2_buf.timestamp;
245 
246 	if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE)
247 		out_vb->timecode = in_vb->timecode;
248 	out_vb->field = in_vb->field;
249 	out_vb->flags = in_vb->flags &
250 		(V4L2_BUF_FLAG_TIMECODE |
251 		 V4L2_BUF_FLAG_KEYFRAME |
252 		 V4L2_BUF_FLAG_PFRAME |
253 		 V4L2_BUF_FLAG_BFRAME |
254 		 V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
255 
256 	switch (ctx->mode) {
257 	case MEM2MEM_HFLIP | MEM2MEM_VFLIP:
258 		p_out += bytesperline * height - bytes_left;
259 		for (y = 0; y < height; ++y) {
260 			for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
261 				if (w & 0x1) {
262 					for (x = 0; x < tile_w; ++x)
263 						*--p_out = *p_in++ +
264 							MEM2MEM_COLOR_STEP;
265 				} else {
266 					for (x = 0; x < tile_w; ++x)
267 						*--p_out = *p_in++ -
268 							MEM2MEM_COLOR_STEP;
269 				}
270 				++w;
271 			}
272 			p_in += bytes_left;
273 			p_out -= bytes_left;
274 		}
275 		break;
276 
277 	case MEM2MEM_HFLIP:
278 		for (y = 0; y < height; ++y) {
279 			p_out += MEM2MEM_NUM_TILES * tile_w;
280 			for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
281 				if (w & 0x01) {
282 					for (x = 0; x < tile_w; ++x)
283 						*--p_out = *p_in++ +
284 							MEM2MEM_COLOR_STEP;
285 				} else {
286 					for (x = 0; x < tile_w; ++x)
287 						*--p_out = *p_in++ -
288 							MEM2MEM_COLOR_STEP;
289 				}
290 				++w;
291 			}
292 			p_in += bytes_left;
293 			p_out += bytesperline;
294 		}
295 		break;
296 
297 	case MEM2MEM_VFLIP:
298 		p_out += bytesperline * (height - 1);
299 		for (y = 0; y < height; ++y) {
300 			for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
301 				if (w & 0x1) {
302 					for (x = 0; x < tile_w; ++x)
303 						*p_out++ = *p_in++ +
304 							MEM2MEM_COLOR_STEP;
305 				} else {
306 					for (x = 0; x < tile_w; ++x)
307 						*p_out++ = *p_in++ -
308 							MEM2MEM_COLOR_STEP;
309 				}
310 				++w;
311 			}
312 			p_in += bytes_left;
313 			p_out += bytes_left - 2 * bytesperline;
314 		}
315 		break;
316 
317 	default:
318 		for (y = 0; y < height; ++y) {
319 			for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
320 				if (w & 0x1) {
321 					for (x = 0; x < tile_w; ++x)
322 						*p_out++ = *p_in++ +
323 							MEM2MEM_COLOR_STEP;
324 				} else {
325 					for (x = 0; x < tile_w; ++x)
326 						*p_out++ = *p_in++ -
327 							MEM2MEM_COLOR_STEP;
328 				}
329 				++w;
330 			}
331 			p_in += bytes_left;
332 			p_out += bytes_left;
333 		}
334 	}
335 
336 	return 0;
337 }
338 
schedule_irq(struct vim2m_dev * dev,int msec_timeout)339 static void schedule_irq(struct vim2m_dev *dev, int msec_timeout)
340 {
341 	dprintk(dev, "Scheduling a simulated irq\n");
342 	mod_timer(&dev->timer, jiffies + msecs_to_jiffies(msec_timeout));
343 }
344 
345 /*
346  * mem2mem callbacks
347  */
348 
349 /*
350  * job_ready() - check whether an instance is ready to be scheduled to run
351  */
job_ready(void * priv)352 static int job_ready(void *priv)
353 {
354 	struct vim2m_ctx *ctx = priv;
355 
356 	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen
357 	    || v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen) {
358 		dprintk(ctx->dev, "Not enough buffers available\n");
359 		return 0;
360 	}
361 
362 	return 1;
363 }
364 
job_abort(void * priv)365 static void job_abort(void *priv)
366 {
367 	struct vim2m_ctx *ctx = priv;
368 
369 	/* Will cancel the transaction in the next interrupt handler */
370 	ctx->aborting = 1;
371 }
372 
373 /* device_run() - prepares and starts the device
374  *
375  * This simulates all the immediate preparations required before starting
376  * a device. This will be called by the framework when it decides to schedule
377  * a particular instance.
378  */
device_run(void * priv)379 static void device_run(void *priv)
380 {
381 	struct vim2m_ctx *ctx = priv;
382 	struct vim2m_dev *dev = ctx->dev;
383 	struct vb2_v4l2_buffer *src_buf, *dst_buf;
384 
385 	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
386 	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
387 
388 	device_process(ctx, src_buf, dst_buf);
389 
390 	/* Run a timer, which simulates a hardware irq  */
391 	schedule_irq(dev, ctx->transtime);
392 }
393 
device_isr(struct timer_list * t)394 static void device_isr(struct timer_list *t)
395 {
396 	struct vim2m_dev *vim2m_dev = from_timer(vim2m_dev, t, timer);
397 	struct vim2m_ctx *curr_ctx;
398 	struct vb2_v4l2_buffer *src_vb, *dst_vb;
399 	unsigned long flags;
400 
401 	curr_ctx = v4l2_m2m_get_curr_priv(vim2m_dev->m2m_dev);
402 
403 	if (NULL == curr_ctx) {
404 		pr_err("Instance released before the end of transaction\n");
405 		return;
406 	}
407 
408 	src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
409 	dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
410 
411 	curr_ctx->num_processed++;
412 
413 	spin_lock_irqsave(&vim2m_dev->irqlock, flags);
414 	v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
415 	v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
416 	spin_unlock_irqrestore(&vim2m_dev->irqlock, flags);
417 
418 	if (curr_ctx->num_processed == curr_ctx->translen
419 	    || curr_ctx->aborting) {
420 		dprintk(curr_ctx->dev, "Finishing transaction\n");
421 		curr_ctx->num_processed = 0;
422 		v4l2_m2m_job_finish(vim2m_dev->m2m_dev, curr_ctx->fh.m2m_ctx);
423 	} else {
424 		device_run(curr_ctx);
425 	}
426 }
427 
428 /*
429  * video ioctls
430  */
vidioc_querycap(struct file * file,void * priv,struct v4l2_capability * cap)431 static int vidioc_querycap(struct file *file, void *priv,
432 			   struct v4l2_capability *cap)
433 {
434 	strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
435 	strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
436 	snprintf(cap->bus_info, sizeof(cap->bus_info),
437 			"platform:%s", MEM2MEM_NAME);
438 	cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
439 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
440 	return 0;
441 }
442 
enum_fmt(struct v4l2_fmtdesc * f,u32 type)443 static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
444 {
445 	int i, num;
446 	struct vim2m_fmt *fmt;
447 
448 	num = 0;
449 
450 	for (i = 0; i < NUM_FORMATS; ++i) {
451 		if (formats[i].types & type) {
452 			/* index-th format of type type found ? */
453 			if (num == f->index)
454 				break;
455 			/* Correct type but haven't reached our index yet,
456 			 * just increment per-type index */
457 			++num;
458 		}
459 	}
460 
461 	if (i < NUM_FORMATS) {
462 		/* Format found */
463 		fmt = &formats[i];
464 		f->pixelformat = fmt->fourcc;
465 		return 0;
466 	}
467 
468 	/* Format not found */
469 	return -EINVAL;
470 }
471 
vidioc_enum_fmt_vid_cap(struct file * file,void * priv,struct v4l2_fmtdesc * f)472 static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
473 				   struct v4l2_fmtdesc *f)
474 {
475 	return enum_fmt(f, MEM2MEM_CAPTURE);
476 }
477 
vidioc_enum_fmt_vid_out(struct file * file,void * priv,struct v4l2_fmtdesc * f)478 static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
479 				   struct v4l2_fmtdesc *f)
480 {
481 	return enum_fmt(f, MEM2MEM_OUTPUT);
482 }
483 
vidioc_g_fmt(struct vim2m_ctx * ctx,struct v4l2_format * f)484 static int vidioc_g_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
485 {
486 	struct vb2_queue *vq;
487 	struct vim2m_q_data *q_data;
488 
489 	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
490 	if (!vq)
491 		return -EINVAL;
492 
493 	q_data = get_q_data(ctx, f->type);
494 
495 	f->fmt.pix.width	= q_data->width;
496 	f->fmt.pix.height	= q_data->height;
497 	f->fmt.pix.field	= V4L2_FIELD_NONE;
498 	f->fmt.pix.pixelformat	= q_data->fmt->fourcc;
499 	f->fmt.pix.bytesperline	= (q_data->width * q_data->fmt->depth) >> 3;
500 	f->fmt.pix.sizeimage	= q_data->sizeimage;
501 	f->fmt.pix.colorspace	= ctx->colorspace;
502 	f->fmt.pix.xfer_func	= ctx->xfer_func;
503 	f->fmt.pix.ycbcr_enc	= ctx->ycbcr_enc;
504 	f->fmt.pix.quantization	= ctx->quant;
505 
506 	return 0;
507 }
508 
vidioc_g_fmt_vid_out(struct file * file,void * priv,struct v4l2_format * f)509 static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
510 				struct v4l2_format *f)
511 {
512 	return vidioc_g_fmt(file2ctx(file), f);
513 }
514 
vidioc_g_fmt_vid_cap(struct file * file,void * priv,struct v4l2_format * f)515 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
516 				struct v4l2_format *f)
517 {
518 	return vidioc_g_fmt(file2ctx(file), f);
519 }
520 
vidioc_try_fmt(struct v4l2_format * f,struct vim2m_fmt * fmt)521 static int vidioc_try_fmt(struct v4l2_format *f, struct vim2m_fmt *fmt)
522 {
523 	/* V4L2 specification suggests the driver corrects the format struct
524 	 * if any of the dimensions is unsupported */
525 	if (f->fmt.pix.height < MIN_H)
526 		f->fmt.pix.height = MIN_H;
527 	else if (f->fmt.pix.height > MAX_H)
528 		f->fmt.pix.height = MAX_H;
529 
530 	if (f->fmt.pix.width < MIN_W)
531 		f->fmt.pix.width = MIN_W;
532 	else if (f->fmt.pix.width > MAX_W)
533 		f->fmt.pix.width = MAX_W;
534 
535 	f->fmt.pix.width &= ~DIM_ALIGN_MASK;
536 	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
537 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
538 	f->fmt.pix.field = V4L2_FIELD_NONE;
539 
540 	return 0;
541 }
542 
vidioc_try_fmt_vid_cap(struct file * file,void * priv,struct v4l2_format * f)543 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
544 				  struct v4l2_format *f)
545 {
546 	struct vim2m_fmt *fmt;
547 	struct vim2m_ctx *ctx = file2ctx(file);
548 
549 	fmt = find_format(f);
550 	if (!fmt) {
551 		f->fmt.pix.pixelformat = formats[0].fourcc;
552 		fmt = find_format(f);
553 	}
554 	if (!(fmt->types & MEM2MEM_CAPTURE)) {
555 		v4l2_err(&ctx->dev->v4l2_dev,
556 			 "Fourcc format (0x%08x) invalid.\n",
557 			 f->fmt.pix.pixelformat);
558 		return -EINVAL;
559 	}
560 	f->fmt.pix.colorspace = ctx->colorspace;
561 	f->fmt.pix.xfer_func = ctx->xfer_func;
562 	f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
563 	f->fmt.pix.quantization = ctx->quant;
564 
565 	return vidioc_try_fmt(f, fmt);
566 }
567 
vidioc_try_fmt_vid_out(struct file * file,void * priv,struct v4l2_format * f)568 static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
569 				  struct v4l2_format *f)
570 {
571 	struct vim2m_fmt *fmt;
572 	struct vim2m_ctx *ctx = file2ctx(file);
573 
574 	fmt = find_format(f);
575 	if (!fmt) {
576 		f->fmt.pix.pixelformat = formats[0].fourcc;
577 		fmt = find_format(f);
578 	}
579 	if (!(fmt->types & MEM2MEM_OUTPUT)) {
580 		v4l2_err(&ctx->dev->v4l2_dev,
581 			 "Fourcc format (0x%08x) invalid.\n",
582 			 f->fmt.pix.pixelformat);
583 		return -EINVAL;
584 	}
585 	if (!f->fmt.pix.colorspace)
586 		f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
587 
588 	return vidioc_try_fmt(f, fmt);
589 }
590 
vidioc_s_fmt(struct vim2m_ctx * ctx,struct v4l2_format * f)591 static int vidioc_s_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
592 {
593 	struct vim2m_q_data *q_data;
594 	struct vb2_queue *vq;
595 
596 	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
597 	if (!vq)
598 		return -EINVAL;
599 
600 	q_data = get_q_data(ctx, f->type);
601 	if (!q_data)
602 		return -EINVAL;
603 
604 	if (vb2_is_busy(vq)) {
605 		v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
606 		return -EBUSY;
607 	}
608 
609 	q_data->fmt		= find_format(f);
610 	q_data->width		= f->fmt.pix.width;
611 	q_data->height		= f->fmt.pix.height;
612 	q_data->sizeimage	= q_data->width * q_data->height
613 				* q_data->fmt->depth >> 3;
614 
615 	dprintk(ctx->dev,
616 		"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
617 		f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
618 
619 	return 0;
620 }
621 
vidioc_s_fmt_vid_cap(struct file * file,void * priv,struct v4l2_format * f)622 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
623 				struct v4l2_format *f)
624 {
625 	int ret;
626 
627 	ret = vidioc_try_fmt_vid_cap(file, priv, f);
628 	if (ret)
629 		return ret;
630 
631 	return vidioc_s_fmt(file2ctx(file), f);
632 }
633 
vidioc_s_fmt_vid_out(struct file * file,void * priv,struct v4l2_format * f)634 static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
635 				struct v4l2_format *f)
636 {
637 	struct vim2m_ctx *ctx = file2ctx(file);
638 	int ret;
639 
640 	ret = vidioc_try_fmt_vid_out(file, priv, f);
641 	if (ret)
642 		return ret;
643 
644 	ret = vidioc_s_fmt(file2ctx(file), f);
645 	if (!ret) {
646 		ctx->colorspace = f->fmt.pix.colorspace;
647 		ctx->xfer_func = f->fmt.pix.xfer_func;
648 		ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
649 		ctx->quant = f->fmt.pix.quantization;
650 	}
651 	return ret;
652 }
653 
vim2m_s_ctrl(struct v4l2_ctrl * ctrl)654 static int vim2m_s_ctrl(struct v4l2_ctrl *ctrl)
655 {
656 	struct vim2m_ctx *ctx =
657 		container_of(ctrl->handler, struct vim2m_ctx, hdl);
658 
659 	switch (ctrl->id) {
660 	case V4L2_CID_HFLIP:
661 		if (ctrl->val)
662 			ctx->mode |= MEM2MEM_HFLIP;
663 		else
664 			ctx->mode &= ~MEM2MEM_HFLIP;
665 		break;
666 
667 	case V4L2_CID_VFLIP:
668 		if (ctrl->val)
669 			ctx->mode |= MEM2MEM_VFLIP;
670 		else
671 			ctx->mode &= ~MEM2MEM_VFLIP;
672 		break;
673 
674 	case V4L2_CID_TRANS_TIME_MSEC:
675 		ctx->transtime = ctrl->val;
676 		break;
677 
678 	case V4L2_CID_TRANS_NUM_BUFS:
679 		ctx->translen = ctrl->val;
680 		break;
681 
682 	default:
683 		v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
684 		return -EINVAL;
685 	}
686 
687 	return 0;
688 }
689 
690 static const struct v4l2_ctrl_ops vim2m_ctrl_ops = {
691 	.s_ctrl = vim2m_s_ctrl,
692 };
693 
694 
695 static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
696 	.vidioc_querycap	= vidioc_querycap,
697 
698 	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
699 	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
700 	.vidioc_try_fmt_vid_cap	= vidioc_try_fmt_vid_cap,
701 	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt_vid_cap,
702 
703 	.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
704 	.vidioc_g_fmt_vid_out	= vidioc_g_fmt_vid_out,
705 	.vidioc_try_fmt_vid_out	= vidioc_try_fmt_vid_out,
706 	.vidioc_s_fmt_vid_out	= vidioc_s_fmt_vid_out,
707 
708 	.vidioc_reqbufs		= v4l2_m2m_ioctl_reqbufs,
709 	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
710 	.vidioc_qbuf		= v4l2_m2m_ioctl_qbuf,
711 	.vidioc_dqbuf		= v4l2_m2m_ioctl_dqbuf,
712 	.vidioc_prepare_buf	= v4l2_m2m_ioctl_prepare_buf,
713 	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
714 	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
715 
716 	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
717 	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
718 
719 	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
720 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
721 };
722 
723 
724 /*
725  * Queue operations
726  */
727 
vim2m_queue_setup(struct vb2_queue * vq,unsigned int * nbuffers,unsigned int * nplanes,unsigned int sizes[],struct device * alloc_devs[])728 static int vim2m_queue_setup(struct vb2_queue *vq,
729 				unsigned int *nbuffers, unsigned int *nplanes,
730 				unsigned int sizes[], struct device *alloc_devs[])
731 {
732 	struct vim2m_ctx *ctx = vb2_get_drv_priv(vq);
733 	struct vim2m_q_data *q_data;
734 	unsigned int size, count = *nbuffers;
735 
736 	q_data = get_q_data(ctx, vq->type);
737 
738 	size = q_data->width * q_data->height * q_data->fmt->depth >> 3;
739 
740 	while (size * count > MEM2MEM_VID_MEM_LIMIT)
741 		(count)--;
742 	*nbuffers = count;
743 
744 	if (*nplanes)
745 		return sizes[0] < size ? -EINVAL : 0;
746 
747 	*nplanes = 1;
748 	sizes[0] = size;
749 
750 	dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
751 
752 	return 0;
753 }
754 
vim2m_buf_prepare(struct vb2_buffer * vb)755 static int vim2m_buf_prepare(struct vb2_buffer *vb)
756 {
757 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
758 	struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
759 	struct vim2m_q_data *q_data;
760 
761 	dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
762 
763 	q_data = get_q_data(ctx, vb->vb2_queue->type);
764 	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
765 		if (vbuf->field == V4L2_FIELD_ANY)
766 			vbuf->field = V4L2_FIELD_NONE;
767 		if (vbuf->field != V4L2_FIELD_NONE) {
768 			dprintk(ctx->dev, "%s field isn't supported\n",
769 					__func__);
770 			return -EINVAL;
771 		}
772 	}
773 
774 	if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
775 		dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n",
776 				__func__, vb2_plane_size(vb, 0), (long)q_data->sizeimage);
777 		return -EINVAL;
778 	}
779 
780 	vb2_set_plane_payload(vb, 0, q_data->sizeimage);
781 
782 	return 0;
783 }
784 
vim2m_buf_queue(struct vb2_buffer * vb)785 static void vim2m_buf_queue(struct vb2_buffer *vb)
786 {
787 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
788 	struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
789 
790 	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
791 }
792 
vim2m_start_streaming(struct vb2_queue * q,unsigned count)793 static int vim2m_start_streaming(struct vb2_queue *q, unsigned count)
794 {
795 	struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
796 	struct vim2m_q_data *q_data = get_q_data(ctx, q->type);
797 
798 	q_data->sequence = 0;
799 	return 0;
800 }
801 
vim2m_stop_streaming(struct vb2_queue * q)802 static void vim2m_stop_streaming(struct vb2_queue *q)
803 {
804 	struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
805 	struct vb2_v4l2_buffer *vbuf;
806 	unsigned long flags;
807 
808 	for (;;) {
809 		if (V4L2_TYPE_IS_OUTPUT(q->type))
810 			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
811 		else
812 			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
813 		if (vbuf == NULL)
814 			return;
815 		spin_lock_irqsave(&ctx->dev->irqlock, flags);
816 		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
817 		spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
818 	}
819 }
820 
821 static const struct vb2_ops vim2m_qops = {
822 	.queue_setup	 = vim2m_queue_setup,
823 	.buf_prepare	 = vim2m_buf_prepare,
824 	.buf_queue	 = vim2m_buf_queue,
825 	.start_streaming = vim2m_start_streaming,
826 	.stop_streaming  = vim2m_stop_streaming,
827 	.wait_prepare	 = vb2_ops_wait_prepare,
828 	.wait_finish	 = vb2_ops_wait_finish,
829 };
830 
queue_init(void * priv,struct vb2_queue * src_vq,struct vb2_queue * dst_vq)831 static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
832 {
833 	struct vim2m_ctx *ctx = priv;
834 	int ret;
835 
836 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
837 	src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
838 	src_vq->drv_priv = ctx;
839 	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
840 	src_vq->ops = &vim2m_qops;
841 	src_vq->mem_ops = &vb2_vmalloc_memops;
842 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
843 	src_vq->lock = &ctx->dev->dev_mutex;
844 
845 	ret = vb2_queue_init(src_vq);
846 	if (ret)
847 		return ret;
848 
849 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
850 	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
851 	dst_vq->drv_priv = ctx;
852 	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
853 	dst_vq->ops = &vim2m_qops;
854 	dst_vq->mem_ops = &vb2_vmalloc_memops;
855 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
856 	dst_vq->lock = &ctx->dev->dev_mutex;
857 
858 	return vb2_queue_init(dst_vq);
859 }
860 
861 static const struct v4l2_ctrl_config vim2m_ctrl_trans_time_msec = {
862 	.ops = &vim2m_ctrl_ops,
863 	.id = V4L2_CID_TRANS_TIME_MSEC,
864 	.name = "Transaction Time (msec)",
865 	.type = V4L2_CTRL_TYPE_INTEGER,
866 	.def = MEM2MEM_DEF_TRANSTIME,
867 	.min = 1,
868 	.max = 10001,
869 	.step = 1,
870 };
871 
872 static const struct v4l2_ctrl_config vim2m_ctrl_trans_num_bufs = {
873 	.ops = &vim2m_ctrl_ops,
874 	.id = V4L2_CID_TRANS_NUM_BUFS,
875 	.name = "Buffers Per Transaction",
876 	.type = V4L2_CTRL_TYPE_INTEGER,
877 	.def = 1,
878 	.min = 1,
879 	.max = MEM2MEM_DEF_NUM_BUFS,
880 	.step = 1,
881 };
882 
883 /*
884  * File operations
885  */
vim2m_open(struct file * file)886 static int vim2m_open(struct file *file)
887 {
888 	struct vim2m_dev *dev = video_drvdata(file);
889 	struct vim2m_ctx *ctx = NULL;
890 	struct v4l2_ctrl_handler *hdl;
891 	int rc = 0;
892 
893 	if (mutex_lock_interruptible(&dev->dev_mutex))
894 		return -ERESTARTSYS;
895 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
896 	if (!ctx) {
897 		rc = -ENOMEM;
898 		goto open_unlock;
899 	}
900 
901 	v4l2_fh_init(&ctx->fh, video_devdata(file));
902 	file->private_data = &ctx->fh;
903 	ctx->dev = dev;
904 	hdl = &ctx->hdl;
905 	v4l2_ctrl_handler_init(hdl, 4);
906 	v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
907 	v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
908 	v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_time_msec, NULL);
909 	v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_num_bufs, NULL);
910 	if (hdl->error) {
911 		rc = hdl->error;
912 		v4l2_ctrl_handler_free(hdl);
913 		kfree(ctx);
914 		goto open_unlock;
915 	}
916 	ctx->fh.ctrl_handler = hdl;
917 	v4l2_ctrl_handler_setup(hdl);
918 
919 	ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
920 	ctx->q_data[V4L2_M2M_SRC].width = 640;
921 	ctx->q_data[V4L2_M2M_SRC].height = 480;
922 	ctx->q_data[V4L2_M2M_SRC].sizeimage =
923 		ctx->q_data[V4L2_M2M_SRC].width *
924 		ctx->q_data[V4L2_M2M_SRC].height *
925 		(ctx->q_data[V4L2_M2M_SRC].fmt->depth >> 3);
926 	ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
927 	ctx->colorspace = V4L2_COLORSPACE_REC709;
928 
929 	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
930 
931 	if (IS_ERR(ctx->fh.m2m_ctx)) {
932 		rc = PTR_ERR(ctx->fh.m2m_ctx);
933 
934 		v4l2_ctrl_handler_free(hdl);
935 		v4l2_fh_exit(&ctx->fh);
936 		kfree(ctx);
937 		goto open_unlock;
938 	}
939 
940 	v4l2_fh_add(&ctx->fh);
941 	atomic_inc(&dev->num_inst);
942 
943 	dprintk(dev, "Created instance: %p, m2m_ctx: %p\n",
944 		ctx, ctx->fh.m2m_ctx);
945 
946 open_unlock:
947 	mutex_unlock(&dev->dev_mutex);
948 	return rc;
949 }
950 
vim2m_release(struct file * file)951 static int vim2m_release(struct file *file)
952 {
953 	struct vim2m_dev *dev = video_drvdata(file);
954 	struct vim2m_ctx *ctx = file2ctx(file);
955 
956 	dprintk(dev, "Releasing instance %p\n", ctx);
957 
958 	v4l2_fh_del(&ctx->fh);
959 	v4l2_fh_exit(&ctx->fh);
960 	v4l2_ctrl_handler_free(&ctx->hdl);
961 	mutex_lock(&dev->dev_mutex);
962 	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
963 	mutex_unlock(&dev->dev_mutex);
964 	kfree(ctx);
965 
966 	atomic_dec(&dev->num_inst);
967 
968 	return 0;
969 }
970 
971 static const struct v4l2_file_operations vim2m_fops = {
972 	.owner		= THIS_MODULE,
973 	.open		= vim2m_open,
974 	.release	= vim2m_release,
975 	.poll		= v4l2_m2m_fop_poll,
976 	.unlocked_ioctl	= video_ioctl2,
977 	.mmap		= v4l2_m2m_fop_mmap,
978 };
979 
980 static const struct video_device vim2m_videodev = {
981 	.name		= MEM2MEM_NAME,
982 	.vfl_dir	= VFL_DIR_M2M,
983 	.fops		= &vim2m_fops,
984 	.ioctl_ops	= &vim2m_ioctl_ops,
985 	.minor		= -1,
986 	.release	= video_device_release_empty,
987 };
988 
989 static const struct v4l2_m2m_ops m2m_ops = {
990 	.device_run	= device_run,
991 	.job_ready	= job_ready,
992 	.job_abort	= job_abort,
993 };
994 
vim2m_probe(struct platform_device * pdev)995 static int vim2m_probe(struct platform_device *pdev)
996 {
997 	struct vim2m_dev *dev;
998 	struct video_device *vfd;
999 	int ret;
1000 
1001 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
1002 	if (!dev)
1003 		return -ENOMEM;
1004 
1005 	spin_lock_init(&dev->irqlock);
1006 
1007 	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
1008 	if (ret)
1009 		return ret;
1010 
1011 	atomic_set(&dev->num_inst, 0);
1012 	mutex_init(&dev->dev_mutex);
1013 
1014 	dev->vfd = vim2m_videodev;
1015 	vfd = &dev->vfd;
1016 	vfd->lock = &dev->dev_mutex;
1017 	vfd->v4l2_dev = &dev->v4l2_dev;
1018 
1019 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
1020 	if (ret) {
1021 		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
1022 		goto unreg_v4l2;
1023 	}
1024 
1025 	video_set_drvdata(vfd, dev);
1026 	v4l2_info(&dev->v4l2_dev,
1027 			"Device registered as /dev/video%d\n", vfd->num);
1028 
1029 	timer_setup(&dev->timer, device_isr, 0);
1030 	platform_set_drvdata(pdev, dev);
1031 
1032 	dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
1033 	if (IS_ERR(dev->m2m_dev)) {
1034 		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
1035 		ret = PTR_ERR(dev->m2m_dev);
1036 		goto unreg_dev;
1037 	}
1038 
1039 #ifdef CONFIG_MEDIA_CONTROLLER
1040 	dev->mdev.dev = &pdev->dev;
1041 	strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
1042 	media_device_init(&dev->mdev);
1043 	dev->v4l2_dev.mdev = &dev->mdev;
1044 
1045 	ret = v4l2_m2m_register_media_controller(dev->m2m_dev,
1046 			vfd, MEDIA_ENT_F_PROC_VIDEO_SCALER);
1047 	if (ret) {
1048 		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
1049 		goto unreg_m2m;
1050 	}
1051 
1052 	ret = media_device_register(&dev->mdev);
1053 	if (ret) {
1054 		v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
1055 		goto unreg_m2m_mc;
1056 	}
1057 #endif
1058 	return 0;
1059 
1060 #ifdef CONFIG_MEDIA_CONTROLLER
1061 unreg_m2m_mc:
1062 	v4l2_m2m_unregister_media_controller(dev->m2m_dev);
1063 unreg_m2m:
1064 	v4l2_m2m_release(dev->m2m_dev);
1065 #endif
1066 unreg_dev:
1067 	video_unregister_device(&dev->vfd);
1068 unreg_v4l2:
1069 	v4l2_device_unregister(&dev->v4l2_dev);
1070 
1071 	return ret;
1072 }
1073 
vim2m_remove(struct platform_device * pdev)1074 static int vim2m_remove(struct platform_device *pdev)
1075 {
1076 	struct vim2m_dev *dev = platform_get_drvdata(pdev);
1077 
1078 	v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
1079 
1080 #ifdef CONFIG_MEDIA_CONTROLLER
1081 	media_device_unregister(&dev->mdev);
1082 	v4l2_m2m_unregister_media_controller(dev->m2m_dev);
1083 	media_device_cleanup(&dev->mdev);
1084 #endif
1085 	v4l2_m2m_release(dev->m2m_dev);
1086 	del_timer_sync(&dev->timer);
1087 	video_unregister_device(&dev->vfd);
1088 	v4l2_device_unregister(&dev->v4l2_dev);
1089 
1090 	return 0;
1091 }
1092 
1093 static struct platform_driver vim2m_pdrv = {
1094 	.probe		= vim2m_probe,
1095 	.remove		= vim2m_remove,
1096 	.driver		= {
1097 		.name	= MEM2MEM_NAME,
1098 	},
1099 };
1100 
vim2m_exit(void)1101 static void __exit vim2m_exit(void)
1102 {
1103 	platform_driver_unregister(&vim2m_pdrv);
1104 	platform_device_unregister(&vim2m_pdev);
1105 }
1106 
vim2m_init(void)1107 static int __init vim2m_init(void)
1108 {
1109 	int ret;
1110 
1111 	ret = platform_device_register(&vim2m_pdev);
1112 	if (ret)
1113 		return ret;
1114 
1115 	ret = platform_driver_register(&vim2m_pdrv);
1116 	if (ret)
1117 		platform_device_unregister(&vim2m_pdev);
1118 
1119 	return ret;
1120 }
1121 
1122 module_init(vim2m_init);
1123 module_exit(vim2m_exit);
1124