From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 19 Dec 2024 01:47:39 +0000
Subject: [PATCH] add wifi6 8852be driver

---
 kernel/drivers/media/i2c/sc230ai.c |  140 ++++++++++++++++++++++++++++++++++++----------
 1 files changed, 110 insertions(+), 30 deletions(-)

diff --git a/kernel/drivers/media/i2c/sc230ai.c b/kernel/drivers/media/i2c/sc230ai.c
index bfd76fc..0394914 100644
--- a/kernel/drivers/media/i2c/sc230ai.c
+++ b/kernel/drivers/media/i2c/sc230ai.c
@@ -61,9 +61,6 @@
 #define SC230AI_REG_SEXPOSURE_L		0x3e05
 #define	SC230AI_EXPOSURE_MIN		1
 #define	SC230AI_EXPOSURE_STEP		1
-#define	SC230AI_EXPOSURE_LIN_MAX	(2 * 0x465 - 9)
-#define	SC230AI_EXPOSURE_HDR_MAX_S	(2 * 0x465 - 9)
-#define	SC230AI_EXPOSURE_HDR_MAX_L	(2 * 0x465 - 9)
 #define SC230AI_VTS_MAX			0x7fff
 
 #define SC230AI_REG_DIG_GAIN		0x3e06
@@ -74,7 +71,7 @@
 #define SC230AI_REG_SANA_GAIN		0x3e12
 #define SC230AI_REG_SANA_FINE_GAIN	0x3e13
 #define SC230AI_GAIN_MIN		1000
-#define SC230AI_GAIN_MAX		1722628       //108.512*15.875*1000
+#define SC230AI_GAIN_MAX		1574800       // 99.2*15.875*1000
 #define SC230AI_GAIN_STEP		1
 #define SC230AI_GAIN_DEFAULT		1000
 #define SC230AI_LGAIN			0
@@ -176,6 +173,7 @@
 	const char		*module_facing;
 	const char		*module_name;
 	const char		*len_name;
+	enum rkmodule_sync_mode	sync_mode;
 	u32			cur_vts;
 	bool			has_init_exp;
 	bool			is_thunderboot;
@@ -537,6 +535,28 @@
 	{REG_NULL, 0x00},
 };
 
+static __maybe_unused const struct regval sc230ai_interal_sync_master_start_regs[] = {
+	{0x300a, 0x24}, //sync as output PAD
+	{0x3032, 0xa0},
+	{0x3222, 0x00}, //master mode
+	{REG_NULL, 0x00},
+};
+
+static __maybe_unused const struct regval sc230ai_interal_sync_master_stop_regs[] = {
+	{REG_NULL, 0x00},
+};
+
+static __maybe_unused const struct regval sc230ai_interal_sync_slaver_start_regs[] = {
+	{0x300a, 0x20}, //sync as input PAD
+	{0x3222, 0x01}, //slave mode
+	{0x3224, 0x92}, //fsync trigger
+	{0x3614, 0x01},
+	{REG_NULL, 0x00},
+};
+
+static __maybe_unused const struct regval sc230ai_interal_sync_slaver_stop_regs[] = {
+	{REG_NULL, 0x00},
+};
 
 static const struct sc230ai_mode supported_modes[] = {
 	{
@@ -678,46 +698,46 @@
 		*again = 0x00;
 		*dgain = 0x00;
 		*dgain_fine = total_gain * 128 / 1000;
-	} else if (total_gain < 3391) {	/* 2 ~ 3.391 gain*/
+	} else if (total_gain < 3100) {	/* 2 ~ 3.1 gain*/
 		*again = 0x01;
 		*dgain = 0x00;
 		*dgain_fine = total_gain * 128 / 1000 / 2;
-	} else if (total_gain < 3391 * 2) {	/* 3.391 ~ 6.782 gain*/
+	} else if (total_gain < 3100 * 2) {	/* 3.100 ~ 6.200 gain*/
 		*again = 0x40;
 		*dgain = 0x00;
-		*dgain_fine = total_gain * 128 / 3391;
-	} else if (total_gain < 3391 * 4) {	/* 6.782 ~ 13.564 gain*/
+		*dgain_fine = total_gain * 128 / 3100;
+	} else if (total_gain < 3100 * 4) {	/* 6.200 ~ 12.400 gain*/
 		*again = 0x48;
 		*dgain = 0x00;
-		*dgain_fine = total_gain * 128 / 3391 / 2;
-	} else if (total_gain < 3391 * 8) {	/* 13.564 ~ 27.128 gain*/
+		*dgain_fine = total_gain * 128 / 3100 / 2;
+	} else if (total_gain < 3100 * 8) {	/* 12.400 ~ 24.800 gain*/
 		*again = 0x49;
 		*dgain = 0x00;
-		*dgain_fine = total_gain * 128 / 3391 / 4;
-	} else if (total_gain < 3391 * 16) {	/* 27.128 ~ 54.256 gain*/
+		*dgain_fine = total_gain * 128 / 3100 / 4;
+	} else if (total_gain < 3100 * 16) {	/* 24.800 ~ 49.600 gain*/
 		*again = 0x4b;
 		*dgain = 0x00;
-		*dgain_fine = total_gain * 128 / 3391 / 8;
-	} else if (total_gain < 3391 * 32) {	/* 54.256 ~ 108.512 gain*/
+		*dgain_fine = total_gain * 128 / 3100 / 8;
+	} else if (total_gain < 3100 * 32) {	/* 49.600 ~ 99.200 gain*/
 		*again = 0x4f;
 		*dgain = 0x00;
-		*dgain_fine = total_gain * 128 / 3391 / 16;
-	} else if (total_gain < 3391 * 64) {	/* 108.512 ~ 217.024 gain*/
+		*dgain_fine = total_gain * 128 / 3100 / 16;
+	} else if (total_gain < 3100 * 64) {	/* 99.200 ~ 198.400 gain*/
 		*again = 0x5f;
 		*dgain = 0x00;
-		*dgain_fine = total_gain * 128 / 3391 / 32;
-	} else if (total_gain < 3391 * 128) {	/* 217.024 ~ 434.048 gain*/
+		*dgain_fine = total_gain * 128 / 3100 / 32;
+	} else if (total_gain < 3100 * 128) {	/* 198.400 ~ 396.800 gain*/
 		*again = 0x5f;
 		*dgain = 0x01;
-		*dgain_fine = total_gain * 128 / 3391 / 64;
-	} else if (total_gain < 3391 * 256) {	/* 434.048 ~ 868.096 gain*/
+		*dgain_fine = total_gain * 128 / 3100 / 64;
+	} else if (total_gain < 3100 * 256) {	/* 396.800 ~ 793.600 gain*/
 		*again = 0x5f;
 		*dgain = 0x03;
-		*dgain_fine = total_gain * 128 / 3391 / 128;
-	} else if (total_gain < 3391 * 512) {	/* 868.096 ~ 1736.192 gain*/
+		*dgain_fine = total_gain * 128 / 3100 / 128;
+	} else {				/* 793.600 ~ 1587.200 gain*/
 		*again = 0x5f;
 		*dgain = 0x07;
-		*dgain_fine = total_gain * 128 / 3391 / 128;
+		*dgain_fine = total_gain * 128 / 3100 / 128;
 	}
 
 	return ret;
@@ -933,6 +953,7 @@
 	u32 i, h, w;
 	long ret = 0;
 	u32 stream = 0;
+	u32 *sync_mode = NULL;
 
 	switch (cmd) {
 	case RKMODULE_GET_MODULE_INFO:
@@ -983,6 +1004,14 @@
 			ret = sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
 				 SC230AI_REG_VALUE_08BIT, SC230AI_MODE_SW_STANDBY);
 		break;
+	case RKMODULE_GET_SYNC_MODE:
+		sync_mode = (u32 *)arg;
+		*sync_mode = sc230ai->sync_mode;
+		break;
+	case RKMODULE_SET_SYNC_MODE:
+		sync_mode = (u32 *)arg;
+		sc230ai->sync_mode = *sync_mode;
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
@@ -1001,6 +1030,7 @@
 	struct preisp_hdrae_exp_s *hdrae;
 	long ret;
 	u32 stream = 0;
+	u32 sync_mode;
 
 	switch (cmd) {
 	case RKMODULE_GET_MODULE_INFO:
@@ -1069,6 +1099,21 @@
 
 		ret = sc230ai_ioctl(sd, cmd, &stream);
 		break;
+	case RKMODULE_GET_SYNC_MODE:
+		ret = sc230ai_ioctl(sd, cmd, &sync_mode);
+		if (!ret) {
+			ret = copy_to_user(up, &sync_mode, sizeof(u32));
+			if (ret)
+				ret = -EFAULT;
+		}
+		break;
+	case RKMODULE_SET_SYNC_MODE:
+		ret = copy_from_user(&sync_mode, up, sizeof(u32));
+		if (!ret)
+			ret = sc230ai_ioctl(sd, cmd, &sync_mode);
+		else
+			ret = -EFAULT;
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
@@ -1080,7 +1125,7 @@
 
 static int __sc230ai_start_stream(struct sc230ai *sc230ai)
 {
-	int ret;
+	int ret = 0;
 
 	if (!sc230ai->is_thunderboot) {
 		ret = sc230ai_write_array(sc230ai->client, sc230ai->cur_mode->reg_list);
@@ -1099,20 +1144,36 @@
 				return ret;
 			}
 		}
+		if (sc230ai->sync_mode == INTERNAL_MASTER_MODE)
+			ret |= sc230ai_write_array(sc230ai->client,
+				sc230ai_interal_sync_master_start_regs);
+		else if (sc230ai->sync_mode == SLAVE_MODE)
+			ret |= sc230ai_write_array(sc230ai->client,
+				sc230ai_interal_sync_slaver_start_regs);
 	}
-	return sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
+	ret |= sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
 				 SC230AI_REG_VALUE_08BIT, SC230AI_MODE_STREAMING);
+	return ret;
 }
 
 static int __sc230ai_stop_stream(struct sc230ai *sc230ai)
 {
+	int ret = 0;
 	sc230ai->has_init_exp = false;
 	if (sc230ai->is_thunderboot) {
 		sc230ai->is_first_streamoff = true;
 		pm_runtime_put(&sc230ai->client->dev);
+	} else {
+		if (sc230ai->sync_mode == INTERNAL_MASTER_MODE)
+			ret |= sc230ai_write_array(sc230ai->client,
+				sc230ai_interal_sync_master_stop_regs);
+		else if (sc230ai->sync_mode == SLAVE_MODE)
+			ret |= sc230ai_write_array(sc230ai->client,
+				sc230ai_interal_sync_slaver_stop_regs);
 	}
-	return sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
+	ret |= sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
 				 SC230AI_REG_VALUE_08BIT, SC230AI_MODE_SW_STANDBY);
+	return ret;
 }
 
 static int __sc230ai_power_on(struct sc230ai *sc230ai);
@@ -1406,7 +1467,7 @@
 	switch (ctrl->id) {
 	case V4L2_CID_VBLANK:
 		/* Update max exposure while meeting expected vblanking */
-		max = sc230ai->cur_mode->height + ctrl->val - 4;
+		max = sc230ai->cur_mode->height + ctrl->val - 5;
 		__v4l2_ctrl_modify_range(sc230ai->exposure,
 					 sc230ai->exposure->minimum, max,
 					 sc230ai->exposure->step,
@@ -1469,8 +1530,7 @@
 					 (ctrl->val + sc230ai->cur_mode->height)
 					 & 0xff);
 		sc230ai->cur_vts = ctrl->val + sc230ai->cur_mode->height;
-		if (sc230ai->cur_vts != sc230ai->cur_mode->vts_def)
-			sc230ai_modify_fps_info(sc230ai);
+		sc230ai_modify_fps_info(sc230ai);
 		break;
 	case V4L2_CID_TEST_PATTERN:
 		ret = sc230ai_enable_test_pattern(sc230ai, ctrl->val);
@@ -1546,7 +1606,7 @@
 					    V4L2_CID_VBLANK, vblank_def,
 					    SC230AI_VTS_MAX - mode->height,
 					    1, vblank_def);
-	exposure_max = SC230AI_EXPOSURE_LIN_MAX;
+	exposure_max = mode->vts_def - 5;
 	sc230ai->exposure = v4l2_ctrl_new_std(handler, &sc230ai_ctrl_ops,
 					      V4L2_CID_EXPOSURE, SC230AI_EXPOSURE_MIN,
 					      exposure_max, SC230AI_EXPOSURE_STEP,
@@ -1629,6 +1689,7 @@
 	char facing[2];
 	int ret;
 	u32 i, hdr_mode = 0;
+	const char *sync_mode_name = NULL;
 
 	dev_info(dev, "driver version: %02x.%02x.%02x",
 		 DRIVER_VERSION >> 16,
@@ -1652,6 +1713,25 @@
 		dev_err(dev, "could not get module information!\n");
 		return -EINVAL;
 	}
+
+	ret = of_property_read_string(node, RKMODULE_CAMERA_SYNC_MODE,
+				      &sync_mode_name);
+	if (ret) {
+		sc230ai->sync_mode = NO_SYNC_MODE;
+		dev_err(dev, "could not get sync mode!\n");
+	} else {
+		if (strcmp(sync_mode_name, RKMODULE_EXTERNAL_MASTER_MODE) == 0) {
+			sc230ai->sync_mode = EXTERNAL_MASTER_MODE;
+			dev_info(dev, "external master mode\n");
+		} else if (strcmp(sync_mode_name, RKMODULE_INTERNAL_MASTER_MODE) == 0) {
+			sc230ai->sync_mode = INTERNAL_MASTER_MODE;
+			dev_info(dev, "internal master mode\n");
+		} else if (strcmp(sync_mode_name, RKMODULE_SLAVE_MODE) == 0) {
+			sc230ai->sync_mode = SLAVE_MODE;
+			dev_info(dev, "slave mode\n");
+		}
+	}
+
 	sc230ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP);
 	sc230ai->client = client;
 	for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {

--
Gitblit v1.6.2