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

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

[media] mt9v011: convert to the control framework

parent 28718152
Loading
Loading
Loading
Loading
+67 −156
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <asm/div64.h>
#include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h>
#include <media/mt9v011.h>

MODULE_DESCRIPTION("Micron mt9v011 sensor driver");
@@ -48,68 +49,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
#define MT9V011_VERSION			0x8232
#define MT9V011_REV_B_VERSION		0x8243

/* supported controls */
static struct v4l2_queryctrl mt9v011_qctrl[] = {
	{
		.id = V4L2_CID_GAIN,
		.type = V4L2_CTRL_TYPE_INTEGER,
		.name = "Gain",
		.minimum = 0,
		.maximum = (1 << 12) - 1 - 0x0020,
		.step = 1,
		.default_value = 0x0020,
		.flags = 0,
	}, {
		.id = V4L2_CID_EXPOSURE,
		.type = V4L2_CTRL_TYPE_INTEGER,
		.name = "Exposure",
		.minimum = 0,
		.maximum = 2047,
		.step = 1,
		.default_value = 0x01fc,
		.flags = 0,
	}, {
		.id = V4L2_CID_RED_BALANCE,
		.type = V4L2_CTRL_TYPE_INTEGER,
		.name = "Red Balance",
		.minimum = -1 << 9,
		.maximum = (1 << 9) - 1,
		.step = 1,
		.default_value = 0,
		.flags = 0,
	}, {
		.id = V4L2_CID_BLUE_BALANCE,
		.type = V4L2_CTRL_TYPE_INTEGER,
		.name = "Blue Balance",
		.minimum = -1 << 9,
		.maximum = (1 << 9) - 1,
		.step = 1,
		.default_value = 0,
		.flags = 0,
	}, {
		.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    = "Vflip",
		.minimum = 0,
		.maximum = 1,
		.step    = 1,
		.default_value = 0,
		.flags = 0,
	}, {
	}
};

struct mt9v011 {
	struct v4l2_subdev sd;
	struct v4l2_ctrl_handler ctrls;
	unsigned width, height;
	unsigned xtal;
	unsigned hflip:1;
@@ -380,99 +322,6 @@ static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
	set_res(sd);
	set_read_mode(sd);

	return 0;
};

static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	struct mt9v011 *core = to_mt9v011(sd);

	v4l2_dbg(1, debug, sd, "g_ctrl called\n");

	switch (ctrl->id) {
	case V4L2_CID_GAIN:
		ctrl->value = core->global_gain;
		return 0;
	case V4L2_CID_EXPOSURE:
		ctrl->value = core->exposure;
		return 0;
	case V4L2_CID_RED_BALANCE:
		ctrl->value = core->red_bal;
		return 0;
	case V4L2_CID_BLUE_BALANCE:
		ctrl->value = core->blue_bal;
		return 0;
	case V4L2_CID_HFLIP:
		ctrl->value = core->hflip ? 1 : 0;
		return 0;
	case V4L2_CID_VFLIP:
		ctrl->value = core->vflip ? 1 : 0;
		return 0;
	}
	return -EINVAL;
}

static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
{
	int i;

	v4l2_dbg(1, debug, sd, "queryctrl called\n");

	for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++)
		if (qc->id && qc->id == mt9v011_qctrl[i].id) {
			memcpy(qc, &(mt9v011_qctrl[i]),
			       sizeof(*qc));
			return 0;
		}

	return -EINVAL;
}


static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	struct mt9v011 *core = to_mt9v011(sd);
	u8 i, n;
	n = ARRAY_SIZE(mt9v011_qctrl);

	for (i = 0; i < n; i++) {
		if (ctrl->id != mt9v011_qctrl[i].id)
			continue;
		if (ctrl->value < mt9v011_qctrl[i].minimum ||
		    ctrl->value > mt9v011_qctrl[i].maximum)
			return -ERANGE;
		v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n",
					ctrl->id, ctrl->value);
		break;
	}

	switch (ctrl->id) {
	case V4L2_CID_GAIN:
		core->global_gain = ctrl->value;
		break;
	case V4L2_CID_EXPOSURE:
		core->exposure = ctrl->value;
		break;
	case V4L2_CID_RED_BALANCE:
		core->red_bal = ctrl->value;
		break;
	case V4L2_CID_BLUE_BALANCE:
		core->blue_bal = ctrl->value;
		break;
	case V4L2_CID_HFLIP:
		core->hflip = ctrl->value;
		set_read_mode(sd);
		return 0;
	case V4L2_CID_VFLIP:
		core->vflip = ctrl->value;
		set_read_mode(sd);
		return 0;
	default:
		return -EINVAL;
	}

	set_balance(sd);

	return 0;
}

@@ -599,10 +448,46 @@ static int mt9v011_g_chip_ident(struct v4l2_subdev *sd,
					  version);
}

static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
	.queryctrl = mt9v011_queryctrl,
	.g_ctrl = mt9v011_g_ctrl,
static int mt9v011_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct mt9v011 *core =
		container_of(ctrl->handler, struct mt9v011, ctrls);
	struct v4l2_subdev *sd = &core->sd;

	switch (ctrl->id) {
	case V4L2_CID_GAIN:
		core->global_gain = ctrl->val;
		break;
	case V4L2_CID_EXPOSURE:
		core->exposure = ctrl->val;
		break;
	case V4L2_CID_RED_BALANCE:
		core->red_bal = ctrl->val;
		break;
	case V4L2_CID_BLUE_BALANCE:
		core->blue_bal = ctrl->val;
		break;
	case V4L2_CID_HFLIP:
		core->hflip = ctrl->val;
		set_read_mode(sd);
		return 0;
	case V4L2_CID_VFLIP:
		core->vflip = ctrl->val;
		set_read_mode(sd);
		return 0;
	default:
		return -EINVAL;
	}

	set_balance(sd);
	return 0;
}

static struct v4l2_ctrl_ops mt9v011_ctrl_ops = {
	.s_ctrl = mt9v011_s_ctrl,
};

static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
	.reset = mt9v011_reset,
	.g_chip_ident = mt9v011_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -658,6 +543,30 @@ static int mt9v011_probe(struct i2c_client *c,
		return -EINVAL;
	}

	v4l2_ctrl_handler_init(&core->ctrls, 5);
	v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops,
			  V4L2_CID_GAIN, 0, (1 << 12) - 1 - 0x20, 1, 0x20);
	v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops,
			  V4L2_CID_EXPOSURE, 0, 2047, 1, 0x01fc);
	v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops,
			  V4L2_CID_RED_BALANCE, -(1 << 9), (1 << 9) - 1, 1, 0);
	v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops,
			  V4L2_CID_BLUE_BALANCE, -(1 << 9), (1 << 9) - 1, 1, 0);
	v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops,
			  V4L2_CID_HFLIP, 0, 1, 1, 0);
	v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops,
			  V4L2_CID_VFLIP, 0, 1, 1, 0);

	if (core->ctrls.error) {
		int ret = core->ctrls.error;

		v4l2_err(sd, "control initialization error %d\n", ret);
		v4l2_ctrl_handler_free(&core->ctrls);
		kfree(core);
		return ret;
	}
	core->sd.ctrl_handler = &core->ctrls;

	core->global_gain = 0x0024;
	core->exposure = 0x01fc;
	core->width  = 640;
@@ -681,12 +590,14 @@ static int mt9v011_probe(struct i2c_client *c,
static int mt9v011_remove(struct i2c_client *c)
{
	struct v4l2_subdev *sd = i2c_get_clientdata(c);
	struct mt9v011 *core = to_mt9v011(sd);

	v4l2_dbg(1, debug, sd,
		"mt9v011.c: removing mt9v011 adapter on address 0x%x\n",
		c->addr << 1);

	v4l2_device_unregister_subdev(sd);
	v4l2_ctrl_handler_free(&core->ctrls);
	kfree(to_mt9v011(sd));
	return 0;
}