[media] mt9v011: convert to the control framework
authorHans Verkuil <hans.verkuil@cisco.com>
Fri, 7 Sep 2012 08:42:15 +0000 (05:42 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 5 Feb 2013 20:02:49 +0000 (18:02 -0200)
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Frank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/i2c/mt9v011.c

index 6bf01ad62765530b03a6eac686e991476e81b27e..73b7688cbebd32de12403178f72ff71cd645fc9b 100644 (file)
@@ -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;
 }