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