diff mbox

[REVIEW,3/3] mt9v011: convert to the control framework.

Message ID 8956523f0ef5757e85f7d7061575e7b227290c7b.1359013702.git.hans.verkuil@cisco.com (mailing list archive)
State New, archived
Headers show

Commit Message

Hans Verkuil Jan. 24, 2013, 7:51 a.m. UTC
From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/mt9v011.c |  223 +++++++++++++------------------------------
 1 file changed, 67 insertions(+), 156 deletions(-)

Comments

Frank Schäfer Jan. 25, 2013, 4:56 p.m. UTC | #1
Am 24.01.2013 08:51, schrieb Hans Verkuil:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  drivers/media/i2c/mt9v011.c |  223 +++++++++++++------------------------------
>  1 file changed, 67 insertions(+), 156 deletions(-)
>
> diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c
> index 6bf01ad..73b7688 100644
> --- a/drivers/media/i2c/mt9v011.c
> +++ b/drivers/media/i2c/mt9v011.c
> @@ -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;
> @@ -381,99 +323,6 @@ static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
>  	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;
>  }
>  
>  static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
> @@ -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;
>  }

Tested-by: Frank Schäfer <fschaefer.oss@googlemail.com>

Fixes the em28xx regression (no image control with "Silvercrest 1.3MPix
webcam") in the media-tree.

Regards,
Frank

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c
index 6bf01ad..73b7688 100644
--- a/drivers/media/i2c/mt9v011.c
+++ b/drivers/media/i2c/mt9v011.c
@@ -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;
@@ -381,99 +323,6 @@  static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
 	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;
 }
 
 static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
@@ -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;
 }