196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/*
296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * A virtual v4l2-mem2mem example device.
396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak *
496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * This is a virtual device driver for testing mem-to-mem videobuf framework.
596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * It simulates a device that uses memory buffers for both source and
696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * destination, processes the data and issues an "irq" (simulated by a timer).
796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * The device is capable of multi-instance, multi-buffer-per-transaction
896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * operation (via the mem2mem framework).
996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak *
1096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
11950720840f392075b19d902e5ca7806a17a562cbPawel Osciak * Pawel Osciak, <pawel@osciak.com>
1296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * Marek Szyprowski, <m.szyprowski@samsung.com>
1396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak *
1496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * This program is free software; you can redistribute it and/or modify
1596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * it under the terms of the GNU General Public License as published by the
1696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * Free Software Foundation; either version 2 of the
1796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * License, or (at your option) any later version
1896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak */
1996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#include <linux/module.h>
2096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#include <linux/delay.h>
2196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#include <linux/fs.h>
2296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#include <linux/timer.h>
2396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#include <linux/sched.h>
246b46c3977cdb34a199bbca20ef67b1e13335c43dRandy Dunlap#include <linux/slab.h>
2596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
2696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#include <linux/platform_device.h>
2796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#include <media/v4l2-mem2mem.h>
2896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#include <media/v4l2-device.h>
2996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#include <media/v4l2-ioctl.h>
30d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski#include <media/videobuf2-vmalloc.h>
3196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
3296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev"
3396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
3496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel OsciakMODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
35950720840f392075b19d902e5ca7806a17a562cbPawel OsciakMODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
3696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel OsciakMODULE_LICENSE("GPL");
371990d50b58bef127a647005fdcada6d07081d3efMauro Carvalho ChehabMODULE_VERSION("0.1.1");
3896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
3996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MIN_W 32
4096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MIN_H 32
4196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MAX_W 640
4296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MAX_H 480
4396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define DIM_ALIGN_MASK 0x08 /* 8-alignment for dimensions */
4496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
4596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/* Flags that indicate a format can be used for capture/output */
4696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_CAPTURE	(1 << 0)
4796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_OUTPUT	(1 << 1)
4896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
4996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_NAME		"m2m-testdev"
5096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
5196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/* Per queue */
5296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_DEF_NUM_BUFS	VIDEO_MAX_FRAME
5396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/* In bytes, per queue */
5496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_VID_MEM_LIMIT	(16 * 1024 * 1024)
5596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
5696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/* Default transaction time in msec */
5796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_DEF_TRANSTIME	1000
5896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/* Default number of buffers per transaction */
5996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_DEF_TRANSLEN	1
6096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_COLOR_STEP	(0xff >> 4)
6196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define MEM2MEM_NUM_TILES	8
6296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
6396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define dprintk(dev, fmt, arg...) \
6496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
6596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
6696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
6796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakvoid m2mtest_dev_release(struct device *dev)
6896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{}
6996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
7096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct platform_device m2mtest_pdev = {
7196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.name		= MEM2MEM_NAME,
7296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.dev.release	= m2mtest_dev_release,
7396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
7496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
7596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstruct m2mtest_fmt {
7696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	char	*name;
7796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	u32	fourcc;
7896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int	depth;
7996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	/* Types the format can be used for */
8096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	u32	types;
8196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
8296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
8396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct m2mtest_fmt formats[] = {
8496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	{
8596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.name	= "RGB565 (BE)",
8696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.fourcc	= V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
8796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.depth	= 16,
8896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		/* Both capture and output format */
8996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.types	= MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
9096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	},
9196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	{
9296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.name	= "4:2:2, packed, YUYV",
9396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.fourcc	= V4L2_PIX_FMT_YUYV,
9496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.depth	= 16,
9596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		/* Output-only format */
9696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.types	= MEM2MEM_OUTPUT,
9796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	},
9896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
9996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
10096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/* Per-queue, driver-specific private data */
10196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstruct m2mtest_q_data {
10296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	unsigned int		width;
10396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	unsigned int		height;
10496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	unsigned int		sizeimage;
10596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_fmt	*fmt;
10696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
10796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
10896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakenum {
10996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	V4L2_M2M_SRC = 0,
11096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	V4L2_M2M_DST = 1,
11196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
11296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
11396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/* Source and destination queue data */
11496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct m2mtest_q_data q_data[2];
11596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
11696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct m2mtest_q_data *get_q_data(enum v4l2_buf_type type)
11796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
11896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	switch (type) {
11996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
12096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return &q_data[V4L2_M2M_SRC];
12196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
12296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return &q_data[V4L2_M2M_DST];
12396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	default:
12496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		BUG();
12596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
12696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return NULL;
12796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
12896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
12996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define V4L2_CID_TRANS_TIME_MSEC	V4L2_CID_PRIVATE_BASE
13096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define V4L2_CID_TRANS_NUM_BUFS		(V4L2_CID_PRIVATE_BASE + 1)
13196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
13296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct v4l2_queryctrl m2mtest_ctrls[] = {
13396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	{
13496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.id		= V4L2_CID_TRANS_TIME_MSEC,
13596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.type		= V4L2_CTRL_TYPE_INTEGER,
13696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.name		= "Transaction time (msec)",
13796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.minimum	= 1,
13896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.maximum	= 10000,
13996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.step		= 100,
14096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.default_value	= 1000,
14196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.flags		= 0,
14296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}, {
14396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.id		= V4L2_CID_TRANS_NUM_BUFS,
14496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.type		= V4L2_CTRL_TYPE_INTEGER,
14596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.name		= "Buffers per transaction",
14696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.minimum	= 1,
14796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.maximum	= MEM2MEM_DEF_NUM_BUFS,
14896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.step		= 1,
14996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.default_value	= 1,
15096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.flags		= 0,
15196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	},
15296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
15396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
15496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak#define NUM_FORMATS ARRAY_SIZE(formats)
15596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
15696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct m2mtest_fmt *find_format(struct v4l2_format *f)
15796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
15896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_fmt *fmt;
15996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	unsigned int k;
16096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
16196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	for (k = 0; k < NUM_FORMATS; k++) {
16296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		fmt = &formats[k];
16396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		if (fmt->fourcc == f->fmt.pix.pixelformat)
16496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			break;
16596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
16696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
16796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (k == NUM_FORMATS)
16896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return NULL;
16996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
17096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return &formats[k];
17196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
17296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
17396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstruct m2mtest_dev {
17496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct v4l2_device	v4l2_dev;
17596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct video_device	*vfd;
17696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
17796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	atomic_t		num_inst;
17896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct mutex		dev_mutex;
17996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	spinlock_t		irqlock;
18096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
18196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct timer_list	timer;
18296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
18396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct v4l2_m2m_dev	*m2m_dev;
18496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
18596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
18696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstruct m2mtest_ctx {
18796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_dev	*dev;
18896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
18996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	/* Processed buffers in this transaction */
19096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	u8			num_processed;
19196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
19296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	/* Transaction length (i.e. how many buffers per transaction) */
19396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	u32			translen;
19496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	/* Transaction time (i.e. simulated processing time) in milliseconds */
19596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	u32			transtime;
19696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
19796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	/* Abort requested by m2m */
19896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int			aborting;
19996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
20096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct v4l2_m2m_ctx	*m2m_ctx;
20196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
20296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
20396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct v4l2_queryctrl *get_ctrl(int id)
20496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
20596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int i;
20696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
20796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	for (i = 0; i < ARRAY_SIZE(m2mtest_ctrls); ++i) {
20896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		if (id == m2mtest_ctrls[i].id)
20996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			return &m2mtest_ctrls[i];
21096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
21196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
21296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return NULL;
21396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
21496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
21596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int device_process(struct m2mtest_ctx *ctx,
216d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski			  struct vb2_buffer *in_vb,
217d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski			  struct vb2_buffer *out_vb)
21896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
21996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_dev *dev = ctx->dev;
220d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct m2mtest_q_data *q_data;
22196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	u8 *p_in, *p_out;
22296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int x, y, t, w;
22396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int tile_w, bytes_left;
224d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	int width, height, bytesperline;
22596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
226d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
227d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
228d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	width	= q_data->width;
229d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	height	= q_data->height;
230d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	bytesperline	= (q_data->width * q_data->fmt->depth) >> 3;
231d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
232d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	p_in = vb2_plane_vaddr(in_vb, 0);
233d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	p_out = vb2_plane_vaddr(out_vb, 0);
23496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!p_in || !p_out) {
23596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&dev->v4l2_dev,
23696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			 "Acquiring kernel pointers to buffers failed\n");
23796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EFAULT;
23896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
23996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
240d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	if (vb2_plane_size(in_vb, 0) > vb2_plane_size(out_vb, 0)) {
24196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
24296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
24396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
24496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
245d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	tile_w = (width * (q_data[V4L2_M2M_DST].fmt->depth >> 3))
24696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		/ MEM2MEM_NUM_TILES;
247d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES;
24896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	w = 0;
24996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
250d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	for (y = 0; y < height; ++y) {
25196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
25296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			if (w & 0x1) {
25396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				for (x = 0; x < tile_w; ++x)
25496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak					*p_out++ = *p_in++ + MEM2MEM_COLOR_STEP;
25596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			} else {
25696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				for (x = 0; x < tile_w; ++x)
25796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak					*p_out++ = *p_in++ - MEM2MEM_COLOR_STEP;
25896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			}
25996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			++w;
26096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		}
26196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		p_in += bytes_left;
26296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		p_out += bytes_left;
26396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
26496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
26596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
26696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
26796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
26896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic void schedule_irq(struct m2mtest_dev *dev, int msec_timeout)
26996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
27096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	dprintk(dev, "Scheduling a simulated irq\n");
27196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	mod_timer(&dev->timer, jiffies + msecs_to_jiffies(msec_timeout));
27296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
27396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
27496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/*
27596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * mem2mem callbacks
27696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak */
27796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
27896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/**
27996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * job_ready() - check whether an instance is ready to be scheduled to run
28096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak */
28196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int job_ready(void *priv)
28296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
28396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
28496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
28596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < ctx->translen
28696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	    || v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < ctx->translen) {
28796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		dprintk(ctx->dev, "Not enough buffers available\n");
28896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return 0;
28996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
29096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
29196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 1;
29296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
29396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
29496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic void job_abort(void *priv)
29596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
29696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
29796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
29896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	/* Will cancel the transaction in the next interrupt handler */
29996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ctx->aborting = 1;
30096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
30196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
302d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowskistatic void m2mtest_lock(void *priv)
303d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski{
304d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct m2mtest_ctx *ctx = priv;
305d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct m2mtest_dev *dev = ctx->dev;
306d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	mutex_lock(&dev->dev_mutex);
307d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski}
308d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
309d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowskistatic void m2mtest_unlock(void *priv)
310d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski{
311d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct m2mtest_ctx *ctx = priv;
312d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct m2mtest_dev *dev = ctx->dev;
313d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	mutex_unlock(&dev->dev_mutex);
314d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski}
315d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
316d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
31796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/* device_run() - prepares and starts the device
31896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak *
31996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * This simulates all the immediate preparations required before starting
32096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * a device. This will be called by the framework when it decides to schedule
32196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * a particular instance.
32296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak */
32396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic void device_run(void *priv)
32496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
32596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
32696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_dev *dev = ctx->dev;
327d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct vb2_buffer *src_buf, *dst_buf;
32896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
32996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
33096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
33196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
33296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	device_process(ctx, src_buf, dst_buf);
33396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
33496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	/* Run a timer, which simulates a hardware irq  */
33596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	schedule_irq(dev, ctx->transtime);
33696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
33796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
33896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic void device_isr(unsigned long priv)
33996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
34096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_dev *m2mtest_dev = (struct m2mtest_dev *)priv;
34196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *curr_ctx;
342d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct vb2_buffer *src_vb, *dst_vb;
34396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	unsigned long flags;
34496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
34596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev);
34696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
34796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (NULL == curr_ctx) {
34896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		printk(KERN_ERR
34996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			"Instance released before the end of transaction\n");
35096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return;
35196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
35296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
353d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
354d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
355d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
35696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	curr_ctx->num_processed++;
35796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
358d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
359d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
360d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
361d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
362d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
36396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (curr_ctx->num_processed == curr_ctx->translen
36496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	    || curr_ctx->aborting) {
36596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		dprintk(curr_ctx->dev, "Finishing transaction\n");
36696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		curr_ctx->num_processed = 0;
36796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->m2m_ctx);
36896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	} else {
36996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		device_run(curr_ctx);
37096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
37196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
37296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
37396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/*
37496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * video ioctls
37596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak */
37696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_querycap(struct file *file, void *priv,
37796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			   struct v4l2_capability *cap)
37896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
37996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
38096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
38196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	cap->bus_info[0] = 0;
38296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
38396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			  | V4L2_CAP_STREAMING;
38496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
38596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
38696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
38796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
38896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
38996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
39096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int i, num;
39196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_fmt *fmt;
39296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
39396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	num = 0;
39496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
39596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	for (i = 0; i < NUM_FORMATS; ++i) {
39696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		if (formats[i].types & type) {
39796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			/* index-th format of type type found ? */
39896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			if (num == f->index)
39996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				break;
40096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			/* Correct type but haven't reached our index yet,
40196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			 * just increment per-type index */
40296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			++num;
40396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		}
40496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
40596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
40696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (i < NUM_FORMATS) {
40796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		/* Format found */
40896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		fmt = &formats[i];
40996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		strncpy(f->description, fmt->name, sizeof(f->description) - 1);
41096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		f->pixelformat = fmt->fourcc;
41196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return 0;
41296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
41396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
41496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	/* Format not found */
41596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return -EINVAL;
41696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
41796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
41896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
41996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				   struct v4l2_fmtdesc *f)
42096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
42196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return enum_fmt(f, MEM2MEM_CAPTURE);
42296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
42396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
42496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
42596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				   struct v4l2_fmtdesc *f)
42696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
42796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return enum_fmt(f, MEM2MEM_OUTPUT);
42896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
42996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
43096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
43196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
432d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct vb2_queue *vq;
43396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_q_data *q_data;
43496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
43596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
43696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!vq)
43796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
43896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
43996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	q_data = get_q_data(f->type);
44096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
44196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	f->fmt.pix.width	= q_data->width;
44296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	f->fmt.pix.height	= q_data->height;
443d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	f->fmt.pix.field	= V4L2_FIELD_NONE;
44496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	f->fmt.pix.pixelformat	= q_data->fmt->fourcc;
44596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	f->fmt.pix.bytesperline	= (q_data->width * q_data->fmt->depth) >> 3;
44696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	f->fmt.pix.sizeimage	= q_data->sizeimage;
44796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
44896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
44996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
45096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
45196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_g_fmt_vid_out(struct file *file, void *priv,
45296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				struct v4l2_format *f)
45396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
45496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return vidioc_g_fmt(priv, f);
45596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
45696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
45796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
45896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				struct v4l2_format *f)
45996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
46096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return vidioc_g_fmt(priv, f);
46196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
46296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
46396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt)
46496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
46596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	enum v4l2_field field;
46696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
46796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	field = f->fmt.pix.field;
46896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
46996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (field == V4L2_FIELD_ANY)
47096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		field = V4L2_FIELD_NONE;
47196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	else if (V4L2_FIELD_NONE != field)
47296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
47396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
47496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	/* V4L2 specification suggests the driver corrects the format struct
47596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	 * if any of the dimensions is unsupported */
47696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	f->fmt.pix.field = field;
47796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
47896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (f->fmt.pix.height < MIN_H)
47996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		f->fmt.pix.height = MIN_H;
48096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	else if (f->fmt.pix.height > MAX_H)
48196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		f->fmt.pix.height = MAX_H;
48296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
48396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (f->fmt.pix.width < MIN_W)
48496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		f->fmt.pix.width = MIN_W;
48596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	else if (f->fmt.pix.width > MAX_W)
48696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		f->fmt.pix.width = MAX_W;
48796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
48896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	f->fmt.pix.width &= ~DIM_ALIGN_MASK;
48996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
49096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
49196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
49296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
49396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
49496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
49596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
49696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				  struct v4l2_format *f)
49796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
49896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_fmt *fmt;
49996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
50096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
50196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	fmt = find_format(f);
50296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
50396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&ctx->dev->v4l2_dev,
50496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			 "Fourcc format (0x%08x) invalid.\n",
50596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			 f->fmt.pix.pixelformat);
50696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
50796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
50896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
50996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return vidioc_try_fmt(f, fmt);
51096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
51196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
51296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_try_fmt_vid_out(struct file *file, void *priv,
51396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				  struct v4l2_format *f)
51496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
51596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_fmt *fmt;
51696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
51796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
51896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	fmt = find_format(f);
51996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
52096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&ctx->dev->v4l2_dev,
52196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			 "Fourcc format (0x%08x) invalid.\n",
52296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			 f->fmt.pix.pixelformat);
52396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
52496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
52596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
52696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return vidioc_try_fmt(f, fmt);
52796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
52896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
52996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
53096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
53196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_q_data *q_data;
532d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct vb2_queue *vq;
53396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
53496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
53596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!vq)
53696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
53796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
53896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	q_data = get_q_data(f->type);
53996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!q_data)
54096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
54196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
542d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	if (vb2_is_busy(vq)) {
54396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
54407e80305babb27a332ce0f04a3c38ce495cbe711Marek Szyprowski		return -EBUSY;
54596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
54696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
54796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	q_data->fmt		= find_format(f);
54896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	q_data->width		= f->fmt.pix.width;
54996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	q_data->height		= f->fmt.pix.height;
55096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	q_data->sizeimage	= q_data->width * q_data->height
55196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				* q_data->fmt->depth >> 3;
55296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
55396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	dprintk(ctx->dev,
55496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
55596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
55696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
55707e80305babb27a332ce0f04a3c38ce495cbe711Marek Szyprowski	return 0;
55896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
55996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
56096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
56196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				struct v4l2_format *f)
56296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
56396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int ret;
56496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
56596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ret = vidioc_try_fmt_vid_cap(file, priv, f);
56696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (ret)
56796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return ret;
56896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
56996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return vidioc_s_fmt(priv, f);
57096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
57196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
57296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_s_fmt_vid_out(struct file *file, void *priv,
57396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				struct v4l2_format *f)
57496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
57596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int ret;
57696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
57796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ret = vidioc_try_fmt_vid_out(file, priv, f);
57896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (ret)
57996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return ret;
58096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
58196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return vidioc_s_fmt(priv, f);
58296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
58396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
58496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_reqbufs(struct file *file, void *priv,
58596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			  struct v4l2_requestbuffers *reqbufs)
58696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
58796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
58896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
58996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
59096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
59196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
59296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_querybuf(struct file *file, void *priv,
59396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			   struct v4l2_buffer *buf)
59496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
59596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
59696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
59796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
59896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
59996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
60096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
60196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
60296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
60396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
60496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
60596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
60696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
60796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
60896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
60996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
61096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
61196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
61296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
61396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
61496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_streamon(struct file *file, void *priv,
61596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			   enum v4l2_buf_type type)
61696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
61796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
61896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
61996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
62096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
62196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
62296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_streamoff(struct file *file, void *priv,
62396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			    enum v4l2_buf_type type)
62496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
62596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
62696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
62796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
62896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
62996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
63096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_queryctrl(struct file *file, void *priv,
63196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			    struct v4l2_queryctrl *qc)
63296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
63396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct v4l2_queryctrl *c;
63496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
63596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	c = get_ctrl(qc->id);
63696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!c)
63796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
63896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
63996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	*qc = *c;
64096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
64196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
64296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
64396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_g_ctrl(struct file *file, void *priv,
64496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			 struct v4l2_control *ctrl)
64596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
64696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
64796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
64896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	switch (ctrl->id) {
64996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	case V4L2_CID_TRANS_TIME_MSEC:
65096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		ctrl->value = ctx->transtime;
65196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		break;
65296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
65396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	case V4L2_CID_TRANS_NUM_BUFS:
65496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		ctrl->value = ctx->translen;
65596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		break;
65696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
65796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	default:
65896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
65996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
66096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
66196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
66296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
66396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
66496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
66596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int check_ctrl_val(struct m2mtest_ctx *ctx, struct v4l2_control *ctrl)
66696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
66796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct v4l2_queryctrl *c;
66896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
66996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	c = get_ctrl(ctrl->id);
67096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!c)
67196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
67296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
67396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (ctrl->value < c->minimum || ctrl->value > c->maximum) {
67496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&ctx->dev->v4l2_dev, "Value out of range\n");
67596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -ERANGE;
67696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
67796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
67896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
67996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
68096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
68196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int vidioc_s_ctrl(struct file *file, void *priv,
68296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			 struct v4l2_control *ctrl)
68396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
68496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
68596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int ret = 0;
68696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
68796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ret = check_ctrl_val(ctx, ctrl);
68896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (ret != 0)
68996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return ret;
69096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
69196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	switch (ctrl->id) {
69296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	case V4L2_CID_TRANS_TIME_MSEC:
69396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		ctx->transtime = ctrl->value;
69496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		break;
69596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
69696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	case V4L2_CID_TRANS_NUM_BUFS:
69796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		ctx->translen = ctrl->value;
69896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		break;
69996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
70096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	default:
70196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
70296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
70396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
70496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
70596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
70696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
70796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
70896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
70996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {
71096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_querycap	= vidioc_querycap,
71196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
71296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
71396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
71496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_try_fmt_vid_cap	= vidioc_try_fmt_vid_cap,
71596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt_vid_cap,
71696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
71796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
71896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_g_fmt_vid_out	= vidioc_g_fmt_vid_out,
71996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_try_fmt_vid_out	= vidioc_try_fmt_vid_out,
72096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_s_fmt_vid_out	= vidioc_s_fmt_vid_out,
72196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
72296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_reqbufs		= vidioc_reqbufs,
72396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_querybuf	= vidioc_querybuf,
72496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
72596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_qbuf		= vidioc_qbuf,
72696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_dqbuf		= vidioc_dqbuf,
72796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
72896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_streamon	= vidioc_streamon,
72996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_streamoff	= vidioc_streamoff,
73096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
73196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_queryctrl	= vidioc_queryctrl,
73296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_g_ctrl		= vidioc_g_ctrl,
73396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.vidioc_s_ctrl		= vidioc_s_ctrl,
73496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
73596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
73696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
73796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/*
73896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * Queue operations
73996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak */
74096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
741fc714e70dd063e6887d09872ac6158b0c20cc817Guennadi Liakhovetskistatic int m2mtest_queue_setup(struct vb2_queue *vq,
742fc714e70dd063e6887d09872ac6158b0c20cc817Guennadi Liakhovetski				const struct v4l2_format *fmt,
743fc714e70dd063e6887d09872ac6158b0c20cc817Guennadi Liakhovetski				unsigned int *nbuffers, unsigned int *nplanes,
744fc714e70dd063e6887d09872ac6158b0c20cc817Guennadi Liakhovetski				unsigned int sizes[], void *alloc_ctxs[])
74596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
746d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vq);
74796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_q_data *q_data;
748d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	unsigned int size, count = *nbuffers;
74996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
75096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	q_data = get_q_data(vq->type);
75196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
752d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	size = q_data->width * q_data->height * q_data->fmt->depth >> 3;
753d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
754d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	while (size * count > MEM2MEM_VID_MEM_LIMIT)
755d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski		(count)--;
75696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
757d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	*nplanes = 1;
758d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	*nbuffers = count;
759d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	sizes[0] = size;
76096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
761d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	/*
762d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	 * videobuf2-vmalloc allocator is context-less so no need to set
763d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	 * alloc_ctxs array.
764d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	 */
76596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
766d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
76796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
76896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
76996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
77096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
771d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowskistatic int m2mtest_buf_prepare(struct vb2_buffer *vb)
77296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
773d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
77496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_q_data *q_data;
77596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
776d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
77796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
778d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	q_data = get_q_data(vb->vb2_queue->type);
77996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
780d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
781d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski		dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n",
782d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski				__func__, vb2_plane_size(vb, 0), (long)q_data->sizeimage);
78396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -EINVAL;
78496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
78596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
786d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	vb2_set_plane_payload(vb, 0, q_data->sizeimage);
78796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
78896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
78996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
79096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
791d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowskistatic void m2mtest_buf_queue(struct vb2_buffer *vb)
79296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
793d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
794d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
79596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
79696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
7970f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrichstatic void m2mtest_wait_prepare(struct vb2_queue *q)
7980f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich{
7990f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich	struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
8000f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich	m2mtest_unlock(ctx);
8010f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich}
8020f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich
8030f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrichstatic void m2mtest_wait_finish(struct vb2_queue *q)
8040f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich{
8050f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich	struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
8060f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich	m2mtest_lock(ctx);
8070f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich}
8080f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich
809d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowskistatic struct vb2_ops m2mtest_qops = {
810d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	.queue_setup	 = m2mtest_queue_setup,
811d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	.buf_prepare	 = m2mtest_buf_prepare,
812d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	.buf_queue	 = m2mtest_buf_queue,
8130f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich	.wait_prepare	 = m2mtest_wait_prepare,
8140f910bf0008c54b33da5691278c8ee8e8700ac48Michael Olbrich	.wait_finish	 = m2mtest_wait_finish,
81596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
81696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
817d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowskistatic int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
81896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
81996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = priv;
820d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	int ret;
82196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
822d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	memset(src_vq, 0, sizeof(*src_vq));
823d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
824d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	src_vq->io_modes = VB2_MMAP;
825d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	src_vq->drv_priv = ctx;
826d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
827d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	src_vq->ops = &m2mtest_qops;
828d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	src_vq->mem_ops = &vb2_vmalloc_memops;
829d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
830d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	ret = vb2_queue_init(src_vq);
831d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	if (ret)
832d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski		return ret;
83396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
834d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	memset(dst_vq, 0, sizeof(*dst_vq));
835d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
836d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	dst_vq->io_modes = VB2_MMAP;
837d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	dst_vq->drv_priv = ctx;
838d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
839d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	dst_vq->ops = &m2mtest_qops;
840d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	dst_vq->mem_ops = &vb2_vmalloc_memops;
841d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
842d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	return vb2_queue_init(dst_vq);
843d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski}
84496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
84596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak/*
84696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak * File operations
84796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak */
84896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int m2mtest_open(struct file *file)
84996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
85096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_dev *dev = video_drvdata(file);
85196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = NULL;
85296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
85396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
85496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!ctx)
85596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -ENOMEM;
85696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
85796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	file->private_data = ctx;
85896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ctx->dev = dev;
85996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ctx->translen = MEM2MEM_DEF_TRANSLEN;
86096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ctx->transtime = MEM2MEM_DEF_TRANSTIME;
86196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ctx->num_processed = 0;
86296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
863d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
864d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski
86596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (IS_ERR(ctx->m2m_ctx)) {
86616ee9bb100340f9f775ab334acb645f54642f312Dan Carpenter		int ret = PTR_ERR(ctx->m2m_ctx);
86716ee9bb100340f9f775ab334acb645f54642f312Dan Carpenter
86896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		kfree(ctx);
86916ee9bb100340f9f775ab334acb645f54642f312Dan Carpenter		return ret;
87096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
87196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
87296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	atomic_inc(&dev->num_inst);
87396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
87496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
87596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
87696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
87796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
87896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
87996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int m2mtest_release(struct file *file)
88096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
88196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_dev *dev = video_drvdata(file);
88296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_ctx *ctx = file->private_data;
88396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
88496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	dprintk(dev, "Releasing instance %p\n", ctx);
88596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
88696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	v4l2_m2m_ctx_release(ctx->m2m_ctx);
88796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	kfree(ctx);
88896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
88996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	atomic_dec(&dev->num_inst);
89096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
89196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
89296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
89396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
89496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic unsigned int m2mtest_poll(struct file *file,
89596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak				 struct poll_table_struct *wait)
89696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
897abf84383ecadc8ada1963f9976e887c6f0b1bad9Joe Perches	struct m2mtest_ctx *ctx = file->private_data;
89896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
89996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
90096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
90196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
90296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int m2mtest_mmap(struct file *file, struct vm_area_struct *vma)
90396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
904abf84383ecadc8ada1963f9976e887c6f0b1bad9Joe Perches	struct m2mtest_ctx *ctx = file->private_data;
90596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
90696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
90796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
90896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
90996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic const struct v4l2_file_operations m2mtest_fops = {
91096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.owner		= THIS_MODULE,
91196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.open		= m2mtest_open,
91296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.release	= m2mtest_release,
91396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.poll		= m2mtest_poll,
91407e80305babb27a332ce0f04a3c38ce495cbe711Marek Szyprowski	.unlocked_ioctl	= video_ioctl2,
91596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.mmap		= m2mtest_mmap,
91696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
91796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
91896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct video_device m2mtest_videodev = {
91996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.name		= MEM2MEM_NAME,
92096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.fops		= &m2mtest_fops,
92196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.ioctl_ops	= &m2mtest_ioctl_ops,
92296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.minor		= -1,
92396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.release	= video_device_release,
92496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
92596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
92696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct v4l2_m2m_ops m2m_ops = {
92796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.device_run	= device_run,
92896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.job_ready	= job_ready,
92996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.job_abort	= job_abort,
930d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	.lock		= m2mtest_lock,
931d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	.unlock		= m2mtest_unlock,
93296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
93396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
93496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int m2mtest_probe(struct platform_device *pdev)
93596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
93696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_dev *dev;
93796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct video_device *vfd;
93896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int ret;
93996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
94096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	dev = kzalloc(sizeof *dev, GFP_KERNEL);
94196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!dev)
94296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return -ENOMEM;
94396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
94496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	spin_lock_init(&dev->irqlock);
94596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
94696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
94796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (ret)
94896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		goto free_dev;
94996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
95096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	atomic_set(&dev->num_inst, 0);
95196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	mutex_init(&dev->dev_mutex);
95296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
95396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	vfd = video_device_alloc();
95496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (!vfd) {
95596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
95696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		ret = -ENOMEM;
95796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		goto unreg_dev;
95896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
95996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
96096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	*vfd = m2mtest_videodev;
96107e80305babb27a332ce0f04a3c38ce495cbe711Marek Szyprowski	vfd->lock = &dev->dev_mutex;
96296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
96396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
96496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (ret) {
96596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
96696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		goto rel_vdev;
96796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
96896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
96996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	video_set_drvdata(vfd, dev);
97096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	snprintf(vfd->name, sizeof(vfd->name), "%s", m2mtest_videodev.name);
97196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	dev->vfd = vfd;
97296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	v4l2_info(&dev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME
97396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak			"Device registered as /dev/video%d\n", vfd->num);
97496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
97596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	setup_timer(&dev->timer, device_isr, (long)dev);
97696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	platform_set_drvdata(pdev, dev);
97796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
97896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
97996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (IS_ERR(dev->m2m_dev)) {
98096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
98196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		ret = PTR_ERR(dev->m2m_dev);
98296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		goto err_m2m;
98396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	}
98496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
985b6ae906b04113cb73c1ffe9c42fbcdcb074d9f07Pawel Osciak	q_data[V4L2_M2M_SRC].fmt = &formats[0];
986b6ae906b04113cb73c1ffe9c42fbcdcb074d9f07Pawel Osciak	q_data[V4L2_M2M_DST].fmt = &formats[0];
987b6ae906b04113cb73c1ffe9c42fbcdcb074d9f07Pawel Osciak
98896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
98996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
990d80ee38cd845baadef175893b99df24e7a03ec40Marek Szyprowski	v4l2_m2m_release(dev->m2m_dev);
99196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakerr_m2m:
99296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	video_unregister_device(dev->vfd);
99396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakrel_vdev:
99496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	video_device_release(vfd);
99596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakunreg_dev:
99696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	v4l2_device_unregister(&dev->v4l2_dev);
99796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakfree_dev:
99896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	kfree(dev);
99996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
100096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return ret;
100196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
100296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
100396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int m2mtest_remove(struct platform_device *pdev)
100496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
100596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	struct m2mtest_dev *dev =
100696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		(struct m2mtest_dev *)platform_get_drvdata(pdev);
100796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
100896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
100996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	v4l2_m2m_release(dev->m2m_dev);
101096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	del_timer_sync(&dev->timer);
101196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	video_unregister_device(dev->vfd);
101296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	v4l2_device_unregister(&dev->v4l2_dev);
101396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	kfree(dev);
101496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
101596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
101696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
101796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
101896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic struct platform_driver m2mtest_pdrv = {
101996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.probe		= m2mtest_probe,
102096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.remove		= m2mtest_remove,
102196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	.driver		= {
102296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.name	= MEM2MEM_NAME,
102396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		.owner	= THIS_MODULE,
102496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	},
102596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak};
102696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
102796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic void __exit m2mtest_exit(void)
102896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
102996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	platform_driver_unregister(&m2mtest_pdrv);
103096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	platform_device_unregister(&m2mtest_pdev);
103196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
103296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
103396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakstatic int __init m2mtest_init(void)
103496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak{
103596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	int ret;
103696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
103796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ret = platform_device_register(&m2mtest_pdev);
103896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (ret)
103996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		return ret;
104096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
104196d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	ret = platform_driver_register(&m2mtest_pdrv);
104296d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	if (ret)
104396d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak		platform_device_unregister(&m2mtest_pdev);
104496d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
104596d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak	return 0;
104696d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak}
104796d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
104896d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakmodule_init(m2mtest_init);
104996d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciakmodule_exit(m2mtest_exit);
105096d8eab5d0a1a9741a4cae1b3c125d75d1aabedfPawel Osciak
1051