Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3dd59c2 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

[media] mem2mem_testdev: convert to the control framework and v4l2_fh

parent 7bf6afbb
Loading
Loading
Loading
Loading
+83 −151
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/videobuf2-vmalloc.h>

#define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev"
@@ -101,6 +102,8 @@ static struct m2mtest_fmt formats[] = {
	},
};

#define NUM_FORMATS ARRAY_SIZE(formats)

/* Per-queue, driver-specific private data */
struct m2mtest_q_data {
	unsigned int		width;
@@ -114,50 +117,8 @@ enum {
	V4L2_M2M_DST = 1,
};

#define V4L2_CID_TRANS_TIME_MSEC	V4L2_CID_PRIVATE_BASE
#define V4L2_CID_TRANS_NUM_BUFS		(V4L2_CID_PRIVATE_BASE + 1)

static struct v4l2_queryctrl m2mtest_ctrls[] = {
	{
		.id		= V4L2_CID_HFLIP,
		.type		= V4L2_CTRL_TYPE_BOOLEAN,
		.name		= "Mirror",
		.minimum	= 0,
		.maximum	= 1,
		.step		= 1,
		.default_value	= 0,
		.flags		= 0,
	}, {
		.id		= V4L2_CID_VFLIP,
		.type		= V4L2_CTRL_TYPE_BOOLEAN,
		.name		= "Vertical Mirror",
		.minimum	= 0,
		.maximum	= 1,
		.step		= 1,
		.default_value	= 0,
		.flags		= 0,
	}, {
		.id		= V4L2_CID_TRANS_TIME_MSEC,
		.type		= V4L2_CTRL_TYPE_INTEGER,
		.name		= "Transaction time (msec)",
		.minimum	= 1,
		.maximum	= 10000,
		.step		= 100,
		.default_value	= 1000,
		.flags		= 0,
	}, {
		.id		= V4L2_CID_TRANS_NUM_BUFS,
		.type		= V4L2_CTRL_TYPE_INTEGER,
		.name		= "Buffers per transaction",
		.minimum	= 1,
		.maximum	= MEM2MEM_DEF_NUM_BUFS,
		.step		= 1,
		.default_value	= 1,
		.flags		= 0,
	},
};

#define NUM_FORMATS ARRAY_SIZE(formats)
#define V4L2_CID_TRANS_TIME_MSEC	(V4L2_CID_USER_BASE + 0x1000)
#define V4L2_CID_TRANS_NUM_BUFS		(V4L2_CID_USER_BASE + 0x1001)

static struct m2mtest_fmt *find_format(struct v4l2_format *f)
{
@@ -190,8 +151,11 @@ struct m2mtest_dev {
};

struct m2mtest_ctx {
	struct v4l2_fh		fh;
	struct m2mtest_dev	*dev;

	struct v4l2_ctrl_handler hdl;

	/* Processed buffers in this transaction */
	u8			num_processed;

@@ -212,6 +176,11 @@ struct m2mtest_ctx {
	struct m2mtest_q_data   q_data[2];
};

static inline struct m2mtest_ctx *file2ctx(struct file *file)
{
	return container_of(file->private_data, struct m2mtest_ctx, fh);
}

static struct m2mtest_q_data *get_q_data(struct m2mtest_ctx *ctx,
					 enum v4l2_buf_type type)
{
@@ -227,18 +196,6 @@ static struct m2mtest_q_data *get_q_data(struct m2mtest_ctx *ctx,
}


static struct v4l2_queryctrl *get_ctrl(int id)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(m2mtest_ctrls); ++i) {
		if (id == m2mtest_ctrls[i].id)
			return &m2mtest_ctrls[i];
	}

	return NULL;
}

static int device_process(struct m2mtest_ctx *ctx,
			  struct vb2_buffer *in_vb,
			  struct vb2_buffer *out_vb)
@@ -543,13 +500,13 @@ static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
				struct v4l2_format *f)
{
	return vidioc_g_fmt(priv, f);
	return vidioc_g_fmt(file2ctx(file), f);
}

static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
				struct v4l2_format *f)
{
	return vidioc_g_fmt(priv, f);
	return vidioc_g_fmt(file2ctx(file), f);
}

static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt)
@@ -588,7 +545,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
				  struct v4l2_format *f)
{
	struct m2mtest_fmt *fmt;
	struct m2mtest_ctx *ctx = priv;
	struct m2mtest_ctx *ctx = file2ctx(file);

	fmt = find_format(f);
	if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
@@ -605,7 +562,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
				  struct v4l2_format *f)
{
	struct m2mtest_fmt *fmt;
	struct m2mtest_ctx *ctx = priv;
	struct m2mtest_ctx *ctx = file2ctx(file);

	fmt = find_format(f);
	if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
@@ -658,7 +615,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
	if (ret)
		return ret;

	return vidioc_s_fmt(priv, f);
	return vidioc_s_fmt(file2ctx(file), f);
}

static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
@@ -670,13 +627,13 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
	if (ret)
		return ret;

	return vidioc_s_fmt(priv, f);
	return vidioc_s_fmt(file2ctx(file), f);
}

static int vidioc_reqbufs(struct file *file, void *priv,
			  struct v4l2_requestbuffers *reqbufs)
{
	struct m2mtest_ctx *ctx = priv;
	struct m2mtest_ctx *ctx = file2ctx(file);

	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
}
@@ -684,21 +641,21 @@ static int vidioc_reqbufs(struct file *file, void *priv,
static int vidioc_querybuf(struct file *file, void *priv,
			   struct v4l2_buffer *buf)
{
	struct m2mtest_ctx *ctx = priv;
	struct m2mtest_ctx *ctx = file2ctx(file);

	return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
}

static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
{
	struct m2mtest_ctx *ctx = priv;
	struct m2mtest_ctx *ctx = file2ctx(file);

	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
}

static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
{
	struct m2mtest_ctx *ctx = priv;
	struct m2mtest_ctx *ctx = file2ctx(file);

	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
}
@@ -706,7 +663,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
static int vidioc_streamon(struct file *file, void *priv,
			   enum v4l2_buf_type type)
{
	struct m2mtest_ctx *ctx = priv;
	struct m2mtest_ctx *ctx = file2ctx(file);

	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
}
@@ -714,101 +671,37 @@ static int vidioc_streamon(struct file *file, void *priv,
static int vidioc_streamoff(struct file *file, void *priv,
			    enum v4l2_buf_type type)
{
	struct m2mtest_ctx *ctx = priv;
	struct m2mtest_ctx *ctx = file2ctx(file);

	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
}

static int vidioc_queryctrl(struct file *file, void *priv,
			    struct v4l2_queryctrl *qc)
static int m2mtest_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct v4l2_queryctrl *c;

	c = get_ctrl(qc->id);
	if (!c)
		return -EINVAL;

	*qc = *c;
	return 0;
}

static int vidioc_g_ctrl(struct file *file, void *priv,
			 struct v4l2_control *ctrl)
{
	struct m2mtest_ctx *ctx = priv;
	struct m2mtest_ctx *ctx =
		container_of(ctrl->handler, struct m2mtest_ctx, hdl);

	switch (ctrl->id) {
	case V4L2_CID_HFLIP:
		ctrl->value = (ctx->mode & MEM2MEM_HFLIP) ? 1 : 0;
		break;

	case V4L2_CID_VFLIP:
		ctrl->value = (ctx->mode & MEM2MEM_VFLIP) ? 1 : 0;
		break;

	case V4L2_CID_TRANS_TIME_MSEC:
		ctrl->value = ctx->transtime;
		break;

	case V4L2_CID_TRANS_NUM_BUFS:
		ctrl->value = ctx->translen;
		break;

	default:
		v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
		return -EINVAL;
	}

	return 0;
}

static int check_ctrl_val(struct m2mtest_ctx *ctx, struct v4l2_control *ctrl)
{
	struct v4l2_queryctrl *c;

	c = get_ctrl(ctrl->id);
	if (!c)
		return -EINVAL;

	if (ctrl->value < c->minimum || ctrl->value > c->maximum) {
		v4l2_err(&ctx->dev->v4l2_dev, "Value out of range\n");
		return -ERANGE;
	}

	return 0;
}

static int vidioc_s_ctrl(struct file *file, void *priv,
			 struct v4l2_control *ctrl)
{
	struct m2mtest_ctx *ctx = priv;
	int ret = 0;

	ret = check_ctrl_val(ctx, ctrl);
	if (ret != 0)
		return ret;

	switch (ctrl->id) {
	case V4L2_CID_HFLIP:
		if (ctrl->value)
		if (ctrl->val)
			ctx->mode |= MEM2MEM_HFLIP;
		else
			ctx->mode &= ~MEM2MEM_HFLIP;
		break;

	case V4L2_CID_VFLIP:
		if (ctrl->value)
		if (ctrl->val)
			ctx->mode |= MEM2MEM_VFLIP;
		else
			ctx->mode &= ~MEM2MEM_VFLIP;
		break;

	case V4L2_CID_TRANS_TIME_MSEC:
		ctx->transtime = ctrl->value;
		ctx->transtime = ctrl->val;
		break;

	case V4L2_CID_TRANS_NUM_BUFS:
		ctx->translen = ctrl->value;
		ctx->translen = ctrl->val;
		break;

	default:
@@ -819,6 +712,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
	return 0;
}

static const struct v4l2_ctrl_ops m2mtest_ctrl_ops = {
	.s_ctrl = m2mtest_s_ctrl,
};


static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {
	.vidioc_querycap	= vidioc_querycap,
@@ -841,10 +738,6 @@ static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {

	.vidioc_streamon	= vidioc_streamon,
	.vidioc_streamoff	= vidioc_streamoff,

	.vidioc_queryctrl	= vidioc_queryctrl,
	.vidioc_g_ctrl		= vidioc_g_ctrl,
	.vidioc_s_ctrl		= vidioc_s_ctrl,
};


@@ -956,6 +849,28 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds
	return vb2_queue_init(dst_vq);
}

static const struct v4l2_ctrl_config m2mtest_ctrl_trans_time_msec = {
	.ops = &m2mtest_ctrl_ops,
	.id = V4L2_CID_TRANS_TIME_MSEC,
	.name = "Transaction Time (msec)",
	.type = V4L2_CTRL_TYPE_INTEGER,
	.def = 1001,
	.min = 1,
	.max = 10001,
	.step = 100,
};

static const struct v4l2_ctrl_config m2mtest_ctrl_trans_num_bufs = {
	.ops = &m2mtest_ctrl_ops,
	.id = V4L2_CID_TRANS_NUM_BUFS,
	.name = "Buffers Per Transaction",
	.type = V4L2_CTRL_TYPE_INTEGER,
	.def = 1,
	.min = 1,
	.max = MEM2MEM_DEF_NUM_BUFS,
	.step = 1,
};

/*
 * File operations
 */
@@ -963,17 +878,29 @@ static int m2mtest_open(struct file *file)
{
	struct m2mtest_dev *dev = video_drvdata(file);
	struct m2mtest_ctx *ctx = NULL;
	struct v4l2_ctrl_handler *hdl;

	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;

	file->private_data = ctx;
	v4l2_fh_init(&ctx->fh, video_devdata(file));
	file->private_data = &ctx->fh;
	ctx->dev = dev;
	ctx->translen = MEM2MEM_DEF_TRANSLEN;
	ctx->transtime = MEM2MEM_DEF_TRANSTIME;
	ctx->num_processed = 0;
	ctx->mode = 0;
	hdl = &ctx->hdl;
	v4l2_ctrl_handler_init(hdl, 4);
	v4l2_ctrl_new_std(hdl, &m2mtest_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
	v4l2_ctrl_new_std(hdl, &m2mtest_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
	v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_time_msec, NULL);
	v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_num_bufs, NULL);
	if (hdl->error) {
		int err = hdl->error;

		v4l2_ctrl_handler_free(hdl);
		return err;
	}
	ctx->fh.ctrl_handler = hdl;
	v4l2_ctrl_handler_setup(hdl);

	ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
	ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
@@ -983,10 +910,12 @@ static int m2mtest_open(struct file *file)
	if (IS_ERR(ctx->m2m_ctx)) {
		int ret = PTR_ERR(ctx->m2m_ctx);

		v4l2_ctrl_handler_free(hdl);
		kfree(ctx);
		return ret;
	}

	v4l2_fh_add(&ctx->fh);
	atomic_inc(&dev->num_inst);

	dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
@@ -997,10 +926,13 @@ static int m2mtest_open(struct file *file)
static int m2mtest_release(struct file *file)
{
	struct m2mtest_dev *dev = video_drvdata(file);
	struct m2mtest_ctx *ctx = file->private_data;
	struct m2mtest_ctx *ctx = file2ctx(file);

	dprintk(dev, "Releasing instance %p\n", ctx);

	v4l2_fh_del(&ctx->fh);
	v4l2_fh_exit(&ctx->fh);
	v4l2_ctrl_handler_free(&ctx->hdl);
	v4l2_m2m_ctx_release(ctx->m2m_ctx);
	kfree(ctx);

@@ -1012,14 +944,14 @@ static int m2mtest_release(struct file *file)
static unsigned int m2mtest_poll(struct file *file,
				 struct poll_table_struct *wait)
{
	struct m2mtest_ctx *ctx = file->private_data;
	struct m2mtest_ctx *ctx = file2ctx(file);

	return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
}

static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma)
{
	struct m2mtest_ctx *ctx = file->private_data;
	struct m2mtest_ctx *ctx = file2ctx(file);

	return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
}