From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 03 Jan 2024 09:43:39 +0000
Subject: [PATCH] update kernel to 5.10.198

---
 kernel/drivers/media/i2c/sc200ai.c |  213 +++++++++++++++++++++++++---------------------------
 1 files changed, 102 insertions(+), 111 deletions(-)

diff --git a/kernel/drivers/media/i2c/sc200ai.c b/kernel/drivers/media/i2c/sc200ai.c
index daa7e4e..44c7156 100644
--- a/kernel/drivers/media/i2c/sc200ai.c
+++ b/kernel/drivers/media/i2c/sc200ai.c
@@ -11,8 +11,11 @@
  * V0.0X01.0X05 add quick stream on/off.
  * V0.0X01.0X06 fix set vflip/hflip failed bug.
  * V0.0X01.0X07
- * 1. fix set double times exposue value failed issue.
- * 2. add some debug info.
+ *	1. fix set double times exposue value failed issue.
+ *	2. add some debug info.
+ * V0.0X01.0X08
+ *	1. add support wakeup & sleep for aov function
+ *	2. using 60fps output default
  */
 
 #include <linux/clk.h>
@@ -34,8 +37,10 @@
 #include <media/v4l2-subdev.h>
 #include <linux/pinctrl/consumer.h>
 #include "../platform/rockchip/isp/rkisp_tb_helper.h"
+#include "cam-tb-setup.h"
+#include "cam-sleep-wakeup.h"
 
-#define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x07)
+#define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x08)
 
 #ifndef V4L2_CID_DIGITAL_GAIN
 #define V4L2_CID_DIGITAL_GAIN		V4L2_CID_GAIN
@@ -179,6 +184,7 @@
 	bool			is_thunderboot;
 	bool			is_first_streamoff;
 	struct preisp_hdrae_exp_s init_hdrae_exp;
+	struct cam_sw_info	*cam_sw_inf;
 };
 
 #define to_sc200ai(sd) container_of(sd, struct sc200ai, subdev)
@@ -611,20 +617,6 @@
 		.height = 1080,
 		.max_fps = {
 			.numerator = 10000,
-			.denominator = 300000,
-		},
-		.exp_def = 0x0080,
-		.hts_def = 0x44C * 2,
-		.vts_def = 0x0465,
-		.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
-		.reg_list = sc200ai_linear_10_1920x1080_30fps_regs,
-		.hdr_mode = NO_HDR,
-		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
-	}, {
-		.width = 1920,
-		.height = 1080,
-		.max_fps = {
-			.numerator = 10000,
 			.denominator = 600000,
 		},
 		.exp_def = 0x0080,
@@ -634,7 +626,23 @@
 		.reg_list = sc200ai_linear_10_1920x1080_60fps_regs,
 		.hdr_mode = NO_HDR,
 		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
-	}, {
+	},
+	{
+		.width = 1920,
+		.height = 1080,
+		.max_fps = {
+			.numerator = 10000,
+			.denominator = 300000,
+		},
+		.exp_def = 0x0080,
+		.hts_def = 0x44C * 2,
+		.vts_def = 0x0465,
+		.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
+		.reg_list = sc200ai_linear_10_1920x1080_30fps_regs,
+		.hdr_mode = NO_HDR,
+		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
+	},
+	{
 		.width = 1920,
 		.height = 1080,
 		.max_fps = {
@@ -1215,17 +1223,23 @@
 		break;
 	case PREISP_CMD_SET_HDRAE_EXP:
 		sc200ai_set_hdrae(sc200ai, arg);
+		if (sc200ai->cam_sw_inf)
+			memcpy(&sc200ai->cam_sw_inf->hdr_ae, (struct preisp_hdrae_exp_s *)(arg),
+				sizeof(struct preisp_hdrae_exp_s));
 		break;
 	case RKMODULE_SET_QUICK_STREAM:
 
 		stream = *((u32 *)arg);
 
-		if (stream)
+		if (stream) {
+			gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 1);
 			ret = sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE,
 				 SC200AI_REG_VALUE_08BIT, SC200AI_MODE_STREAMING);
-		else
+		} else {
 			ret = sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE,
 				 SC200AI_REG_VALUE_08BIT, SC200AI_MODE_SW_STANDBY);
+			gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 0);
+		}
 		break;
 	case RKMODULE_GET_CHANNEL_INFO:
 		ch_info = (struct rkmodule_channel_info *)arg;
@@ -1512,6 +1526,9 @@
 		dev_err(dev, "Failed to enable xvclk\n");
 		return ret;
 	}
+
+	cam_sw_regulator_bulk_init(sc200ai->cam_sw_inf, SC200AI_NUM_SUPPLIES, sc200ai->supplies);
+
 	if (sc200ai->is_thunderboot)
 		return 0;
 
@@ -1576,6 +1593,51 @@
 	regulator_bulk_disable(SC200AI_NUM_SUPPLIES, sc200ai->supplies);
 }
 
+#if IS_REACHABLE(CONFIG_VIDEO_CAM_SLEEP_WAKEUP)
+static int __maybe_unused sc200ai_resume(struct device *dev)
+{
+	int ret;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct sc200ai *sc200ai = to_sc200ai(sd);
+
+	cam_sw_prepare_wakeup(sc200ai->cam_sw_inf, dev);
+
+	usleep_range(4000, 5000);
+	cam_sw_write_array(sc200ai->cam_sw_inf);
+
+	if (__v4l2_ctrl_handler_setup(&sc200ai->ctrl_handler))
+		dev_err(dev, "__v4l2_ctrl_handler_setup fail!");
+
+	if (sc200ai->has_init_exp && sc200ai->cur_mode != NO_HDR) {	// hdr mode
+		ret = sc200ai_ioctl(&sc200ai->subdev, PREISP_CMD_SET_HDRAE_EXP,
+				    &sc200ai->cam_sw_inf->hdr_ae);
+		if (ret) {
+			dev_err(&sc200ai->client->dev, "set exp fail in hdr mode\n");
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static int __maybe_unused sc200ai_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct sc200ai *sc200ai = to_sc200ai(sd);
+
+	cam_sw_write_array_cb_init(sc200ai->cam_sw_inf, client,
+				   (void *)sc200ai->cur_mode->reg_list,
+				   (sensor_write_array)sc200ai_write_array);
+	cam_sw_prepare_sleep(sc200ai->cam_sw_inf);
+
+	return 0;
+}
+#else
+#define sc200ai_resume NULL
+#define sc200ai_suspend NULL
+#endif
+
 static int sc200ai_runtime_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -1636,6 +1698,7 @@
 static const struct dev_pm_ops sc200ai_pm_ops = {
 	SET_RUNTIME_PM_OPS(sc200ai_runtime_suspend,
 			   sc200ai_runtime_resume, NULL)
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(sc200ai_suspend, sc200ai_resume)
 };
 
 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
@@ -1889,109 +1952,28 @@
 }
 
 #ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
-static u32 rk_cam_hdr;
-static u32 rk_cam_w;
-static u32 rk_cam_h;
-static u32 rk_cam_fps;
-
-static int __init __maybe_unused rk_cam_hdr_setup(char *str)
-{
-	int ret = 0;
-	unsigned long val = 0;
-
-	ret = kstrtoul(str, 0, &val);
-	if (!ret)
-		rk_cam_hdr = (u32)val;
-	else
-		pr_err("get rk_cam_hdr fail\n");
-	return 1;
-}
-
-static int __init __maybe_unused rk_cam_w_setup(char *str)
-{
-	int ret = 0;
-	unsigned long val = 0;
-
-	ret = kstrtoul(str, 0, &val);
-	if (!ret)
-		rk_cam_w = (u32)val;
-	else
-		pr_err("get rk_cam_w fail\n");
-	return 1;
-}
-
-static int __init __maybe_unused rk_cam_h_setup(char *str)
-{
-	int ret = 0;
-	unsigned long val = 0;
-
-	ret = kstrtoul(str, 0, &val);
-	if (!ret)
-		rk_cam_h = (u32)val;
-	else
-		pr_err("get rk_cam_h fail\n");
-	return 1;
-}
-
-static int __init __maybe_unused rk_cam_fps_setup(char *str)
-{
-	int ret = 0;
-	unsigned long val = 0;
-
-	ret = kstrtoul(str, 0, &val);
-	if (!ret)
-		rk_cam_fps = (u32)val;
-	else
-		pr_err("get rk_cam_fps fail\n");
-	return 1;
-}
-
-__setup("rk_cam_hdr=", rk_cam_hdr_setup);
-__setup("rk_cam_w=", rk_cam_w_setup);
-__setup("rk_cam_h=", rk_cam_h_setup);
-__setup("rk_cam_fps=", rk_cam_fps_setup);
-
 static void find_terminal_resolution(struct sc200ai *sc200ai)
 {
 	int i = 0;
 	const struct sc200ai_mode *mode = NULL;
-	const struct sc200ai_mode *fit_mode = NULL;
-	u32 cur_fps = 0;
-	u32 dst_fps = 0;
-	u32 tmp_fps = 0;
+	u32 rk_cam_hdr = get_rk_cam_hdr();
+	u32 rk_cam_w = get_rk_cam_w();
+	u32 rk_cam_h = get_rk_cam_h();
 
-	if (rk_cam_w == 0 || rk_cam_h == 0 ||
-	    rk_cam_fps == 0)
+	if (rk_cam_w == 0 || rk_cam_h == 0)
 		goto err_find_res;
 
-	dst_fps = rk_cam_fps;
 	for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
 		mode = &supported_modes[i];
-		cur_fps = mode->max_fps.denominator / mode->max_fps.numerator;
 		if (mode->width == rk_cam_w && mode->height == rk_cam_h &&
 		    mode->hdr_mode == rk_cam_hdr) {
-			if (cur_fps == dst_fps) {
-				sc200ai->cur_mode = mode;
-				return;
-			}
-			if (cur_fps >= dst_fps) {
-				if (fit_mode) {
-					tmp_fps = fit_mode->max_fps.denominator / fit_mode->max_fps.numerator;
-					if (tmp_fps - dst_fps > cur_fps - dst_fps)
-						fit_mode = mode;
-				} else {
-					fit_mode = mode;
-				}
-			}
+			sc200ai->cur_mode = mode;
+			return;
 		}
 	}
-	if (fit_mode) {
-		sc200ai->cur_mode = fit_mode;
-		return;
-	}
 err_find_res:
-	dev_err(&sc200ai->client->dev, "not match %dx%d@%dfps mode %d\n!",
-		rk_cam_w, rk_cam_h, dst_fps, rk_cam_hdr);
+	dev_err(&sc200ai->client->dev, "not match %dx%d mode %d\n!",
+		rk_cam_w, rk_cam_h, rk_cam_hdr);
 	sc200ai->cur_mode = &supported_modes[0];
 }
 #else
@@ -2057,11 +2039,11 @@
 		return -EINVAL;
 	}
 
-	sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
+	sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", sc200ai->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW);
 	if (IS_ERR(sc200ai->reset_gpio))
 		dev_warn(dev, "Failed to get reset-gpios\n");
 
-	sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_ASIS);
+	sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", sc200ai->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW);
 	if (IS_ERR(sc200ai->pwdn_gpio))
 		dev_warn(dev, "Failed to get pwdn-gpios\n");
 
@@ -2117,6 +2099,13 @@
 		goto err_power_off;
 #endif
 
+	if (!sc200ai->cam_sw_inf) {
+		sc200ai->cam_sw_inf = cam_sw_init();
+		cam_sw_clk_init(sc200ai->cam_sw_inf, sc200ai->xvclk, SC200AI_XVCLK_FREQ);
+		cam_sw_reset_pin_init(sc200ai->cam_sw_inf, sc200ai->reset_gpio, 0);
+		cam_sw_pwdn_pin_init(sc200ai->cam_sw_inf, sc200ai->pwdn_gpio, 1);
+	}
+
 	memset(facing, 0, sizeof(facing));
 	if (strcmp(sc200ai->module_facing, "back") == 0)
 		facing[0] = 'b';
@@ -2167,6 +2156,8 @@
 	v4l2_ctrl_handler_free(&sc200ai->ctrl_handler);
 	mutex_destroy(&sc200ai->mutex);
 
+	cam_sw_deinit(sc200ai->cam_sw_inf);
+
 	pm_runtime_disable(&client->dev);
 	if (!pm_runtime_status_suspended(&client->dev))
 		__sc200ai_power_off(sc200ai);

--
Gitblit v1.6.2