From 072de836f53be56a70cecf70b43ae43b7ce17376 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 10:08:36 +0000
Subject: [PATCH] mk-rootfs.sh

---
 kernel/drivers/media/i2c/ov02b10.c |   93 +++++++++++++++++++++++++++++++---------------
 1 files changed, 63 insertions(+), 30 deletions(-)

diff --git a/kernel/drivers/media/i2c/ov02b10.c b/kernel/drivers/media/i2c/ov02b10.c
index 19ca156..94d5d7f 100644
--- a/kernel/drivers/media/i2c/ov02b10.c
+++ b/kernel/drivers/media/i2c/ov02b10.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
  *
  * V0.0X01.0X00 first version.
+ * V0.0X01.0X01 fix power on & off sequence
  */
 
 #include <linux/clk.h>
@@ -27,7 +28,7 @@
 #include <linux/rk-preisp.h>
 #include "../platform/rockchip/isp/rkisp_tb_helper.h"
 
-#define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x00)
+#define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x01)
 
 #ifndef V4L2_CID_DIGITAL_GAIN
 #define V4L2_CID_DIGITAL_GAIN		V4L2_CID_GAIN
@@ -91,20 +92,11 @@
 #define SENSOR_ID(_msb, _lsb)   ((_msb) << 8 | (_lsb))
 
 static const char * const OV02B10_supply_names[] = {
-	"avdd",		/* Analog power */
 	"dovdd",	/* Digital I/O power */
-	"dvdd",         /* Digital core power */
+	"avdd",		/* Analog power */
 };
 
 #define OV02B10_NUM_SUPPLIES ARRAY_SIZE(OV02B10_supply_names)
-
-enum ov02b10_max_pad {
-	PAD0,
-	PAD1,
-	PAD2,
-	PAD3,
-	PAD_MAX,
-};
 
 struct regval {
 	u8 addr;
@@ -534,14 +526,12 @@
 	struct ov02b10 *ov02b10 = to_ov02b10(sd);
 	const struct ov02b10_mode *mode = ov02b10->cur_mode;
 
-	mutex_lock(&ov02b10->mutex);
 	fi->interval = mode->max_fps;
-	mutex_unlock(&ov02b10->mutex);
 
 	return 0;
 }
 
-static int ov02b10_g_mbus_config(struct v4l2_subdev *sd,
+static int ov02b10_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
 				struct v4l2_mbus_config *config)
 {
 	struct ov02b10 *ov02b10 = to_ov02b10(sd);
@@ -558,7 +548,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;
@@ -639,8 +629,11 @@
 		}
 
 		ret = ov02b10_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:
@@ -653,6 +646,8 @@
 		ret = copy_from_user(cfg, up, sizeof(*cfg));
 		if (!ret)
 			ret = ov02b10_ioctl(sd, cmd, cfg);
+		else
+			ret = -EFAULT;
 		kfree(cfg);
 		break;
 	case RKMODULE_GET_HDR_CFG:
@@ -663,8 +658,11 @@
 		}
 
 		ret = ov02b10_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:
@@ -677,6 +675,8 @@
 		ret = copy_from_user(hdr, up, sizeof(*hdr));
 		if (!ret)
 			ret = ov02b10_ioctl(sd, cmd, hdr);
+		else
+			ret = -EFAULT;
 		kfree(hdr);
 		break;
 	case PREISP_CMD_SET_HDRAE_EXP:
@@ -689,17 +689,23 @@
 		ret = copy_from_user(hdrae, up, sizeof(*hdrae));
 		if (!ret)
 			ret = ov02b10_ioctl(sd, cmd, hdrae);
+		else
+			ret = -EFAULT;
 		kfree(hdrae);
 		break;
 	case RKMODULE_SET_CONVERSION_GAIN:
 		ret = copy_from_user(&cg, up, sizeof(cg));
 		if (!ret)
 			ret = ov02b10_ioctl(sd, cmd, &cg);
+		else
+			ret = -EFAULT;
 		break;
 	case RKMODULE_SET_QUICK_STREAM:
 		ret = copy_from_user(&stream, up, sizeof(u32));
 		if (!ret)
 			ret = ov02b10_ioctl(sd, cmd, &stream);
+		else
+			ret = -EFAULT;
 		break;
 	default:
 		ret = -ENOIOCTLCMD;
@@ -813,6 +819,31 @@
 	return ret;
 }
 
+static int ov02b10_enable_regulators(struct ov02b10 *ov02b10,
+				    struct regulator_bulk_data *consumers)
+{
+	int i, j;
+	int ret = 0;
+	struct device *dev = &ov02b10->client->dev;
+	int num_consumers = OV02B10_NUM_SUPPLIES;
+
+	for (i = 0; i < num_consumers; i++) {
+
+		ret = regulator_enable(consumers[i].consumer);
+		if (ret < 0) {
+			dev_err(dev, "Failed to enable regulator: %s\n",
+				consumers[i].supply);
+			goto err;
+		}
+	}
+	return 0;
+err:
+	for (j = 0; j < i; j++)
+		regulator_disable(consumers[j].consumer);
+
+	return ret;
+}
+
 static int __ov02b10_power_on(struct ov02b10 *ov02b10)
 {
 	int ret;
@@ -829,11 +860,6 @@
 		dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
 	if (clk_get_rate(ov02b10->xvclk) != OV02B10_XVCLK_FREQ)
 		dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
-	ret = clk_prepare_enable(ov02b10->xvclk);
-	if (ret < 0) {
-		dev_err(dev, "Failed to enable xvclk\n");
-		return ret;
-	}
 
 	if (!IS_ERR(ov02b10->pwdn_gpio))
 		gpiod_direction_output(ov02b10->pwdn_gpio, 1);
@@ -841,10 +867,16 @@
 	if (!IS_ERR(ov02b10->reset_gpio))
 		gpiod_direction_output(ov02b10->reset_gpio, 1);
 
-	ret = regulator_bulk_enable(OV02B10_NUM_SUPPLIES, ov02b10->supplies);
+	ret = ov02b10_enable_regulators(ov02b10, ov02b10->supplies);
 	if (ret < 0) {
 		dev_err(dev, "Failed to enable regulators\n");
 		goto disable_clk;
+	}
+	usleep_range(100, 110);
+	ret = clk_prepare_enable(ov02b10->xvclk);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable xvclk\n");
+		return ret;
 	}
 
 	/* From spec: delay from power stable to pwdn off: 5ms */
@@ -872,13 +904,14 @@
 	int ret;
 	struct device *dev = &ov02b10->client->dev;
 
-	if (!IS_ERR(ov02b10->pwdn_gpio))
-		gpiod_direction_output(ov02b10->pwdn_gpio, 1);
+	if (!IS_ERR(ov02b10->reset_gpio))
+		gpiod_direction_output(ov02b10->reset_gpio, 1);
 
 	clk_disable_unprepare(ov02b10->xvclk);
 
-	if (!IS_ERR(ov02b10->reset_gpio))
-		gpiod_direction_output(ov02b10->reset_gpio, 1);
+	if (!IS_ERR(ov02b10->pwdn_gpio))
+		gpiod_direction_output(ov02b10->pwdn_gpio, 1);
+
 	if (!IS_ERR_OR_NULL(ov02b10->pins_sleep)) {
 		ret = pinctrl_select_state(ov02b10->pinctrl,
 					   ov02b10->pins_sleep);
@@ -888,7 +921,7 @@
 	regulator_bulk_disable(OV02B10_NUM_SUPPLIES, ov02b10->supplies);
 }
 
-static int ov02b10_runtime_resume(struct device *dev)
+static int __maybe_unused ov02b10_runtime_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
@@ -897,7 +930,7 @@
 	return __ov02b10_power_on(ov02b10);
 }
 
-static int ov02b10_runtime_suspend(struct device *dev)
+static int __maybe_unused ov02b10_runtime_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
@@ -969,7 +1002,6 @@
 static const struct v4l2_subdev_video_ops ov02b10_video_ops = {
 	.s_stream = ov02b10_s_stream,
 	.g_frame_interval = ov02b10_g_frame_interval,
-	.g_mbus_config = ov02b10_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops ov02b10_pad_ops = {
@@ -978,6 +1010,7 @@
 	.enum_frame_interval = ov02b10_enum_frame_interval,
 	.get_fmt = ov02b10_get_fmt,
 	.set_fmt = ov02b10_set_fmt,
+	.get_mbus_config = ov02b10_g_mbus_config,
 };
 
 static const struct v4l2_subdev_ops ov02b10_subdev_ops = {

--
Gitblit v1.6.2