diff options
Diffstat (limited to 'drivers/media/i2c/mt9v011.c')
-rw-r--r-- | drivers/media/i2c/mt9v011.c | 223 |
1 files changed, 67 insertions, 156 deletions
diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index 6bf01ad62765..73b7688cbebd 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; } |