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/imx415.c |  522 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 466 insertions(+), 56 deletions(-)

diff --git a/kernel/drivers/media/i2c/imx415.c b/kernel/drivers/media/i2c/imx415.c
index 0bd0431..2cf6561 100644
--- a/kernel/drivers/media/i2c/imx415.c
+++ b/kernel/drivers/media/i2c/imx415.c
@@ -50,6 +50,8 @@
 #include <media/v4l2-subdev.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/rk-preisp.h>
+#include <media/v4l2-fwnode.h>
+#include <linux/of_graph.h>
 #include "../platform/rockchip/isp/rkisp_tb_helper.h"
 
 #define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x08)
@@ -58,17 +60,20 @@
 #define V4L2_CID_DIGITAL_GAIN		V4L2_CID_GAIN
 #endif
 
+#define MIPI_FREQ_1188M			1188000000
 #define MIPI_FREQ_891M			891000000
 #define MIPI_FREQ_446M			446000000
 #define MIPI_FREQ_743M			743000000
 #define MIPI_FREQ_297M			297000000
 
 #define IMX415_4LANES			4
+#define IMX415_2LANES			2
 
 #define IMX415_MAX_PIXEL_RATE		(MIPI_FREQ_891M / 10 * 2 * IMX415_4LANES)
 #define OF_CAMERA_HDR_MODE		"rockchip,camera-hdr-mode"
 
 #define IMX415_XVCLK_FREQ_37M		37125000
+#define IMX415_XVCLK_FREQ_27M		27000000
 
 /* TODO: Get the real chip id from reg */
 #define CHIP_ID				0xE0
@@ -142,6 +147,7 @@
 #define IMX415_FLIP_REG			0x3030
 
 #define REG_NULL			0xFFFF
+#define REG_DELAY			0xFFFE
 
 #define IMX415_REG_VALUE_08BIT		1
 #define IMX415_REG_VALUE_16BIT		2
@@ -164,6 +170,7 @@
 
 #define OF_CAMERA_PINCTRL_STATE_DEFAULT	"rockchip,camera_default"
 #define OF_CAMERA_PINCTRL_STATE_SLEEP	"rockchip,camera_sleep"
+#define RKMODULE_CAMERA_FASTBOOT_ENABLE "rockchip,camera_fastboot"
 
 #define IMX415_NAME			"imx415"
 
@@ -194,6 +201,7 @@
 	const struct regval *reg_list;
 	u32 hdr_mode;
 	u32 vc[PAD_MAX];
+	u32 xvclk;
 };
 
 struct imx415 {
@@ -220,9 +228,10 @@
 	struct mutex		mutex;
 	bool			streaming;
 	bool			power_on;
-	bool			is_thunderboot;
+	u32			is_thunderboot;
 	bool			is_thunderboot_ng;
 	bool			is_first_streamoff;
+	const struct imx415_mode *supported_modes;
 	const struct imx415_mode *cur_mode;
 	u32			module_index;
 	u32			cfg_num;
@@ -232,6 +241,7 @@
 	u32			cur_vts;
 	bool			has_init_exp;
 	struct preisp_hdrae_exp_s init_hdrae_exp;
+	struct v4l2_fwnode_endpoint bus_cfg;
 };
 
 static struct rkmodule_csi_dphy_param dcphy_param = {
@@ -746,6 +756,311 @@
 };
 
 /*
+ * Xclk 27Mhz
+ * 15fps
+ * CSI-2_2lane
+ * AD:12bit Output:12bit
+ * 891Mbps
+ * Master Mode
+ * Time 9.988ms Gain:6dB
+ * All-pixel
+ */
+static __maybe_unused const struct regval imx415_linear_12bit_3864x2192_891M_regs_2lane[] = {
+	{0x3008, 0x5D},
+	{0x300A, 0x42},
+	{0x3028, 0x98},
+	{0x3029, 0x08},
+	{0x3033, 0x05},
+	{0x3050, 0x79},
+	{0x3051, 0x07},
+	{0x3090, 0x14},
+	{0x30C1, 0x00},
+	{0x3116, 0x23},
+	{0x3118, 0xC6},
+	{0x311A, 0xE7},
+	{0x311E, 0x23},
+	{0x32D4, 0x21},
+	{0x32EC, 0xA1},
+	{0x344C, 0x2B},
+	{0x344D, 0x01},
+	{0x344E, 0xED},
+	{0x344F, 0x01},
+	{0x3450, 0xF6},
+	{0x3451, 0x02},
+	{0x3452, 0x7F},
+	{0x3453, 0x03},
+	{0x358A, 0x04},
+	{0x35A1, 0x02},
+	{0x35EC, 0x27},
+	{0x35EE, 0x8D},
+	{0x35F0, 0x8D},
+	{0x35F2, 0x29},
+	{0x36BC, 0x0C},
+	{0x36CC, 0x53},
+	{0x36CD, 0x00},
+	{0x36CE, 0x3C},
+	{0x36D0, 0x8C},
+	{0x36D1, 0x00},
+	{0x36D2, 0x71},
+	{0x36D4, 0x3C},
+	{0x36D6, 0x53},
+	{0x36D7, 0x00},
+	{0x36D8, 0x71},
+	{0x36DA, 0x8C},
+	{0x36DB, 0x00},
+	{0x3720, 0x00},
+	{0x3724, 0x02},
+	{0x3726, 0x02},
+	{0x3732, 0x02},
+	{0x3734, 0x03},
+	{0x3736, 0x03},
+	{0x3742, 0x03},
+	{0x3862, 0xE0},
+	{0x38CC, 0x30},
+	{0x38CD, 0x2F},
+	{0x395C, 0x0C},
+	{0x39A4, 0x07},
+	{0x39A8, 0x32},
+	{0x39AA, 0x32},
+	{0x39AC, 0x32},
+	{0x39AE, 0x32},
+	{0x39B0, 0x32},
+	{0x39B2, 0x2F},
+	{0x39B4, 0x2D},
+	{0x39B6, 0x28},
+	{0x39B8, 0x30},
+	{0x39BA, 0x30},
+	{0x39BC, 0x30},
+	{0x39BE, 0x30},
+	{0x39C0, 0x30},
+	{0x39C2, 0x2E},
+	{0x39C4, 0x2B},
+	{0x39C6, 0x25},
+	{0x3A42, 0xD1},
+	{0x3A4C, 0x77},
+	{0x3AE0, 0x02},
+	{0x3AEC, 0x0C},
+	{0x3B00, 0x2E},
+	{0x3B06, 0x29},
+	{0x3B98, 0x25},
+	{0x3B99, 0x21},
+	{0x3B9B, 0x13},
+	{0x3B9C, 0x13},
+	{0x3B9D, 0x13},
+	{0x3B9E, 0x13},
+	{0x3BA1, 0x00},
+	{0x3BA2, 0x06},
+	{0x3BA3, 0x0B},
+	{0x3BA4, 0x10},
+	{0x3BA5, 0x14},
+	{0x3BA6, 0x18},
+	{0x3BA7, 0x1A},
+	{0x3BA8, 0x1A},
+	{0x3BA9, 0x1A},
+	{0x3BAC, 0xED},
+	{0x3BAD, 0x01},
+	{0x3BAE, 0xF6},
+	{0x3BAF, 0x02},
+	{0x3BB0, 0xA2},
+	{0x3BB1, 0x03},
+	{0x3BB2, 0xE0},
+	{0x3BB3, 0x03},
+	{0x3BB4, 0xE0},
+	{0x3BB5, 0x03},
+	{0x3BB6, 0xE0},
+	{0x3BB7, 0x03},
+	{0x3BB8, 0xE0},
+	{0x3BBA, 0xE0},
+	{0x3BBC, 0xDA},
+	{0x3BBE, 0x88},
+	{0x3BC0, 0x44},
+	{0x3BC2, 0x7B},
+	{0x3BC4, 0xA2},
+	{0x3BC8, 0xBD},
+	{0x3BCA, 0xBD},
+	{0x4001, 0x01},
+	{0x4004, 0xC0},
+	{0x4005, 0x06},
+	{0x400C, 0x00},
+	{0x4018, 0x7F},
+	{0x401A, 0x37},
+	{0x401C, 0x37},
+	{0x401E, 0xF7},
+	{0x401F, 0x00},
+	{0x4020, 0x3F},
+	{0x4022, 0x6F},
+	{0x4024, 0x3F},
+	{0x4026, 0x5F},
+	{0x4028, 0x2F},
+	{0x4074, 0x01},
+	{0x3002, 0x00},
+	//{0x3000, 0x00},
+	{REG_DELAY, 0x1E},//wait_ms(30)
+	{REG_NULL, 0x00},
+};
+
+/*
+ * Xclk 27Mhz
+ * 90.059fps
+ * CSI-2_2lane
+ * AD:10bit Output:12bit
+ * 2376Mbps
+ * Master Mode
+ * Time 9.999ms Gain:6dB
+ * 2568x1440 2/2-line binning & Window cropping
+ */
+static __maybe_unused const struct regval imx415_linear_12bit_1284x720_2376M_regs_2lane[] = {
+	{0x3008, 0x5D},
+	{0x300A, 0x42},
+	{0x301C, 0x04},
+	{0x3020, 0x01},
+	{0x3021, 0x01},
+	{0x3022, 0x01},
+	{0x3024, 0xAB},
+	{0x3025, 0x07},
+	{0x3028, 0xA4},
+	{0x3029, 0x01},
+	{0x3031, 0x00},
+	{0x3033, 0x00},
+	{0x3040, 0x88},
+	{0x3041, 0x02},
+	{0x3042, 0x08},
+	{0x3043, 0x0A},
+	{0x3044, 0xF0},
+	{0x3045, 0x02},
+	{0x3046, 0x40},
+	{0x3047, 0x0B},
+	{0x3050, 0xC4},
+	{0x3090, 0x14},
+	{0x30C1, 0x00},
+	{0x30D9, 0x02},
+	{0x30DA, 0x01},
+	{0x3116, 0x23},
+	{0x3118, 0x08},
+	{0x3119, 0x01},
+	{0x311A, 0xE7},
+	{0x311E, 0x23},
+	{0x32D4, 0x21},
+	{0x32EC, 0xA1},
+	{0x344C, 0x2B},
+	{0x344D, 0x01},
+	{0x344E, 0xED},
+	{0x344F, 0x01},
+	{0x3450, 0xF6},
+	{0x3451, 0x02},
+	{0x3452, 0x7F},
+	{0x3453, 0x03},
+	{0x358A, 0x04},
+	{0x35A1, 0x02},
+	{0x35EC, 0x27},
+	{0x35EE, 0x8D},
+	{0x35F0, 0x8D},
+	{0x35F2, 0x29},
+	{0x36BC, 0x0C},
+	{0x36CC, 0x53},
+	{0x36CD, 0x00},
+	{0x36CE, 0x3C},
+	{0x36D0, 0x8C},
+	{0x36D1, 0x00},
+	{0x36D2, 0x71},
+	{0x36D4, 0x3C},
+	{0x36D6, 0x53},
+	{0x36D7, 0x00},
+	{0x36D8, 0x71},
+	{0x36DA, 0x8C},
+	{0x36DB, 0x00},
+	{0x3701, 0x00},
+	{0x3720, 0x00},
+	{0x3724, 0x02},
+	{0x3726, 0x02},
+	{0x3732, 0x02},
+	{0x3734, 0x03},
+	{0x3736, 0x03},
+	{0x3742, 0x03},
+	{0x3862, 0xE0},
+	{0x38CC, 0x30},
+	{0x38CD, 0x2F},
+	{0x395C, 0x0C},
+	{0x39A4, 0x07},
+	{0x39A8, 0x32},
+	{0x39AA, 0x32},
+	{0x39AC, 0x32},
+	{0x39AE, 0x32},
+	{0x39B0, 0x32},
+	{0x39B2, 0x2F},
+	{0x39B4, 0x2D},
+	{0x39B6, 0x28},
+	{0x39B8, 0x30},
+	{0x39BA, 0x30},
+	{0x39BC, 0x30},
+	{0x39BE, 0x30},
+	{0x39C0, 0x30},
+	{0x39C2, 0x2E},
+	{0x39C4, 0x2B},
+	{0x39C6, 0x25},
+	{0x3A42, 0xD1},
+	{0x3A4C, 0x77},
+	{0x3AE0, 0x02},
+	{0x3AEC, 0x0C},
+	{0x3B00, 0x2E},
+	{0x3B06, 0x29},
+	{0x3B98, 0x25},
+	{0x3B99, 0x21},
+	{0x3B9B, 0x13},
+	{0x3B9C, 0x13},
+	{0x3B9D, 0x13},
+	{0x3B9E, 0x13},
+	{0x3BA1, 0x00},
+	{0x3BA2, 0x06},
+	{0x3BA3, 0x0B},
+	{0x3BA4, 0x10},
+	{0x3BA5, 0x14},
+	{0x3BA6, 0x18},
+	{0x3BA7, 0x1A},
+	{0x3BA8, 0x1A},
+	{0x3BA9, 0x1A},
+	{0x3BAC, 0xED},
+	{0x3BAD, 0x01},
+	{0x3BAE, 0xF6},
+	{0x3BAF, 0x02},
+	{0x3BB0, 0xA2},
+	{0x3BB1, 0x03},
+	{0x3BB2, 0xE0},
+	{0x3BB3, 0x03},
+	{0x3BB4, 0xE0},
+	{0x3BB5, 0x03},
+	{0x3BB6, 0xE0},
+	{0x3BB7, 0x03},
+	{0x3BB8, 0xE0},
+	{0x3BBA, 0xE0},
+	{0x3BBC, 0xDA},
+	{0x3BBE, 0x88},
+	{0x3BC0, 0x44},
+	{0x3BC2, 0x7B},
+	{0x3BC4, 0xA2},
+	{0x3BC8, 0xBD},
+	{0x3BCA, 0xBD},
+	{0x4001, 0x01},
+	{0x4004, 0xC0},
+	{0x4005, 0x06},
+	{0x4018, 0xE7},
+	{0x401A, 0x8F},
+	{0x401C, 0x8F},
+	{0x401E, 0x7F},
+	{0x401F, 0x02},
+	{0x4020, 0x97},
+	{0x4022, 0x0F},
+	{0x4023, 0x01},
+	{0x4024, 0x97},
+	{0x4026, 0xF7},
+	{0x4028, 0x7F},
+	{0x3002, 0x00},
+	//{0x3000, 0x00},
+	{REG_DELAY, 0x1E},//wait_ms(30)
+	{REG_NULL, 0x00},
+};
+
+/*
  * The width and height must be configured to be
  * the same as the current output resolution of the sensor.
  * The input width of the isp needs to be 16 aligned.
@@ -779,6 +1094,7 @@
 		.mipi_freq_idx = 1,
 		.bpp = 10,
 		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
+		.xvclk = IMX415_XVCLK_FREQ_37M,
 	},
 	{
 		.bus_fmt = MEDIA_BUS_FMT_SGBRG10_1X10,
@@ -804,6 +1120,7 @@
 		.vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
 		.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
 		.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
+		.xvclk = IMX415_XVCLK_FREQ_37M,
 	},
 	{
 		.bus_fmt = MEDIA_BUS_FMT_SGBRG10_1X10,
@@ -829,6 +1146,7 @@
 		.vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr0
 		.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
 		.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_2,//S->csi wr2
+		.xvclk = IMX415_XVCLK_FREQ_37M,
 	},
 	{
 		.bus_fmt = MEDIA_BUS_FMT_SGBRG10_1X10,
@@ -854,6 +1172,7 @@
 		.vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr0
 		.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
 		.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_2,//S->csi wr2
+		.xvclk = IMX415_XVCLK_FREQ_37M,
 	},
 	{
 		/* 1H period = (1100 clock) = (1100 * 1 / 74.25MHz) */
@@ -873,6 +1192,7 @@
 		.mipi_freq_idx = 1,
 		.bpp = 12,
 		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
+		.xvclk = IMX415_XVCLK_FREQ_37M,
 	},
 	{
 		.bus_fmt = MEDIA_BUS_FMT_SGBRG12_1X12,
@@ -898,6 +1218,7 @@
 		.vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
 		.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
 		.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
+		.xvclk = IMX415_XVCLK_FREQ_37M,
 	},
 	{
 		.bus_fmt = MEDIA_BUS_FMT_SGBRG12_1X12,
@@ -923,6 +1244,7 @@
 		.vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr0
 		.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
 		.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_2,//S->csi wr2
+		.xvclk = IMX415_XVCLK_FREQ_37M,
 	},
 	{
 		.bus_fmt = MEDIA_BUS_FMT_SGBRG12_1X12,
@@ -941,6 +1263,7 @@
 		.mipi_freq_idx = 0,
 		.bpp = 12,
 		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
+		.xvclk = IMX415_XVCLK_FREQ_37M,
 	},
 	{
 		.bus_fmt = MEDIA_BUS_FMT_SGBRG12_1X12,
@@ -966,6 +1289,50 @@
 		.vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
 		.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
 		.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
+		.xvclk = IMX415_XVCLK_FREQ_37M,
+	},
+};
+
+static const struct imx415_mode supported_modes_2lane[] = {
+	{
+		/* 1H period = (1100 clock) = (1100 * 1 / 74.25MHz) */
+		.bus_fmt = MEDIA_BUS_FMT_SGBRG12_1X12,
+		.width = 3864,
+		.height = 2192,
+		.max_fps = {
+			.numerator = 10000,
+			.denominator = 150000,
+		},
+		.exp_def = 0x08ca - 0x08,
+		.hts_def = 0x0898 * IMX415_2LANES * 2,
+		.vts_def = 0x08ca,
+		.global_reg_list = NULL,
+		.reg_list = imx415_linear_12bit_3864x2192_891M_regs_2lane,
+		.hdr_mode = NO_HDR,
+		.mipi_freq_idx = 1,
+		.bpp = 12,
+		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
+		.xvclk = IMX415_XVCLK_FREQ_27M,
+	},
+	{
+		/* 1H period = (1100 clock) = (1100 * 1 / 74.25MHz) */
+		.bus_fmt = MEDIA_BUS_FMT_SGBRG12_1X12,
+		.width = 1284,
+		.height = 720,
+		.max_fps = {
+			.numerator = 10000,
+			.denominator = 900000,
+		},
+		.exp_def = 0x07AB-8,
+		.hts_def = 0x01A4 * IMX415_2LANES * 2,
+		.vts_def = 0x07AB,
+		.global_reg_list = NULL,
+		.reg_list = imx415_linear_12bit_1284x720_2376M_regs_2lane,
+		.hdr_mode = NO_HDR,
+		.mipi_freq_idx = 4,
+		.bpp = 12,
+		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
+		.xvclk = IMX415_XVCLK_FREQ_27M,
 	},
 };
 
@@ -974,6 +1341,7 @@
 	MIPI_FREQ_446M,
 	MIPI_FREQ_743M,
 	MIPI_FREQ_891M,
+	MIPI_FREQ_1188M,
 };
 
 /* Write registers up to 4 at a time */
@@ -1010,10 +1378,18 @@
 {
 	u32 i;
 	int ret = 0;
-
+	if (!regs) {
+		dev_err(&client->dev, "write reg array error\n");
+		return ret;
+	}
 	for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) {
-		ret = imx415_write_reg(client, regs[i].addr,
-				       IMX415_REG_VALUE_08BIT, regs[i].val);
+		if (regs[i].addr == REG_DELAY) {
+			usleep_range(regs[i].val * 1000, regs[i].val * 1000 + 500);
+			dev_info(&client->dev, "write reg array, sleep %dms\n", regs[i].val);
+		} else {
+			ret = imx415_write_reg(client, regs[i].addr,
+				IMX415_REG_VALUE_08BIT, regs[i].val);
+		}
 	}
 	return ret;
 }
@@ -1070,9 +1446,9 @@
 	unsigned int i;
 
 	for (i = 0; i < imx415->cfg_num; i++) {
-		dist = imx415_get_reso_dist(&supported_modes[i], framefmt);
+		dist = imx415_get_reso_dist(&imx415->supported_modes[i], framefmt);
 		if ((cur_best_fit_dist == -1 || dist < cur_best_fit_dist) &&
-			supported_modes[i].bus_fmt == framefmt->code) {
+			imx415->supported_modes[i].bus_fmt == framefmt->code) {
 			cur_best_fit_dist = dist;
 			cur_best_fit = i;
 		}
@@ -1080,7 +1456,7 @@
 	dev_info(&imx415->client->dev, "%s: cur_best_fit(%d)",
 		 __func__, cur_best_fit);
 
-	return &supported_modes[cur_best_fit];
+	return &imx415->supported_modes[cur_best_fit];
 }
 
 static int __imx415_power_on(struct imx415 *imx415);
@@ -1094,8 +1470,8 @@
 	}
 	imx415->cur_mode = mode;
 	imx415->cur_vts = imx415->cur_mode->vts_def;
-	dev_dbg(&imx415->client->dev, "set fmt: cur_mode: %dx%d, hdr: %d\n",
-		mode->width, mode->height, mode->hdr_mode);
+	dev_info(&imx415->client->dev, "set fmt: cur_mode: %dx%d, hdr: %d, bpp: %d\n",
+		mode->width, mode->height, mode->hdr_mode, mode->bpp);
 }
 
 static int imx415_set_fmt(struct v4l2_subdev *sd,
@@ -1106,6 +1482,7 @@
 	const struct imx415_mode *mode;
 	s64 h_blank, vblank_def, vblank_min;
 	u64 pixel_rate = 0;
+	u8 lanes = imx415->bus_cfg.bus.mipi_csi2.num_data_lanes;
 
 	mutex_lock(&imx415->mutex);
 
@@ -1134,7 +1511,8 @@
 					 1, vblank_def);
 		__v4l2_ctrl_s_ctrl(imx415->vblank, vblank_def);
 		__v4l2_ctrl_s_ctrl(imx415->link_freq, mode->mipi_freq_idx);
-		pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * IMX415_4LANES;
+		pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] /
+			mode->bpp * 2 * lanes;
 		__v4l2_ctrl_s_ctrl_int64(imx415->pixel_rate,
 					 pixel_rate);
 	}
@@ -1185,7 +1563,7 @@
 	if (code->index >= imx415->cfg_num)
 		return -EINVAL;
 
-	code->code = supported_modes[code->index].bus_fmt;
+	code->code = imx415->supported_modes[code->index].bus_fmt;
 
 	return 0;
 }
@@ -1199,13 +1577,13 @@
 	if (fse->index >= imx415->cfg_num)
 		return -EINVAL;
 
-	if (fse->code != supported_modes[fse->index].bus_fmt)
+	if (fse->code != imx415->supported_modes[fse->index].bus_fmt)
 		return -EINVAL;
 
-	fse->min_width  = supported_modes[fse->index].width;
-	fse->max_width  = supported_modes[fse->index].width;
-	fse->max_height = supported_modes[fse->index].height;
-	fse->min_height = supported_modes[fse->index].height;
+	fse->min_width  = imx415->supported_modes[fse->index].width;
+	fse->max_width  = imx415->supported_modes[fse->index].width;
+	fse->max_height = imx415->supported_modes[fse->index].height;
+	fse->min_height = imx415->supported_modes[fse->index].height;
 
 	return 0;
 }
@@ -1227,8 +1605,9 @@
 	struct imx415 *imx415 = to_imx415(sd);
 	const struct imx415_mode *mode = imx415->cur_mode;
 	u32 val = 0;
+	u8 lanes = imx415->bus_cfg.bus.mipi_csi2.num_data_lanes;
 
-	val = 1 << (IMX415_4LANES - 1) |
+	val = 1 << (lanes - 1) |
 	      V4L2_MBUS_CSI2_CHANNEL_0 |
 	      V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
 	if (mode->hdr_mode != NO_HDR)
@@ -1687,6 +2066,7 @@
 	const struct imx415_mode *mode;
 	u64 pixel_rate = 0;
 	struct rkmodule_csi_dphy_param *dphy_param;
+	u8 lanes = imx415->bus_cfg.bus.mipi_csi2.num_data_lanes;
 
 	switch (cmd) {
 	case PREISP_CMD_SET_HDRAE_EXP:
@@ -1708,10 +2088,11 @@
 		w = imx415->cur_mode->width;
 		h = imx415->cur_mode->height;
 		for (i = 0; i < imx415->cfg_num; i++) {
-			if (w == supported_modes[i].width &&
-			    h == supported_modes[i].height &&
-			    supported_modes[i].hdr_mode == hdr->hdr_mode) {
-				imx415_change_mode(imx415, &supported_modes[i]);
+			if (w == imx415->supported_modes[i].width &&
+			    h == imx415->supported_modes[i].height &&
+			    imx415->supported_modes[i].hdr_mode == hdr->hdr_mode) {
+				dev_info(&imx415->client->dev, "set hdr cfg, set mode to %d\n", i);
+				imx415_change_mode(imx415, &imx415->supported_modes[i]);
 				break;
 			}
 		}
@@ -1741,7 +2122,8 @@
 				IMX415_VTS_MAX - mode->height,
 				1, h);
 			__v4l2_ctrl_s_ctrl(imx415->link_freq, mode->mipi_freq_idx);
-			pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * IMX415_4LANES;
+			pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] /
+				mode->bpp * 2 * lanes;
 			__v4l2_ctrl_s_ctrl_int64(imx415->pixel_rate,
 						 pixel_rate);
 			mutex_unlock(&imx415->mutex);
@@ -2045,10 +2427,6 @@
 {
 	int ret;
 	struct device *dev = &imx415->client->dev;
-
-	if (imx415->is_thunderboot)
-		return 0;
-
 	if (!IS_ERR_OR_NULL(imx415->pins_default)) {
 		ret = pinctrl_select_state(imx415->pinctrl,
 					   imx415->pins_default);
@@ -2056,26 +2434,28 @@
 			dev_err(dev, "could not set pins\n");
 	}
 
-	ret = regulator_bulk_enable(IMX415_NUM_SUPPLIES, imx415->supplies);
-	if (ret < 0) {
-		dev_err(dev, "Failed to enable regulators\n");
-		goto err_pinctrl;
-	}
-	if (!IS_ERR(imx415->power_gpio))
-		gpiod_direction_output(imx415->power_gpio, 1);
-	/* At least 500ns between power raising and XCLR */
-	/* fix power on timing if insmod this ko */
-	usleep_range(10 * 1000, 20 * 1000);
-	if (!IS_ERR(imx415->reset_gpio))
-		gpiod_direction_output(imx415->reset_gpio, 0);
+	if (!imx415->is_thunderboot) {
+		ret = regulator_bulk_enable(IMX415_NUM_SUPPLIES, imx415->supplies);
+		if (ret < 0) {
+			dev_err(dev, "Failed to enable regulators\n");
+			goto err_pinctrl;
+		}
+		if (!IS_ERR(imx415->power_gpio))
+			gpiod_direction_output(imx415->power_gpio, 1);
+		/* At least 500ns between power raising and XCLR */
+		/* fix power on timing if insmod this ko */
+		usleep_range(10 * 1000, 20 * 1000);
+		if (!IS_ERR(imx415->reset_gpio))
+			gpiod_direction_output(imx415->reset_gpio, 0);
 
-	/* At least 1us between XCLR and clk */
-	/* fix power on timing if insmod this ko */
-	usleep_range(10 * 1000, 20 * 1000);
-	ret = clk_set_rate(imx415->xvclk, IMX415_XVCLK_FREQ_37M);
+		/* At least 1us between XCLR and clk */
+		/* fix power on timing if insmod this ko */
+		usleep_range(10 * 1000, 20 * 1000);
+	}
+	ret = clk_set_rate(imx415->xvclk, imx415->cur_mode->xvclk);
 	if (ret < 0)
 		dev_warn(dev, "Failed to set xvclk rate\n");
-	if (clk_get_rate(imx415->xvclk) != IMX415_XVCLK_FREQ_37M)
+	if (clk_get_rate(imx415->xvclk) != imx415->cur_mode->xvclk)
 		dev_warn(dev, "xvclk mismatched\n");
 	ret = clk_prepare_enable(imx415->xvclk);
 	if (ret < 0) {
@@ -2084,7 +2464,8 @@
 	}
 
 	/* At least 20us between XCLR and I2C communication */
-	usleep_range(20*1000, 30*1000);
+	if (!imx415->is_thunderboot)
+		usleep_range(20*1000, 30*1000);
 
 	return 0;
 
@@ -2154,7 +2535,7 @@
 	struct imx415 *imx415 = to_imx415(sd);
 	struct v4l2_mbus_framefmt *try_fmt =
 				v4l2_subdev_get_try_format(sd, fh->pad, 0);
-	const struct imx415_mode *def_mode = &supported_modes[0];
+	const struct imx415_mode *def_mode = &imx415->supported_modes[0];
 
 	mutex_lock(&imx415->mutex);
 	/* Initialize try_fmt */
@@ -2179,11 +2560,11 @@
 	if (fie->index >= imx415->cfg_num)
 		return -EINVAL;
 
-	fie->code = supported_modes[fie->index].bus_fmt;
-	fie->width = supported_modes[fie->index].width;
-	fie->height = supported_modes[fie->index].height;
-	fie->interval = supported_modes[fie->index].max_fps;
-	fie->reserved[0] = supported_modes[fie->index].hdr_mode;
+	fie->code = imx415->supported_modes[fie->index].bus_fmt;
+	fie->width = imx415->supported_modes[fie->index].width;
+	fie->height = imx415->supported_modes[fie->index].height;
+	fie->interval = imx415->supported_modes[fie->index].max_fps;
+	fie->reserved[0] = imx415->supported_modes[fie->index].hdr_mode;
 	return 0;
 }
 
@@ -2401,8 +2782,10 @@
 	struct v4l2_ctrl_handler *handler;
 	s64 exposure_max, vblank_def;
 	u64 pixel_rate;
+	u64 max_pixel_rate;
 	u32 h_blank;
 	int ret;
+	u8 lanes = imx415->bus_cfg.bus.mipi_csi2.num_data_lanes;
 
 	handler = &imx415->ctrl_handler;
 	mode = imx415->cur_mode;
@@ -2418,9 +2801,10 @@
 	v4l2_ctrl_s_ctrl(imx415->link_freq, mode->mipi_freq_idx);
 
 	/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
-	pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * IMX415_4LANES;
+	pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * lanes;
+	max_pixel_rate = MIPI_FREQ_1188M / mode->bpp * 2 * lanes;
 	imx415->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
-		V4L2_CID_PIXEL_RATE, 0, IMX415_MAX_PIXEL_RATE,
+		V4L2_CID_PIXEL_RATE, 0, max_pixel_rate,
 		1, pixel_rate);
 
 	h_blank = mode->hts_def - mode->width;
@@ -2511,6 +2895,7 @@
 	struct device_node *node = dev->of_node;
 	struct imx415 *imx415;
 	struct v4l2_subdev *sd;
+	struct device_node *endpoint;
 	char facing[2];
 	int ret;
 	u32 i, hdr_mode = 0;
@@ -2542,16 +2927,41 @@
 		hdr_mode = NO_HDR;
 		dev_warn(dev, " Get hdr mode failed! no hdr default\n");
 	}
+
+	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+	if (!endpoint) {
+		dev_err(dev, "Failed to get endpoint\n");
+		return -EINVAL;
+	}
+
+	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
+		&imx415->bus_cfg);
+	of_node_put(endpoint);
+	if (ret) {
+		dev_err(dev, "Failed to get bus config\n");
+		return -EINVAL;
+	}
+
 	imx415->client = client;
-	imx415->cfg_num = ARRAY_SIZE(supported_modes);
+	if (imx415->bus_cfg.bus.mipi_csi2.num_data_lanes == IMX415_4LANES) {
+		imx415->supported_modes = supported_modes;
+		imx415->cfg_num = ARRAY_SIZE(supported_modes);
+	} else {
+		imx415->supported_modes = supported_modes_2lane;
+		imx415->cfg_num = ARRAY_SIZE(supported_modes_2lane);
+	}
+	dev_info(dev, "detect imx415 lane %d\n",
+		imx415->bus_cfg.bus.mipi_csi2.num_data_lanes);
+
 	for (i = 0; i < imx415->cfg_num; i++) {
-		if (hdr_mode == supported_modes[i].hdr_mode) {
-			imx415->cur_mode = &supported_modes[i];
+		if (hdr_mode == imx415->supported_modes[i].hdr_mode) {
+			imx415->cur_mode = &imx415->supported_modes[i];
 			break;
 		}
 	}
 
-	imx415->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP);
+	of_property_read_u32(node, RKMODULE_CAMERA_FASTBOOT_ENABLE,
+		&imx415->is_thunderboot);
 
 	imx415->xvclk = devm_clk_get(dev, "xvclk");
 	if (IS_ERR(imx415->xvclk)) {

--
Gitblit v1.6.2