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/sc031gs.c |   76 +++++++++++++++++++++++++++++---------
 1 files changed, 58 insertions(+), 18 deletions(-)

diff --git a/kernel/drivers/media/i2c/sc031gs.c b/kernel/drivers/media/i2c/sc031gs.c
index be1602b..7415d82 100644
--- a/kernel/drivers/media/i2c/sc031gs.c
+++ b/kernel/drivers/media/i2c/sc031gs.c
@@ -50,8 +50,8 @@
 
 #define SC031GS_REG_COARSE_AGAIN		0x3e08
 #define SC031GS_REG_FINE_AGAIN          0x3e09
-#define	ANALOG_GAIN_MIN			0x01
-#define	ANALOG_GAIN_MAX			0xF8
+#define	ANALOG_GAIN_MIN			0x10
+#define	ANALOG_GAIN_MAX			0x7c0   // 124x
 #define	ANALOG_GAIN_STEP		1
 #define	ANALOG_GAIN_DEFAULT		0x1f
 
@@ -117,6 +117,8 @@
 	struct v4l2_ctrl	*vblank;
 	struct v4l2_ctrl	*test_pattern;
 	struct mutex		mutex;
+	struct v4l2_fract	cur_fps;
+	u32			cur_vts;
 	bool			streaming;
 	bool			power_on;
 	const struct sc031gs_mode *cur_mode;
@@ -296,7 +298,7 @@
 	{0x3d08, 0x01},
 	{0x3e01, 0x14},
 	{0x3e02, 0x80},
-	{0x3e06, 0x0c},
+	{0x3e06, 0x00},
 	{0x4500, 0x59},
 	{0x4501, 0xc4},
 	{0x4603, 0x00},
@@ -477,6 +479,8 @@
 		__v4l2_ctrl_modify_range(sc031gs->vblank, vblank_def,
 					 SC031GS_VTS_MAX - mode->height,
 					 1, vblank_def);
+		sc031gs->cur_fps = mode->max_fps;
+		sc031gs->cur_vts = mode->vts_def;
 	}
 
 	mutex_unlock(&sc031gs->mutex);
@@ -611,7 +615,10 @@
 
 		ret = sc031gs_ioctl(sd, cmd, inf);
 		if (!ret)
-			ret = copy_to_user(up, inf, sizeof(*inf));
+			if (copy_to_user(up, inf, sizeof(*inf))) {
+				kfree(inf);
+				return -EFAULT;
+			}
 		kfree(inf);
 		break;
 	case RKMODULE_AWB_CFG:
@@ -620,16 +627,17 @@
 			ret = -ENOMEM;
 			return ret;
 		}
-
-		ret = copy_from_user(cfg, up, sizeof(*cfg));
-		if (!ret)
-			ret = sc031gs_ioctl(sd, cmd, cfg);
+		if (copy_from_user(cfg, up, sizeof(*cfg))) {
+			kfree(cfg);
+			return -EFAULT;
+		}
+		ret = sc031gs_ioctl(sd, cmd, cfg);
 		kfree(cfg);
 		break;
 	case RKMODULE_SET_QUICK_STREAM:
-		ret = copy_from_user(&stream, up, sizeof(u32));
-		if (!ret)
-			ret = sc031gs_ioctl(sd, cmd, &stream);
+		if (copy_from_user(&stream, up, sizeof(u32)))
+			return -EFAULT;
+		ret = sc031gs_ioctl(sd, cmd, &stream);
 		break;
 	default:
 		ret = -ENOIOCTLCMD;
@@ -643,7 +651,7 @@
 static int sc031gs_set_ctrl_gain(struct sc031gs *sc031gs, u32 a_gain)
 {
 	int ret = 0;
-	u32 coarse_again, fine_again, fine_again_reg, coarse_again_reg;
+	u32 coarse_again, fine_again, fine_again_reg, coarse_again_reg, digital_gain_reg;
 
 		if (a_gain < 0x20) { /*1x ~ 2x*/
 			fine_again = a_gain - 16;
@@ -651,24 +659,40 @@
 			fine_again_reg = ((0x01 << 4) & 0x10) |
 				(fine_again & 0x0f);
 			coarse_again_reg = coarse_again  & 0x1F;
+			digital_gain_reg = 0x80;
 		} else if (a_gain < 0x40) { /*2x ~ 4x*/
 			fine_again = (a_gain >> 1) - 16;
 			coarse_again = 0x7;
 			fine_again_reg = ((0x01 << 4) & 0x10) |
 				(fine_again & 0x0f);
 			coarse_again_reg = coarse_again  & 0x1F;
+			digital_gain_reg = 0x80;
 		} else if (a_gain < 0x80) { /*4x ~ 8x*/
 			fine_again = (a_gain >> 2) - 16;
 			coarse_again = 0xf;
 			fine_again_reg = ((0x01 << 4) & 0x10) |
 				(fine_again & 0x0f);
 			coarse_again_reg = coarse_again  & 0x1F;
-		} else { /*8x ~ 16x*/
+			digital_gain_reg = 0x80;
+		} else if (a_gain < 0x100) { /*8x ~ 16x*/
 			fine_again = (a_gain >> 3) - 16;
 			coarse_again = 0x1f;
 			fine_again_reg = ((0x01 << 4) & 0x10) |
 				(fine_again & 0x0f);
 			coarse_again_reg = coarse_again  & 0x1F;
+			digital_gain_reg = 0x80;
+		} else if (a_gain < 0x200) { /*16x ~ 32x*/
+			fine_again_reg = 0x1f;
+			coarse_again_reg = 0x1f;
+			digital_gain_reg = (a_gain * 0x80 / 0x100) & 0xf8;
+		} else if (a_gain < 0x400) { /*32x ~ 64x*/
+			fine_again_reg = 0x1f;
+			coarse_again_reg = 0x1f;
+			digital_gain_reg = (a_gain * 0x80 / 0x200) & 0x1f8;
+		} else { /*64x ~ 124*/
+			fine_again_reg = 0x1f;
+			coarse_again_reg = 0x1f;
+			digital_gain_reg = (a_gain * 0x80 / 0x400) & 0x3f8;
 		}
 
 		if (a_gain < 0x20) {
@@ -690,6 +714,9 @@
 			SC031GS_REG_FINE_AGAIN,
 			SC031GS_REG_VALUE_08BIT,
 			fine_again_reg);
+
+		ret |= sc031gs_write_reg(sc031gs->client, 0x3e06,
+						SC031GS_REG_VALUE_16BIT, digital_gain_reg);
 
 	return ret;
 }
@@ -765,9 +792,10 @@
 	struct sc031gs *sc031gs = to_sc031gs(sd);
 	const struct sc031gs_mode *mode = sc031gs->cur_mode;
 
-	mutex_lock(&sc031gs->mutex);
-	fi->interval = mode->max_fps;
-	mutex_unlock(&sc031gs->mutex);
+	if (sc031gs->streaming)
+		fi->interval = sc031gs->cur_fps;
+	else
+		fi->interval = mode->max_fps;
 
 	return 0;
 }
@@ -917,8 +945,7 @@
 	if (fie->index >= ARRAY_SIZE(supported_modes))
 		return -EINVAL;
 
-	if (fie->code != PIX_FORMAT)
-		return -EINVAL;
+	fie->code = PIX_FORMAT;
 
 	fie->width = supported_modes[fie->index].width;
 	fie->height = supported_modes[fie->index].height;
@@ -967,6 +994,14 @@
 	.pad	= &sc031gs_pad_ops,
 };
 
+static void sc031gs_modify_fps_info(struct sc031gs *sc031gs)
+{
+	const struct sc031gs_mode *mode = sc031gs->cur_mode;
+
+	sc031gs->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def /
+				       sc031gs->cur_vts;
+}
+
 static int sc031gs_set_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct sc031gs *sc031gs = container_of(ctrl->handler,
@@ -1003,6 +1038,9 @@
 		ret = sc031gs_write_reg(sc031gs->client, SC031GS_REG_VTS,
 				       SC031GS_REG_VALUE_16BIT,
 				       ctrl->val + sc031gs->cur_mode->height);
+		if (!ret)
+			sc031gs->cur_vts = ctrl->val + sc031gs->cur_mode->height;
+		sc031gs_modify_fps_info(sc031gs);
 		break;
 	case V4L2_CID_TEST_PATTERN:
 		ret = sc031gs_enable_test_pattern(sc031gs, ctrl->val);
@@ -1053,6 +1091,7 @@
 		sc031gs->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
 	vblank_def = mode->vts_def - mode->height;
+	sc031gs->cur_vts = mode->vts_def;
 	sc031gs->vblank = v4l2_ctrl_new_std(handler, &sc031gs_ctrl_ops,
 				V4L2_CID_VBLANK, vblank_def,
 				SC031GS_VTS_MAX - mode->height,
@@ -1082,6 +1121,7 @@
 	}
 
 	sc031gs->subdev.ctrl_handler = handler;
+	sc031gs->cur_fps = mode->max_fps;
 
 	return 0;
 

--
Gitblit v1.6.2