diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 4a1433728cd5..ce6d8a90f4a1 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -53,12 +53,20 @@ /* Analog gain control */ #define IMX214_REG_ANALOG_GAIN CCI_REG16(0x0204) #define IMX214_REG_SHORT_ANALOG_GAIN CCI_REG16(0x0216) +#define IMX214_ANA_GAIN_MIN 0 +#define IMX214_ANA_GAIN_MAX 448 +#define IMX214_ANA_GAIN_STEP 1 +#define IMX214_ANA_GAIN_DEFAULT 0x0 /* Digital gain control */ #define IMX214_REG_DIG_GAIN_GREENR CCI_REG16(0x020e) #define IMX214_REG_DIG_GAIN_RED CCI_REG16(0x0210) #define IMX214_REG_DIG_GAIN_BLUE CCI_REG16(0x0212) #define IMX214_REG_DIG_GAIN_GREENB CCI_REG16(0x0214) +#define IMX214_DGTL_GAIN_MIN 0x0100 +#define IMX214_DGTL_GAIN_MAX 0x0fff +#define IMX214_DGTL_GAIN_DEFAULT 0x0100 +#define IMX214_DGTL_GAIN_STEP 1 #define IMX214_REG_ORIENTATION CCI_REG8(0x0101) @@ -271,13 +279,6 @@ static const struct cci_reg_sequence mode_4096x2304[] = { { IMX214_REG_SHORT_EXPOSURE, 500 }, - { IMX214_REG_ANALOG_GAIN, 0 }, - { IMX214_REG_DIG_GAIN_GREENR, 256 }, - { IMX214_REG_DIG_GAIN_RED, 256 }, - { IMX214_REG_DIG_GAIN_BLUE, 256 }, - { IMX214_REG_DIG_GAIN_GREENB, 256 }, - { IMX214_REG_SHORT_ANALOG_GAIN, 0 }, - { CCI_REG8(0x4170), 0x00 }, { CCI_REG8(0x4171), 0x10 }, { CCI_REG8(0x4176), 0x00 }, @@ -327,13 +328,6 @@ static const struct cci_reg_sequence mode_1920x1080[] = { { IMX214_REG_SHORT_EXPOSURE, 500 }, - { IMX214_REG_ANALOG_GAIN, 0 }, - { IMX214_REG_DIG_GAIN_GREENR, 256 }, - { IMX214_REG_DIG_GAIN_RED, 256 }, - { IMX214_REG_DIG_GAIN_BLUE, 256 }, - { IMX214_REG_DIG_GAIN_GREENB, 256 }, - { IMX214_REG_SHORT_ANALOG_GAIN, 0 }, - { CCI_REG8(0x4170), 0x00 }, { CCI_REG8(0x4171), 0x10 }, { CCI_REG8(0x4176), 0x00 }, @@ -757,6 +751,18 @@ static int imx214_entity_init_state(struct v4l2_subdev *subdev, return 0; } +static int imx214_update_digital_gain(struct imx214 *imx214, u32 val) +{ + int ret = 0; + + cci_write(imx214->regmap, IMX214_REG_DIG_GAIN_GREENR, val, &ret); + cci_write(imx214->regmap, IMX214_REG_DIG_GAIN_RED, val, &ret); + cci_write(imx214->regmap, IMX214_REG_DIG_GAIN_BLUE, val, &ret); + cci_write(imx214->regmap, IMX214_REG_DIG_GAIN_GREENB, val, &ret); + + return ret; +} + static int imx214_set_ctrl(struct v4l2_ctrl *ctrl) { struct imx214 *imx214 = container_of(ctrl->handler, @@ -788,6 +794,15 @@ static int imx214_set_ctrl(struct v4l2_ctrl *ctrl) return 0; switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + cci_write(imx214->regmap, IMX214_REG_ANALOG_GAIN, + ctrl->val, &ret); + cci_write(imx214->regmap, IMX214_REG_SHORT_ANALOG_GAIN, + ctrl->val, &ret); + break; + case V4L2_CID_DIGITAL_GAIN: + ret = imx214_update_digital_gain(imx214, ctrl->val); + break; case V4L2_CID_EXPOSURE: cci_write(imx214->regmap, IMX214_REG_EXPOSURE, ctrl->val, &ret); break; @@ -834,7 +849,7 @@ static int imx214_ctrls_init(struct imx214 *imx214) return ret; ctrl_hdlr = &imx214->ctrls; - ret = v4l2_ctrl_handler_init(&imx214->ctrls, 10); + ret = v4l2_ctrl_handler_init(&imx214->ctrls, 12); if (ret) return ret; @@ -871,6 +886,14 @@ static int imx214_ctrls_init(struct imx214 *imx214) IMX214_EXPOSURE_STEP, exposure_def); + v4l2_ctrl_new_std(ctrl_hdlr, &imx214_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + IMX214_ANA_GAIN_MIN, IMX214_ANA_GAIN_MAX, + IMX214_ANA_GAIN_STEP, IMX214_ANA_GAIN_DEFAULT); + + v4l2_ctrl_new_std(ctrl_hdlr, &imx214_ctrl_ops, V4L2_CID_DIGITAL_GAIN, + IMX214_DGTL_GAIN_MIN, IMX214_DGTL_GAIN_MAX, + IMX214_DGTL_GAIN_STEP, IMX214_DGTL_GAIN_DEFAULT); + imx214->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx214_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); if (imx214->hflip) -- 2.46.0