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/sc4238.c |   87 +++++++++++++++++++++++++++++++++++--------
 1 files changed, 71 insertions(+), 16 deletions(-)

diff --git a/kernel/drivers/media/i2c/sc4238.c b/kernel/drivers/media/i2c/sc4238.c
index ebb973c..5bbf26d 100644
--- a/kernel/drivers/media/i2c/sc4238.c
+++ b/kernel/drivers/media/i2c/sc4238.c
@@ -114,14 +114,6 @@
 #define MIRROR_BIT_MASK			(BIT(1) | BIT(2))
 #define FLIP_BIT_MASK			(BIT(6) | BIT(5))
 
-enum sc4238_max_pad {
-	PAD0,
-	PAD1,
-	PAD2,
-	PAD3,
-	PAD_MAX,
-};
-
 struct regval {
 	u16 addr;
 	u8 val;
@@ -167,6 +159,7 @@
 	struct v4l2_ctrl	*h_flip;
 	struct v4l2_ctrl	*v_flip;
 	struct mutex		mutex;
+	struct v4l2_fract	cur_fps;
 	bool			streaming;
 	bool			power_on;
 	const struct sc4238_mode *cur_mode;
@@ -1581,6 +1574,8 @@
 					 mode->pixel_rate);
 		__v4l2_ctrl_s_ctrl(sc4238->link_freq,
 					 mode->link_freq);
+		sc4238->cur_fps = mode->max_fps;
+		sc4238->cur_vts = mode->vts_def;
 	}
 
 	mutex_unlock(&sc4238->mutex);
@@ -1674,14 +1669,15 @@
 	struct sc4238 *sc4238 = to_sc4238(sd);
 	const struct sc4238_mode *mode = sc4238->cur_mode;
 
-	mutex_lock(&sc4238->mutex);
-	fi->interval = mode->max_fps;
-	mutex_unlock(&sc4238->mutex);
+	if (sc4238->streaming)
+		fi->interval = sc4238->cur_fps;
+	else
+		fi->interval = mode->max_fps;
 
 	return 0;
 }
 
-static int sc4238_g_mbus_config(struct v4l2_subdev *sd,
+static int sc4238_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
 				struct v4l2_mbus_config *config)
 {
 	struct sc4238 *sc4238 = to_sc4238(sd);
@@ -1698,7 +1694,7 @@
 		V4L2_MBUS_CSI2_CONTINUOUS_CLOCK |
 		V4L2_MBUS_CSI2_CHANNEL_1;
 
-	config->type = V4L2_MBUS_CSI2;
+	config->type = V4L2_MBUS_CSI2_DPHY;
 	config->flags = val;
 
 	return 0;
@@ -1884,10 +1880,22 @@
 	return ret;
 }
 
+static int sc4238_get_channel_info(struct sc4238 *sc4238, struct rkmodule_channel_info *ch_info)
+{
+	if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
+		return -EINVAL;
+	ch_info->vc = sc4238->cur_mode->vc[ch_info->index];
+	ch_info->width = sc4238->cur_mode->width;
+	ch_info->height = sc4238->cur_mode->height;
+	ch_info->bus_fmt = sc4238->cur_mode->bus_fmt;
+	return 0;
+}
+
 static long sc4238_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
 	struct sc4238 *sc4238 = to_sc4238(sd);
 	struct rkmodule_hdr_cfg *hdr_cfg;
+	struct rkmodule_channel_info *ch_info;
 	long ret = 0;
 	u32 i, h, w;
 	u32 stream = 0;
@@ -1923,6 +1931,8 @@
 			__v4l2_ctrl_modify_range(sc4238->vblank, h,
 				SC4238_VTS_MAX - sc4238->cur_mode->height,
 				1, h);
+			sc4238->cur_fps = sc4238->cur_mode->max_fps;
+			sc4238->cur_vts = sc4238->cur_mode->vts_def;
 			dev_info(&sc4238->client->dev,
 				"sensor mode: %d\n",
 				sc4238->cur_mode->hdr_mode);
@@ -1947,6 +1957,10 @@
 			ret = sc4238_write_reg(sc4238->client, SC4238_REG_CTRL_MODE,
 				SC4238_REG_VALUE_08BIT, SC4238_MODE_SW_STANDBY);
 		break;
+	case RKMODULE_GET_CHANNEL_INFO:
+		ch_info = (struct rkmodule_channel_info *)arg;
+		ret = sc4238_get_channel_info(sc4238, ch_info);
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
@@ -1964,6 +1978,7 @@
 	struct rkmodule_awb_cfg *cfg;
 	struct rkmodule_hdr_cfg *hdr;
 	struct preisp_hdrae_exp_s *hdrae;
+	struct rkmodule_channel_info *ch_info;
 	long ret;
 	u32 stream = 0;
 
@@ -1976,8 +1991,11 @@
 		}
 
 		ret = sc4238_ioctl(sd, cmd, inf);
-		if (!ret)
+		if (!ret) {
 			ret = copy_to_user(up, inf, sizeof(*inf));
+			if (ret)
+				ret = -EFAULT;
+		}
 		kfree(inf);
 		break;
 	case RKMODULE_AWB_CFG:
@@ -1990,6 +2008,8 @@
 		ret = copy_from_user(cfg, up, sizeof(*cfg));
 		if (!ret)
 			ret = sc4238_ioctl(sd, cmd, cfg);
+		else
+			ret = -EFAULT;
 		kfree(cfg);
 		break;
 	case RKMODULE_GET_HDR_CFG:
@@ -2000,8 +2020,11 @@
 		}
 
 		ret = sc4238_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:
@@ -2014,6 +2037,8 @@
 		ret = copy_from_user(hdr, up, sizeof(*hdr));
 		if (!ret)
 			ret = sc4238_ioctl(sd, cmd, hdr);
+		else
+			ret = -EFAULT;
 		kfree(hdr);
 		break;
 	case PREISP_CMD_SET_HDRAE_EXP:
@@ -2026,12 +2051,31 @@
 		ret = copy_from_user(hdrae, up, sizeof(*hdrae));
 		if (!ret)
 			ret = sc4238_ioctl(sd, cmd, hdrae);
+		else
+			ret = -EFAULT;
 		kfree(hdrae);
 		break;
 	case RKMODULE_SET_QUICK_STREAM:
 		ret = copy_from_user(&stream, up, sizeof(u32));
 		if (!ret)
 			ret = sc4238_ioctl(sd, cmd, &stream);
+		else
+			ret = -EFAULT;
+		break;
+	case RKMODULE_GET_CHANNEL_INFO:
+		ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
+		if (!ch_info) {
+			ret = -ENOMEM;
+			return ret;
+		}
+
+		ret = sc4238_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;
@@ -2345,7 +2389,6 @@
 static const struct v4l2_subdev_video_ops sc4238_video_ops = {
 	.s_stream = sc4238_s_stream,
 	.g_frame_interval = sc4238_g_frame_interval,
-	.g_mbus_config = sc4238_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops sc4238_pad_ops = {
@@ -2354,6 +2397,7 @@
 	.enum_frame_interval = sc4238_enum_frame_interval,
 	.get_fmt = sc4238_get_fmt,
 	.set_fmt = sc4238_set_fmt,
+	.get_mbus_config = sc4238_g_mbus_config,
 };
 
 static const struct v4l2_subdev_ops sc4238_subdev_ops = {
@@ -2361,6 +2405,14 @@
 	.video	= &sc4238_video_ops,
 	.pad	= &sc4238_pad_ops,
 };
+
+static void sc4238_modify_fps_info(struct sc4238 *sc4238)
+{
+	const struct sc4238_mode *mode = sc4238->cur_mode;
+
+	sc4238->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def /
+				      sc4238->cur_vts;
+}
 
 static int sc4238_set_ctrl(struct v4l2_ctrl *ctrl)
 {
@@ -2432,6 +2484,7 @@
 					ctrl->val + sc4238->cur_mode->height);
 		if (ret == 0)
 			sc4238->cur_vts = ctrl->val + sc4238->cur_mode->height;
+		sc4238_modify_fps_info(sc4238);
 		dev_dbg(&client->dev, "set vblank 0x%x\n",
 			ctrl->val);
 		break;
@@ -2565,6 +2618,8 @@
 
 	sc4238->subdev.ctrl_handler = handler;
 	sc4238->has_init_exp = false;
+	sc4238->cur_fps = mode->max_fps;
+	sc4238->cur_vts = mode->vts_def;
 
 	return 0;
 

--
Gitblit v1.6.2