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/dw9800w.c |  101 +++++++++++++++++++++++++++++++-------------------
 1 files changed, 63 insertions(+), 38 deletions(-)

diff --git a/kernel/drivers/media/i2c/dw9800w.c b/kernel/drivers/media/i2c/dw9800w.c
index 2b0729e..e104336 100644
--- a/kernel/drivers/media/i2c/dw9800w.c
+++ b/kernel/drivers/media/i2c/dw9800w.c
@@ -44,6 +44,7 @@
 /* dw9800w device structure */
 struct dw9800w_device {
 	struct v4l2_ctrl_handler ctrls_vcm;
+	struct v4l2_ctrl *focus;
 	struct i2c_client *client;
 	struct v4l2_subdev sd;
 	struct v4l2_device vdev;
@@ -52,13 +53,14 @@
 	struct gpio_desc *power_gpio;
 	unsigned short current_related_pos;
 	unsigned short current_lens_pos;
+	unsigned int max_current;
 	unsigned int start_current;
 	unsigned int rated_current;
-	unsigned int step;
 	unsigned int step_mode;
 	unsigned int vcm_movefull_t;
 	unsigned int t_src;
 	unsigned int t_div;
+	unsigned int max_logicalpos;
 
 	struct __kernel_old_timeval start_move_tv;
 	struct __kernel_old_timeval end_move_tv;
@@ -67,7 +69,6 @@
 	u32 module_index;
 	const char *module_facing;
 	struct rk_cam_vcm_cfg vcm_cfg;
-	int max_ma;
 	struct mutex lock;
 };
 
@@ -217,22 +218,25 @@
 	unsigned int *cur_pos)
 {
 	struct i2c_client *client = dev_vcm->client;
+	unsigned int dac, position, range;
 	int ret;
-	unsigned int abs_step;
 
-	ret = dw9800w_read_reg(client, 0x03, 2, &abs_step);
+	range = dev_vcm->rated_current - dev_vcm->start_current;
+	ret = dw9800w_read_reg(client, 0x03, 2, &dac);
 	if (ret != 0)
 		goto err;
 
-	if (abs_step <= dev_vcm->start_current)
-		abs_step = VCMDRV_MAX_LOG;
-	else if ((abs_step > dev_vcm->start_current) &&
-		 (abs_step <= dev_vcm->rated_current))
-		abs_step = (dev_vcm->rated_current - abs_step) / dev_vcm->step;
-	else
-		abs_step = 0;
+	if (dac <= dev_vcm->start_current) {
+		position = dev_vcm->max_logicalpos;
+	} else if ((dac > dev_vcm->start_current) &&
+		   (dac <= dev_vcm->rated_current)) {
+		position = (dac - dev_vcm->start_current) * dev_vcm->max_logicalpos / range;
+		position = dev_vcm->max_logicalpos - position;
+	} else {
+		position = 0;
+	}
 
-	*cur_pos = abs_step;
+	*cur_pos = position;
 	dev_dbg(&client->dev, "%s: get position %d\n", __func__, *cur_pos);
 	return 0;
 
@@ -245,16 +249,18 @@
 static int dw9800w_set_pos(struct dw9800w_device *dev_vcm,
 	unsigned int dest_pos)
 {
-	int ret;
-	unsigned int position = 0;
-	struct i2c_client *client = dev_vcm->client;
+	struct i2c_client *client = v4l2_get_subdevdata(&dev_vcm->sd);
+	unsigned int position;
+	unsigned int range;
 	u32 is_busy, i;
+	int ret;
 
-	if (dest_pos >= VCMDRV_MAX_LOG)
+	range = dev_vcm->rated_current - dev_vcm->start_current;
+	if (dest_pos >= dev_vcm->max_logicalpos)
 		position = dev_vcm->start_current;
 	else
 		position = dev_vcm->start_current +
-			   (dev_vcm->step * (VCMDRV_MAX_LOG - dest_pos));
+			   (range * (dev_vcm->max_logicalpos - dest_pos) / dev_vcm->max_logicalpos);
 
 	if (position > DW9800W_MAX_REG)
 		position = DW9800W_MAX_REG;
@@ -304,10 +310,10 @@
 
 	if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) {
 
-		if (dest_pos > VCMDRV_MAX_LOG) {
+		if (dest_pos > dev_vcm->max_logicalpos) {
 			dev_info(&client->dev,
 				"%s dest_pos is error. %d > %d\n",
-				__func__, dest_pos, VCMDRV_MAX_LOG);
+				__func__, dest_pos, dev_vcm->max_logicalpos);
 			return -EINVAL;
 		}
 		/* calculate move time */
@@ -318,7 +324,7 @@
 		ret = dw9800w_set_pos(dev_vcm, dest_pos);
 		if (dev_vcm->step_mode == LSC_MODE)
 			dev_vcm->move_us = ((dev_vcm->vcm_movefull_t * (uint32_t)move_pos) /
-					   VCMDRV_MAX_LOG);
+					   dev_vcm->max_logicalpos);
 		else
 			dev_vcm->move_us = dev_vcm->vcm_movefull_t;
 
@@ -376,28 +382,27 @@
 static void dw9800w_update_vcm_cfg(struct dw9800w_device *dev_vcm)
 {
 	struct i2c_client *client = dev_vcm->client;
-	int cur_dist;
 
-	if (dev_vcm->max_ma == 0) {
+	if (dev_vcm->max_current == 0) {
 		dev_err(&client->dev, "max current is zero");
 		return;
 	}
 
-	cur_dist = dev_vcm->vcm_cfg.rated_ma - dev_vcm->vcm_cfg.start_ma;
-	cur_dist = cur_dist * DW9800W_MAX_REG / dev_vcm->max_ma;
-	dev_vcm->step = (cur_dist + (VCMDRV_MAX_LOG - 1)) / VCMDRV_MAX_LOG;
+	if (dev_vcm->vcm_cfg.rated_ma > dev_vcm->max_current)
+		dev_vcm->max_current = DW9800W_MAX_REG;
+
 	dev_vcm->start_current = dev_vcm->vcm_cfg.start_ma *
-				 DW9800W_MAX_REG / dev_vcm->max_ma;
+				 DW9800W_MAX_REG / dev_vcm->max_current;
 	dev_vcm->rated_current = dev_vcm->vcm_cfg.rated_ma *
-				 DW9800W_MAX_REG / dev_vcm->max_ma;
+				 DW9800W_MAX_REG / dev_vcm->max_current;
 	dev_vcm->step_mode = dev_vcm->vcm_cfg.step_mode;
 
 	dev_info(&client->dev,
-		"vcm_cfg: %d, %d, %d, max_ma %d\n",
+		"vcm_cfg: %d, %d, %d, max_current %d\n",
 		dev_vcm->vcm_cfg.start_ma,
 		dev_vcm->vcm_cfg.rated_ma,
 		dev_vcm->vcm_cfg.step_mode,
-		dev_vcm->max_ma);
+		dev_vcm->max_current);
 }
 
 static long dw9800w_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
@@ -406,6 +411,7 @@
 	struct i2c_client *client = dev_vcm->client;
 	struct rk_cam_vcm_tim *vcm_tim;
 	struct rk_cam_vcm_cfg *vcm_cfg;
+	unsigned int max_logicalpos;
 	int ret = 0;
 
 	if (cmd == RK_VIDIOC_VCM_TIMEINFO) {
@@ -441,6 +447,16 @@
 		dev_vcm->vcm_cfg.rated_ma = vcm_cfg->rated_ma;
 		dev_vcm->vcm_cfg.step_mode = vcm_cfg->step_mode;
 		dw9800w_update_vcm_cfg(dev_vcm);
+	} else if (cmd == RK_VIDIOC_SET_VCM_MAX_LOGICALPOS) {
+		max_logicalpos = *(unsigned int *)arg;
+
+		if (max_logicalpos > 0) {
+			dev_vcm->max_logicalpos = max_logicalpos;
+			__v4l2_ctrl_modify_range(dev_vcm->focus,
+				0, dev_vcm->max_logicalpos, 1, dev_vcm->max_logicalpos);
+		}
+		dev_dbg(&client->dev,
+			"max_logicalpos %d\n", max_logicalpos);
 	} else {
 		dev_err(&client->dev,
 			"cmd 0x%x not supported\n", cmd);
@@ -460,6 +476,7 @@
 	struct rk_cam_compat_vcm_tim compat_vcm_tim;
 	struct rk_cam_vcm_tim vcm_tim;
 	struct rk_cam_vcm_cfg vcm_cfg;
+	unsigned int max_logicalpos;
 	long ret;
 
 	if (cmd == RK_VIDIOC_COMPAT_VCM_TIMEINFO) {
@@ -490,6 +507,12 @@
 		ret = copy_from_user(&vcm_cfg, up, sizeof(vcm_cfg));
 		if (!ret)
 			ret = dw9800w_ioctl(sd, cmd, &vcm_cfg);
+		else
+			ret = -EFAULT;
+	} else if (cmd == RK_VIDIOC_SET_VCM_MAX_LOGICALPOS) {
+		ret = copy_from_user(&max_logicalpos, up, sizeof(max_logicalpos));
+		if (!ret)
+			ret = dw9800w_ioctl(sd, cmd, &max_logicalpos);
 		else
 			ret = -EFAULT;
 	} else {
@@ -528,8 +551,9 @@
 
 	v4l2_ctrl_handler_init(hdl, 1);
 
-	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
-			  0, VCMDRV_MAX_LOG, 1, 32);
+	dev_vcm->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
+					   0, dev_vcm->max_logicalpos, 1,
+					   dev_vcm->max_logicalpos / 2);
 
 	if (hdl->error)
 		dev_err(dev_vcm->sd.dev, "%s fail error: 0x%x\n",
@@ -585,7 +609,7 @@
 {
 	struct device_node *np = of_node_get(client->dev.of_node);
 	struct dw9800w_device *dw9800w_dev;
-	unsigned int max_ma, start_ma, rated_ma, step_mode;
+	unsigned int max_current, start_ma, rated_ma, step_mode;
 	unsigned int t_src, t_div;
 	struct v4l2_subdev *sd;
 	char facing[2];
@@ -594,14 +618,14 @@
 	dev_info(&client->dev, "probing...\n");
 	if (of_property_read_u32(np,
 		OF_CAMERA_VCMDRV_MAX_CURRENT,
-		(unsigned int *)&max_ma)) {
-		max_ma = DW9800W_MAX_CURRENT;
+		(unsigned int *)&max_current)) {
+		max_current = DW9800W_MAX_CURRENT;
 		dev_info(&client->dev,
 			"could not get module %s from dts!\n",
 			OF_CAMERA_VCMDRV_MAX_CURRENT);
 	}
-	if (max_ma == 0)
-		max_ma = DW9800W_MAX_CURRENT;
+	if (max_current == 0)
+		max_current = DW9800W_MAX_CURRENT;
 
 	if (of_property_read_u32(np,
 		OF_CAMERA_VCMDRV_START_CURRENT,
@@ -680,6 +704,7 @@
 	dw9800w_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 	dw9800w_dev->sd.internal_ops = &dw9800w_int_ops;
 
+	dw9800w_dev->max_logicalpos = VCMDRV_MAX_LOG;
 	ret = dw9800w_init_controls(dw9800w_dev);
 	if (ret)
 		goto err_cleanup;
@@ -704,13 +729,13 @@
 	if (ret)
 		dev_err(&client->dev, "v4l2 async register subdev failed\n");
 
-	dw9800w_dev->max_ma = max_ma;
+	dw9800w_dev->max_current = max_current;
 	dw9800w_dev->vcm_cfg.start_ma = start_ma;
 	dw9800w_dev->vcm_cfg.rated_ma = rated_ma;
 	dw9800w_dev->vcm_cfg.step_mode = step_mode;
 	dw9800w_update_vcm_cfg(dw9800w_dev);
 	dw9800w_dev->move_us	= 0;
-	dw9800w_dev->current_related_pos = VCMDRV_MAX_LOG;
+	dw9800w_dev->current_related_pos = dw9800w_dev->max_logicalpos;
 	dw9800w_dev->start_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
 	dw9800w_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
 

--
Gitblit v1.6.2