From b777a9ce95bae96df4953bd1a2f5b04612eedbac Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megi@xff.cz>
Date: Fri, 3 Jun 2022 16:04:04 +0200
Subject: [PATCH 359/389] media: i2c: ov8858: Add support for digital gain
 control

Digital gain control is useful and was missing.

Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
 drivers/media/i2c/ov8858.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/media/i2c/ov8858.c b/drivers/media/i2c/ov8858.c
index a83a5b702d7b..5a66cb65a48c 100644
--- a/drivers/media/i2c/ov8858.c
+++ b/drivers/media/i2c/ov8858.c
@@ -64,6 +64,16 @@
 #define OV8858_GAIN_STEP		1
 #define OV8858_GAIN_DEFAULT		0x80
 
+#define OV8858_REG_DGAIN_H		0x350a
+#define OV8858_REG_DGAIN_L		0x350b
+#define OV8858_DGAIN_H_MASK		0xff
+#define OV8858_DGAIN_H_SHIFT		6
+#define OV8858_DGAIN_L_MASK		0x3f
+#define OV8858_DGAIN_MIN		0x0
+#define OV8858_DGAIN_MAX		0x3fff
+#define OV8858_DGAIN_STEP		1
+#define OV8858_DGAIN_DEFAULT		0x200
+
 #define OV8858_REG_TEST_PATTERN		0x5e00
 #define	OV8858_TEST_PATTERN_ENABLE	0x80
 #define	OV8858_TEST_PATTERN_DISABLE	0x0
@@ -818,6 +828,7 @@ static const struct regval ov8858_global_regs_r2a_2lane[] = {
 	{0x5001, 0x01}, // BLC on
 	{0x5002, 0x08}, // H scale off, WBMATCH off, OTP_DPC
 	{0x5003, 0x20}, // DPC_DBC buffer control enable, WB
+	{0x501e, 0x93}, // enable digital gain
 	{0x5046, 0x12}, //
 	{0x5780, 0x3e}, // DPC
 	{0x5781, 0x0f}, //
@@ -1231,6 +1242,7 @@ static const struct regval ov8858_global_regs_r2a_4lane[] = {
 	{0x5001, 0x01}, // BLC on
 	{0x5002, 0x08}, // WBMATCH sensor's gain, H scale/WBMATCH/OTP_DPC off
 	{0x5003, 0x20}, // DPC_DBC buffer control enable, WB
+	{0x501e, 0x93}, // enable digital gain
 	{0x5046, 0x12}, //
 	{0x5780, 0x3e}, // DPC
 	{0x5781, 0x0f}, //
@@ -2335,6 +2347,17 @@ static int ov8858_set_ctrl(struct v4l2_ctrl *ctrl)
 					OV8858_REG_VALUE_08BIT,
 					ctrl->val & OV8858_GAIN_L_MASK);
 		break;
+	case V4L2_CID_DIGITAL_GAIN:
+		ret = ov8858_write_reg(ov8858->client,
+					OV8858_REG_DGAIN_H,
+					OV8858_REG_VALUE_08BIT,
+					(ctrl->val >> OV8858_DGAIN_H_SHIFT) &
+					OV8858_DGAIN_H_MASK);
+		ret |= ov8858_write_reg(ov8858->client,
+					OV8858_REG_DGAIN_L,
+					OV8858_REG_VALUE_08BIT,
+					ctrl->val & OV8858_DGAIN_L_MASK);
+		break;
 	case V4L2_CID_VBLANK:
 		ret = ov8858_write_reg(ov8858->client,
 					OV8858_REG_VTS,
@@ -2406,6 +2429,11 @@ static int ov8858_initialize_controls(struct ov8858 *ov8858)
 				OV8858_GAIN_MAX, OV8858_GAIN_STEP,
 				OV8858_GAIN_DEFAULT);
 
+	ov8858->digi_gain = v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops,
+				V4L2_CID_DIGITAL_GAIN, OV8858_DGAIN_MIN,
+				OV8858_DGAIN_MAX, OV8858_DGAIN_STEP,
+				OV8858_DGAIN_DEFAULT);
+
 	ov8858->test_pattern = v4l2_ctrl_new_std_menu_items(handler,
 				&ov8858_ctrl_ops, V4L2_CID_TEST_PATTERN,
 				ARRAY_SIZE(ov8858_test_pattern_menu) - 1,
-- 
2.35.3

