[v2,14/20] media: i2c: ov4689: Implement manual color balance controls
Commit Message
The OV4689 sensor has separate red and blue gain settings (up to 4x).
Implement appropriate controls in the driver. Default gain values
are not modified.
Signed-off-by: Mikhail Rudenko <mike.rudenko@gmail.com>
---
drivers/media/i2c/ov4689.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
Comments
Hi Mikhail,
Thank you for the patch.
On Mon, Dec 18, 2023 at 08:40:35PM +0300, Mikhail Rudenko wrote:
> The OV4689 sensor has separate red and blue gain settings (up to 4x).
> Implement appropriate controls in the driver. Default gain values
> are not modified.
>
> Signed-off-by: Mikhail Rudenko <mike.rudenko@gmail.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> drivers/media/i2c/ov4689.c | 23 ++++++++++++++++++++++-
> 1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c
> index 579362570ba4..b43fb1d7b15f 100644
> --- a/drivers/media/i2c/ov4689.c
> +++ b/drivers/media/i2c/ov4689.c
> @@ -56,6 +56,13 @@
> #define OV4689_TIMING_FLIP_BOTH (OV4689_TIMING_FLIP_ARRAY |\
> OV4689_TIMING_FLIP_DIGITAL)
>
> +#define OV4689_REG_WB_GAIN_RED CCI_REG16(0x500c)
> +#define OV4689_REG_WB_GAIN_BLUE CCI_REG16(0x5010)
> +#define OV4689_WB_GAIN_MIN 1
> +#define OV4689_WB_GAIN_MAX 0xfff
> +#define OV4689_WB_GAIN_STEP 1
> +#define OV4689_WB_GAIN_DEFAULT 0x400
> +
> #define OV4689_REG_TEST_PATTERN CCI_REG8(0x5040)
> #define OV4689_TEST_PATTERN_ENABLE 0x80
> #define OV4689_TEST_PATTERN_DISABLE 0x0
> @@ -632,6 +639,12 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl)
> case V4L2_CID_DIGITAL_GAIN:
> cci_write(regmap, OV4689_REG_DIG_GAIN, ctrl->val, &ret);
> break;
> + case V4L2_CID_RED_BALANCE:
> + cci_write(regmap, OV4689_REG_WB_GAIN_RED, ctrl->val, &ret);
> + break;
> + case V4L2_CID_BLUE_BALANCE:
> + cci_write(regmap, OV4689_REG_WB_GAIN_BLUE, ctrl->val, &ret);
> + break;
> default:
> dev_warn(dev, "%s Unhandled id:0x%x, val:0x%x\n",
> __func__, ctrl->id, ctrl->val);
> @@ -662,7 +675,7 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689)
>
> handler = &ov4689->ctrl_handler;
> mode = ov4689->cur_mode;
> - ret = v4l2_ctrl_handler_init(handler, 13);
> + ret = v4l2_ctrl_handler_init(handler, 15);
> if (ret)
> return ret;
>
> @@ -709,6 +722,14 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689)
> OV4689_DIG_GAIN_MIN, OV4689_DIG_GAIN_MAX,
> OV4689_DIG_GAIN_STEP, OV4689_DIG_GAIN_DEFAULT);
>
> + v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_RED_BALANCE,
> + OV4689_WB_GAIN_MIN, OV4689_WB_GAIN_MAX,
> + OV4689_WB_GAIN_STEP, OV4689_WB_GAIN_DEFAULT);
> +
> + v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_BLUE_BALANCE,
> + OV4689_WB_GAIN_MIN, OV4689_WB_GAIN_MAX,
> + OV4689_WB_GAIN_STEP, OV4689_WB_GAIN_DEFAULT);
> +
> if (handler->error) {
> ret = handler->error;
> dev_err(ov4689->dev, "Failed to init controls(%d)\n", ret);
@@ -56,6 +56,13 @@
#define OV4689_TIMING_FLIP_BOTH (OV4689_TIMING_FLIP_ARRAY |\
OV4689_TIMING_FLIP_DIGITAL)
+#define OV4689_REG_WB_GAIN_RED CCI_REG16(0x500c)
+#define OV4689_REG_WB_GAIN_BLUE CCI_REG16(0x5010)
+#define OV4689_WB_GAIN_MIN 1
+#define OV4689_WB_GAIN_MAX 0xfff
+#define OV4689_WB_GAIN_STEP 1
+#define OV4689_WB_GAIN_DEFAULT 0x400
+
#define OV4689_REG_TEST_PATTERN CCI_REG8(0x5040)
#define OV4689_TEST_PATTERN_ENABLE 0x80
#define OV4689_TEST_PATTERN_DISABLE 0x0
@@ -632,6 +639,12 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_DIGITAL_GAIN:
cci_write(regmap, OV4689_REG_DIG_GAIN, ctrl->val, &ret);
break;
+ case V4L2_CID_RED_BALANCE:
+ cci_write(regmap, OV4689_REG_WB_GAIN_RED, ctrl->val, &ret);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ cci_write(regmap, OV4689_REG_WB_GAIN_BLUE, ctrl->val, &ret);
+ break;
default:
dev_warn(dev, "%s Unhandled id:0x%x, val:0x%x\n",
__func__, ctrl->id, ctrl->val);
@@ -662,7 +675,7 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689)
handler = &ov4689->ctrl_handler;
mode = ov4689->cur_mode;
- ret = v4l2_ctrl_handler_init(handler, 13);
+ ret = v4l2_ctrl_handler_init(handler, 15);
if (ret)
return ret;
@@ -709,6 +722,14 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689)
OV4689_DIG_GAIN_MIN, OV4689_DIG_GAIN_MAX,
OV4689_DIG_GAIN_STEP, OV4689_DIG_GAIN_DEFAULT);
+ v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_RED_BALANCE,
+ OV4689_WB_GAIN_MIN, OV4689_WB_GAIN_MAX,
+ OV4689_WB_GAIN_STEP, OV4689_WB_GAIN_DEFAULT);
+
+ v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_BLUE_BALANCE,
+ OV4689_WB_GAIN_MIN, OV4689_WB_GAIN_MAX,
+ OV4689_WB_GAIN_STEP, OV4689_WB_GAIN_DEFAULT);
+
if (handler->error) {
ret = handler->error;
dev_err(ov4689->dev, "Failed to init controls(%d)\n", ret);