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/sc500ai.c |  122 ++++++++++++++++++++++++++--------------
 1 files changed, 80 insertions(+), 42 deletions(-)

diff --git a/kernel/drivers/media/i2c/sc500ai.c b/kernel/drivers/media/i2c/sc500ai.c
index 63bc371..f5a2042 100644
--- a/kernel/drivers/media/i2c/sc500ai.c
+++ b/kernel/drivers/media/i2c/sc500ai.c
@@ -123,14 +123,6 @@
 
 #define sc500ai_NUM_SUPPLIES ARRAY_SIZE(sc500ai_supply_names)
 
-enum sc500ai_max_pad {
-	PAD0, /* link to isp */
-	PAD1, /* link to csi wr0 | hdr x2:L x3:M */
-	PAD2, /* link to csi wr1 | hdr      x3:L */
-	PAD3, /* link to csi wr2 | hdr x2:M x3:S */
-	PAD_MAX,
-};
-
 struct regval {
 	u16 addr;
 	u8 val;
@@ -173,6 +165,7 @@
 	struct v4l2_ctrl	*pixel_rate;
 	struct v4l2_ctrl	*link_freq;
 	struct mutex		mutex;
+	struct v4l2_fract	cur_fps;
 	bool			streaming;
 	bool			power_on;
 	const struct sc500ai_mode *cur_mode;
@@ -277,6 +270,7 @@
 	{0x3e17, 0x80},
 	{0x4500, 0x88},
 	{0x4509, 0x20},
+	{0x4800, 0x04},
 	{0x5799, 0x00},
 	{0x59e0, 0x60},
 	{0x59e1, 0x08},
@@ -596,6 +590,8 @@
 		__v4l2_ctrl_s_ctrl(sc500ai->link_freq, mode->mipi_freq_idx);
 		pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * SC500AI_LANES;
 		__v4l2_ctrl_s_ctrl_int64(sc500ai->pixel_rate, pixel_rate);
+		sc500ai->cur_fps = mode->max_fps;
+		sc500ai->cur_vts = mode->vts_def;
 	}
 
 	mutex_unlock(&sc500ai->mutex);
@@ -671,14 +667,15 @@
 	struct sc500ai *sc500ai = to_sc500ai(sd);
 	const struct sc500ai_mode *mode = sc500ai->cur_mode;
 
-	mutex_lock(&sc500ai->mutex);
-	fi->interval = mode->max_fps;
-	mutex_unlock(&sc500ai->mutex);
+	if (sc500ai->streaming)
+		fi->interval = sc500ai->cur_fps;
+	else
+		fi->interval = mode->max_fps;
 
 	return 0;
 }
 
-static int sc500ai_g_mbus_config(struct v4l2_subdev *sd,
+static int sc500ai_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
                                  struct v4l2_mbus_config *config)
 {
 	struct sc500ai *sc500ai = to_sc500ai(sd);
@@ -692,7 +689,7 @@
 	if (mode->hdr_mode == HDR_X3)
 		val |= V4L2_MBUS_CSI2_CHANNEL_2;
 
-	config->type = V4L2_MBUS_CSI2;
+	config->type = V4L2_MBUS_CSI2_DPHY;
 	config->flags = val;
 
 	return 0;
@@ -911,11 +908,23 @@
 	return ret;
 }
 
+static int sc500ai_get_channel_info(struct sc500ai *sc500ai, struct rkmodule_channel_info *ch_info)
+{
+	if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
+		return -EINVAL;
+	ch_info->vc = sc500ai->cur_mode->vc[ch_info->index];
+	ch_info->width = sc500ai->cur_mode->width;
+	ch_info->height = sc500ai->cur_mode->height;
+	ch_info->bus_fmt = sc500ai->cur_mode->bus_fmt;
+	return 0;
+}
+
 static long sc500ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
 	struct sc500ai *sc500ai = to_sc500ai(sd);
 	struct rkmodule_hdr_cfg *hdr;
 	const struct sc500ai_mode *mode;
+	struct rkmodule_channel_info *ch_info;
 
 	long ret = 0;
 	u32 i, h, w;
@@ -959,7 +968,8 @@
 			__v4l2_ctrl_s_ctrl(sc500ai->link_freq, mode->mipi_freq_idx);
 			pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * SC500AI_LANES;
 			__v4l2_ctrl_s_ctrl_int64(sc500ai->pixel_rate, pixel_rate);
-
+			sc500ai->cur_fps = mode->max_fps;
+			sc500ai->cur_vts = mode->vts_def;
 			dev_info(&sc500ai->client->dev, "sensor mode: %d\n", sc500ai->cur_mode->hdr_mode);
 		}
 		break;
@@ -976,6 +986,10 @@
 			ret = sc500ai_write_reg(sc500ai->client, SC500AI_REG_CTRL_MODE,
 			                        SC500AI_REG_VALUE_08BIT, SC500AI_MODE_SW_STANDBY);
 		break;
+	case RKMODULE_GET_CHANNEL_INFO:
+		ch_info = (struct rkmodule_channel_info *)arg;
+		ret = sc500ai_get_channel_info(sc500ai, ch_info);
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
@@ -990,9 +1004,9 @@
 {
 	void __user *up = compat_ptr(arg);
 	struct rkmodule_inf *inf;
-	struct rkmodule_awb_cfg *cfg;
 	struct rkmodule_hdr_cfg *hdr;
 	struct preisp_hdrae_exp_s *hdrae;
+	struct rkmodule_channel_info *ch_info;
 	long ret = 0;
 	u32 stream = 0;
 
@@ -1005,21 +1019,12 @@
 		}
 
 		ret = sc500ai_ioctl(sd, cmd, inf);
-		if (!ret)
+		if (!ret) {
 			ret = copy_to_user(up, inf, sizeof(*inf));
-		kfree(inf);
-		break;
-	case RKMODULE_AWB_CFG:
-		cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
-		if (!cfg) {
-			ret = -ENOMEM;
-			return ret;
+			if (ret)
+				ret = -EFAULT;
 		}
-
-		ret = copy_from_user(cfg, up, sizeof(*cfg));
-		if (!ret)
-			ret = sc500ai_ioctl(sd, cmd, cfg);
-		kfree(cfg);
+		kfree(inf);
 		break;
 	case RKMODULE_GET_HDR_CFG:
 		hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
@@ -1029,8 +1034,11 @@
 		}
 
 		ret = sc500ai_ioctl(sd, cmd, hdr);
-		if (!ret)
+		if (!ret) {
 			ret = copy_to_user(up, hdr, sizeof(*hdr));
+			if (ret)
+				ret = -EFAULT;
+		}
 		kfree(hdr);
 		break;
 	case RKMODULE_SET_HDR_CFG:
@@ -1040,9 +1048,10 @@
 			return ret;
 		}
 
-		ret = copy_from_user(hdr, up, sizeof(*hdr));
-		if (!ret)
-			ret = sc500ai_ioctl(sd, cmd, hdr);
+		if (copy_from_user(hdr, up, sizeof(*hdr)))
+			return -EFAULT;
+
+		ret = sc500ai_ioctl(sd, cmd, hdr);
 		kfree(hdr);
 		break;
 	case PREISP_CMD_SET_HDRAE_EXP:
@@ -1052,15 +1061,32 @@
 			return ret;
 		}
 
-		ret = copy_from_user(hdrae, up, sizeof(*hdrae));
-		if (!ret)
-			ret = sc500ai_ioctl(sd, cmd, hdrae);
+		if (copy_from_user(hdrae, up, sizeof(*hdrae)))
+			return -EFAULT;
+
+		ret = sc500ai_ioctl(sd, cmd, hdrae);
 		kfree(hdrae);
 		break;
 	case RKMODULE_SET_QUICK_STREAM:
-		ret = copy_from_user(&stream, up, sizeof(u32));
-		if (!ret)
-			ret = sc500ai_ioctl(sd, cmd, &stream);
+		if (copy_from_user(&stream, up, sizeof(u32)))
+			return -EFAULT;
+
+		ret = sc500ai_ioctl(sd, cmd, &stream);
+		break;
+	case RKMODULE_GET_CHANNEL_INFO:
+		ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
+		if (!ch_info) {
+			ret = -ENOMEM;
+			return ret;
+		}
+
+		ret = sc500ai_ioctl(sd, cmd, ch_info);
+		if (!ret) {
+			ret = copy_to_user(up, ch_info, sizeof(*ch_info));
+			if (ret)
+				ret = -EFAULT;
+		}
+		kfree(ch_info);
 		break;
 	default:
 		ret = -ENOIOCTLCMD;
@@ -1348,7 +1374,6 @@
 static const struct v4l2_subdev_video_ops sc500ai_video_ops = {
 	.s_stream = sc500ai_s_stream,
 	.g_frame_interval = sc500ai_g_frame_interval,
-	.g_mbus_config = sc500ai_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops sc500ai_pad_ops = {
@@ -1358,6 +1383,7 @@
 	.get_fmt = sc500ai_get_fmt,
 	.set_fmt = sc500ai_set_fmt,
 	.get_selection = sc500ai_get_selection,
+	.get_mbus_config = sc500ai_g_mbus_config,
 };
 
 static const struct v4l2_subdev_ops sc500ai_subdev_ops = {
@@ -1365,6 +1391,14 @@
 	.video	= &sc500ai_video_ops,
 	.pad	= &sc500ai_pad_ops,
 };
+
+static void sc500ai_modify_fps_info(struct sc500ai *sc500ai)
+{
+	const struct sc500ai_mode *mode = sc500ai->cur_mode;
+
+	sc500ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def /
+				       sc500ai->cur_vts;
+}
 
 static int sc500ai_set_ctrl(struct v4l2_ctrl *ctrl)
 {
@@ -1399,7 +1433,7 @@
 	switch (ctrl->id) {
 	case V4L2_CID_EXPOSURE:
 		if (sc500ai->cur_mode->hdr_mode != NO_HDR)
-			return ret;
+			goto ctrl_end;
 		val = ctrl->val << 1;
 		ret = sc500ai_write_reg(sc500ai->client,
 					SC500AI_REG_EXPOSURE_H,
@@ -1418,7 +1452,7 @@
 		break;
 	case V4L2_CID_ANALOGUE_GAIN:
 		if (sc500ai->cur_mode->hdr_mode != NO_HDR)
-			return ret;
+			goto ctrl_end;
 
 		sc500ai_get_gain_reg(ctrl->val, &again, &again_fine, &dgain, &dgain_fine);
 		ret = sc500ai_write_reg(sc500ai->client,
@@ -1453,7 +1487,9 @@
 					 SC500AI_REG_VTS_L,
 					 SC500AI_REG_VALUE_08BIT,
 					 vts & 0xff);
-		sc500ai->cur_vts = vts;
+		if (!ret)
+			sc500ai->cur_vts = vts;
+		sc500ai_modify_fps_info(sc500ai);
 		break;
 	case V4L2_CID_HFLIP:
 		ret = sc500ai_read_reg(sc500ai->client, SC500AI_FLIP_MIRROR_REG,
@@ -1520,6 +1556,7 @@
 		break;
 	}
 
+ctrl_end:
 	pm_runtime_put(&client->dev);
 
 	return ret;
@@ -1565,6 +1602,7 @@
 
 	vblank_def = mode->vts_def - mode->height;
 	sc500ai->cur_vts = mode->vts_def;
+	sc500ai->cur_fps = mode->max_fps;
 	sc500ai->vblank = v4l2_ctrl_new_std(handler, &sc500ai_ctrl_ops,
 	                                    V4L2_CID_VBLANK, vblank_def,
 	                                    SC500AI_VTS_MAX - mode->height,

--
Gitblit v1.6.2