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/gc2053.c |  396 +++++++++++++++++++++++--------------------------------
 1 files changed, 166 insertions(+), 230 deletions(-)

diff --git a/kernel/drivers/media/i2c/gc2053.c b/kernel/drivers/media/i2c/gc2053.c
index 1b027fd..8475b67 100644
--- a/kernel/drivers/media/i2c/gc2053.c
+++ b/kernel/drivers/media/i2c/gc2053.c
@@ -6,6 +6,7 @@
  *
  * V0.0X01.0X00 first version.
  * V0.0X01.0X01 add quick stream on/off
+ * V0.0X01.0X02 support slave mode
  */
 
 #include <linux/clk.h>
@@ -35,8 +36,9 @@
 #include <media/v4l2-mediabus.h>
 #include <media/v4l2-subdev.h>
 
-#define DRIVER_VERSION          KERNEL_VERSION(0, 0x01, 0x01)
+#define DRIVER_VERSION          KERNEL_VERSION(0, 0x01, 0x02)
 #define GC2053_NAME             "gc2053"
+#define GC2053_MEDIA_BUS_FMT    MEDIA_BUS_FMT_SGRBG10_1X10
 
 #define MIPI_FREQ_297M          297000000
 #define GC2053_XVCLK_FREQ       24000000
@@ -53,6 +55,8 @@
 #define GC2053_REG_VTS_L        0x42
 
 #define GC2053_REG_CTRL_MODE    0x3E
+#define GC2053_MODE_SW_STANDBY  0x11
+#define GC2053_MODE_STREAMING   0x91
 
 #define REG_NULL                0xFF
 
@@ -91,23 +95,6 @@
 #define GC2053_NUM_SUPPLIES ARRAY_SIZE(gc2053_supply_names)
 
 #define to_gc2053(sd) container_of(sd, struct gc2053, subdev)
-
-#define USE_DVP_INTERFACE         0
-
-#if USE_DVP_INTERFACE
-  #define GC2053_MEDIA_BUS_FMT    MEDIA_BUS_FMT_SRGGB8_1X8
-  #define GC2053_MODE_SW_STANDBY  0x00
-  #define GC2053_MODE_STREAMING   0x40
-#else
-  #define GC2053_MEDIA_BUS_FMT    MEDIA_BUS_FMT_SGRBG10_1X10
-  #define GC2053_MODE_SW_STANDBY  0x11
-  #define GC2053_MODE_STREAMING   0x91
-#endif
-
-enum gc2053_max_pad {
-	PAD0,
-	PAD_MAX,
-};
 
 struct regval {
 	u8 addr;
@@ -154,11 +141,12 @@
 	unsigned int        lane_num;
 	unsigned int        cfg_num;
 	unsigned int        pixel_rate;
-	u32         cur_vts;
+
 	u32         module_index;
 	const char      *module_facing;
 	const char      *module_name;
 	const char      *len_name;
+	enum rkmodule_sync_mode	sync_mode;
 	struct rkmodule_awb_cfg awb_cfg;
 	struct rkmodule_lsc_cfg lsc_cfg;
 	u8			flip;
@@ -316,173 +304,26 @@
 	{REG_NULL, 0x00},
 };
 
-/*
- * window_size=1920*1080
- * mclk=24mhz,pclk=74.25mhz
- * pixel_line_total=2200,line_frame_total=1125
- * row_time=29.629us,frame_rate=30fps
- */
-static const struct regval __maybe_unused gc2053_1920x1080_regs_dvp[] = {
-	/****system****/
-	{0xfe, 0x80},
-	{0xfe, 0x80},
-	{0xfe, 0x80},
+static __maybe_unused const struct regval gc2053_master_mode_regs[] = {
 	{0xfe, 0x00},
-	{0xf2, 0x00},
-	{0xf3, 0x0f},
-	{0xf4, 0x36},
-	{0xf5, 0xc0},
-	{0xf6, 0x44},
-	{0xf7, 0x01},
-	{0xf8, 0x63},
-	{0xf9, 0x40},
-	{0xfc, 0x8e},
-	/****CISCTL & ANALOG****/
+	{0x7f, 0x09},
+	{0x82, 0x01},
+	{0x83, 0x0c},
+	{0x84, 0x80},
+	{REG_NULL, 0x00},
+};
+
+static __maybe_unused const struct regval gc2053_slave_mode_regs[] = {
 	{0xfe, 0x00},
-	{0x87, 0x18},
-	{0xee, 0x30},
-	{0xd0, 0xb7},
-	{0x03, 0x04},
-	{0x04, 0x60},
-	{0x05, 0x04},
-	{0x06, 0x4c},
-	{0x07, 0x00},
-	{0x08, 0x11},
-	{0x09, 0x00},
-	{0x0a, 0x02},
-	{0x0b, 0x00},
-	{0x0c, 0x02},
-	{0x0d, 0x04},
-	{0x0e, 0x40},
-	{0x12, 0xe2},
-	{0x13, 0x16},
-	{0x19, 0x0a},
-	{0x21, 0x1c},
-	{0x28, 0x0a},
-	{0x29, 0x24},
-	{0x2b, 0x04},
-	{0x32, 0xf8},
-	{0x37, 0x03},
-	{0x39, 0x15},
-	{0x43, 0x07},
-	{0x44, 0x40},
-	{0x46, 0x0b},
-	{0x4b, 0x20},
-	{0x4e, 0x08},
-	{0x55, 0x20},
-	{0x66, 0x05},
-	{0x67, 0x05},
-	{0x77, 0x01},
-	{0x78, 0x00},
-	{0x7c, 0x93},
-	{0x8c, 0x12},
-	{0x8d, 0x92},
-	{0x90, 0x00},
-	{0x9d, 0x10},
-	{0xce, 0x7c},
-	{0xd2, 0x41},
-	{0xd3, 0xdc},
-	{0xe6, 0x50},
-	/*gain*/
-	{0xb6, 0xc0},
-	{0xb0, 0x70},
-	{0xb1, 0x01},
-	{0xb2, 0x00},
-	{0xb3, 0x00},
-	{0xb4, 0x00},
-	{0xb8, 0x01},
-	{0xb9, 0x00},
-	/*blk*/
-	{0x26, 0x30},
-	{0xfe, 0x01},
-	{0x40, 0x23},
-	{0x55, 0x07},
-	{0x60, 0x40},
-	{0xfe, 0x04},
-	{0x14, 0x78},
-	{0x15, 0x78},
-	{0x16, 0x78},
-	{0x17, 0x78},
-	/*window*/
-	{0xfe, 0x01},
-	{0x92, 0x00},
-	{0x94, 0x03},
-	{0x95, 0x04},
-	{0x96, 0x38},
-	{0x97, 0x07},
-	{0x98, 0x80},
-	/*ISP*/
-	{0xfe, 0x01},
-	{0x01, 0x05},
-	{0x02, 0x89},
-	{0x04, 0x01},
-	{0x07, 0xa6},
-	{0x08, 0xa9},
-	{0x09, 0xa8},
-	{0x0a, 0xa7},
-	{0x0b, 0xff},
-	{0x0c, 0xff},
-	{0x0f, 0x00},
-	{0x50, 0x1c},
-	{0x89, 0x03},
-	{0xfe, 0x04},
-	{0x28, 0x86},
-	{0x29, 0x86},
-	{0x2a, 0x86},
-	{0x2b, 0x68},
-	{0x2c, 0x68},
-	{0x2d, 0x68},
-	{0x2e, 0x68},
-	{0x2f, 0x68},
-	{0x30, 0x4f},
-	{0x31, 0x68},
-	{0x32, 0x67},
-	{0x33, 0x66},
-	{0x34, 0x66},
-	{0x35, 0x66},
-	{0x36, 0x66},
-	{0x37, 0x66},
-	{0x38, 0x62},
-	{0x39, 0x62},
-	{0x3a, 0x62},
-	{0x3b, 0x62},
-	{0x3c, 0x62},
-	{0x3d, 0x62},
-	{0x3e, 0x62},
-	{0x3f, 0x62},
-	/****DVP & MIPI****/
-	{0xfe, 0x01},
-	{0x9a, 0x06},
-	{0xfe, 0x00},
-	{0x7b, 0x2a},
-	{0x23, 0x2d},
-	{0xfe, 0x03},
-	{0x01, 0x20},
-	{0x02, 0x56},
-	{0x03, 0xb2},
-	{0x12, 0x80},
-	{0x13, 0x07},
-	{0xfe, 0x00},
+	{0x7f, 0x09},
+	{0x82, 0x0a},
+	{0x83, 0x0b},
+	{0x84, 0x80},
+	{0x85, 0x51},
 	{REG_NULL, 0x00},
 };
 
 static const struct gc2053_mode supported_modes[] = {
-#if USE_DVP_INTERFACE
-	{
-		.width = 1920,
-		.height = 1080,
-		.max_fps = {
-			.numerator = 10000,
-			.denominator = 300000,
-		},
-		.exp_def = 0x0010,
-		.hts_def = 0x0898,
-		.vts_def = 0x0465,
-		.reg_list = gc2053_1920x1080_regs_dvp,
-		.hdr_mode = NO_HDR,
-		.vc[PAD0] = 0,
-	},
-#endif
 	{
 		.width = 1920,
 		.height = 1080,
@@ -499,11 +340,9 @@
 	},
 };
 
-#if !USE_DVP_INTERFACE
 static const s64 link_freq_menu_items[] = {
 	MIPI_FREQ_297M
 };
-#endif
 
 /* sensor register write */
 static int gc2053_write_reg(struct i2c_client *client, u8 reg, u8 val)
@@ -606,7 +445,7 @@
 	return &supported_modes[cur_best_fit];
 }
 
-static uint8_t gain_reg_table[29][4] = {
+static const uint8_t gain_reg_table[29][4] = {
 	{0x00, 0x00, 0x01, 0x00},
 	{0x00, 0x10, 0x01, 0x0c},
 	{0x00, 0x20, 0x01, 0x1b},
@@ -638,7 +477,7 @@
 	{0x00, 0xce, 0x3f, 0x3f},
 };
 
-static  uint32_t gain_level_table[29] = {
+static const uint32_t gain_level_table[30] = {
 	64,
 	76,
 	91,
@@ -668,6 +507,7 @@
 	5572,
 	6552,
 	7713,
+	0xffffffff
 };
 
 static int gc2053_set_gain(struct gc2053 *gc2053, u32 gain)
@@ -675,13 +515,16 @@
 	int ret;
 	uint8_t i = 0;
 	uint8_t total = 0;
-	uint8_t temp = 0;
+	uint32_t temp = 0;
 
 	total = sizeof(gain_level_table) / sizeof(u32) - 1;
-	for (i = 0; i < total; i++) {
+	for (i = 0; i <= total; i++) {
 		if ((gain_level_table[i] <= gain) && (gain < gain_level_table[i+1]))
 			break;
 	}
+
+	if (i > total)
+		i = total;
 
 	ret = gc2053_write_reg(gc2053->client, 0xb4, gain_reg_table[i][0]);
 	ret |= gc2053_write_reg(gc2053->client, 0xb3, gain_reg_table[i][1]);
@@ -731,8 +574,13 @@
 		break;
 	case V4L2_CID_VBLANK:
 		vts = ctrl->val + gc2053->cur_mode->height;
+		/* Note: In master-slave mode, Galaxycore request slave sensor frame rate bigger than master. */
+		if (gc2053->sync_mode == INTERNAL_MASTER_MODE)
+			vts += 10;
 		ret = gc2053_write_reg(gc2053->client, GC2053_REG_VTS_H, (vts >> 8) & 0x3f);
 		ret |= gc2053_write_reg(gc2053->client, GC2053_REG_VTS_L, vts & 0xff);
+		/* TBD: master and slave not sync to streaming, but except sleep 20ms below */
+		usleep_range(20000, 50000);
 		break;
 	case V4L2_CID_HFLIP:
 		if (ctrl->val)
@@ -772,7 +620,7 @@
 					   gc2053->supplies);
 }
 
-static int __maybe_unused gc2053_parse_of_mipi(struct gc2053 *gc2053)
+static int gc2053_parse_of(struct gc2053 *gc2053)
 {
 	struct device *dev = &gc2053->client->dev;
 	struct device_node *endpoint;
@@ -795,7 +643,6 @@
 	if (2 == gc2053->lane_num) {
 		gc2053->cur_mode = &supported_modes[0];
 		gc2053->cfg_num = ARRAY_SIZE(supported_modes);
-		gc2053->cur_vts = gc2053->cur_mode->vts_def;
 
 		/*pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
 		gc2053->pixel_rate = MIPI_FREQ_297M * 2U * (gc2053->lane_num) / 10U;
@@ -811,7 +658,7 @@
 {
 	const struct gc2053_mode *mode;
 	struct v4l2_ctrl_handler *handler;
-	struct v4l2_ctrl __maybe_unused *ctrl;
+	struct v4l2_ctrl *ctrl;
 	s64 exposure_max, vblank_def;
 	u32 h_blank;
 	int ret;
@@ -823,12 +670,10 @@
 		return ret;
 	handler->lock = &gc2053->mutex;
 
-#if !USE_DVP_INTERFACE
 	ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
 					  0, 0, link_freq_menu_items);
 	if (ctrl)
 		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-#endif
 
 	v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
 			  0, gc2053->pixel_rate, 1, gc2053->pixel_rate);
@@ -1013,22 +858,41 @@
 
 static int __gc2053_start_stream(struct gc2053 *gc2053)
 {
+	struct i2c_client *client = gc2053->client;
 	int ret;
 
-	ret = gc2053_write_array(gc2053->client, gc2053->cur_mode->reg_list);
+	ret = gc2053_write_array(client, gc2053->cur_mode->reg_list);
 	if (ret)
 		return ret;
 
 	/* In case these controls are set before streaming */
 	mutex_unlock(&gc2053->mutex);
-	v4l2_ctrl_handler_setup(&gc2053->ctrl_handler);
+	ret = v4l2_ctrl_handler_setup(&gc2053->ctrl_handler);
 	mutex_lock(&gc2053->mutex);
 
-	ret = gc2053_set_flip(gc2053, gc2053->flip);
+	ret |= gc2053_set_flip(gc2053, gc2053->flip);
 	if (ret)
 		return ret;
-	return gc2053_write_reg(gc2053->client, GC2053_REG_CTRL_MODE,
+	if (gc2053->sync_mode == INTERNAL_MASTER_MODE) {
+		ret = gc2053_write_array(client, gc2053_master_mode_regs);
+		if (ret)
+			dev_err(&client->dev,
+				"write internal master mode reg failed %d\n", ret);
+	} else if (gc2053->sync_mode == EXTERNAL_MASTER_MODE) {
+		ret = gc2053_write_array(client, gc2053_slave_mode_regs);
+		if (ret)
+			dev_err(&client->dev,
+				"write external master mode reg failed %d\n", ret);
+	} else if (gc2053->sync_mode == SLAVE_MODE) {
+		ret = gc2053_write_array(gc2053->client, gc2053_slave_mode_regs);
+		if (ret)
+			dev_err(&client->dev, "write slave mode reg failed %d\n", ret);
+	}
+
+	ret = gc2053_write_reg(gc2053->client, GC2053_REG_CTRL_MODE,
 							GC2053_MODE_STREAMING);
+
+	return ret;
 }
 
 static int __gc2053_stop_stream(struct gc2053 *gc2053)
@@ -1041,10 +905,26 @@
 				  struct rkmodule_inf *inf)
 {
 	memset(inf, 0, sizeof(*inf));
-	strscpy(inf->base.sensor, GC2053_NAME, sizeof(inf->base.sensor));
-	strscpy(inf->base.module, gc2053->module_name,
+	strlcpy(inf->base.sensor, GC2053_NAME, sizeof(inf->base.sensor));
+	strlcpy(inf->base.module, gc2053->module_name,
 		sizeof(inf->base.module));
-	strscpy(inf->base.lens, gc2053->len_name, sizeof(inf->base.lens));
+	strlcpy(inf->base.lens, gc2053->len_name, sizeof(inf->base.lens));
+}
+
+static void gc2053_set_awb_cfg(struct gc2053 *gc2053,
+				   struct rkmodule_awb_cfg *cfg)
+{
+	mutex_lock(&gc2053->mutex);
+	memcpy(&gc2053->awb_cfg, cfg, sizeof(*cfg));
+	mutex_unlock(&gc2053->mutex);
+}
+
+static void gc2053_set_lsc_cfg(struct gc2053 *gc2053,
+				   struct rkmodule_lsc_cfg *cfg)
+{
+	mutex_lock(&gc2053->mutex);
+	memcpy(&gc2053->lsc_cfg, cfg, sizeof(*cfg));
+	mutex_unlock(&gc2053->mutex);
 }
 
 static long gc2053_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
@@ -1053,6 +933,7 @@
 	long ret = 0;
 	struct rkmodule_hdr_cfg *hdr_cfg;
 	u32 stream = 0;
+	u32 *sync_mode = NULL;
 
 	switch (cmd) {
 	case RKMODULE_GET_HDR_CFG:
@@ -1060,12 +941,14 @@
 		hdr_cfg->esp.mode = HDR_NORMAL_VC;
 		hdr_cfg->hdr_mode = gc2053->cur_mode->hdr_mode;
 		break;
-	case RKMODULE_SET_HDR_CFG:
-		ret = -EINVAL;
-		dev_err(&gc2053->client->dev, "gc2053 not support hdr mode\n");
-		break;
 	case RKMODULE_GET_MODULE_INFO:
 		gc2053_get_module_inf(gc2053, (struct rkmodule_inf *)arg);
+		break;
+	case RKMODULE_AWB_CFG:
+		gc2053_set_awb_cfg(gc2053, (struct rkmodule_awb_cfg *)arg);
+		break;
+	case RKMODULE_LSC_CFG:
+		gc2053_set_lsc_cfg(gc2053, (struct rkmodule_lsc_cfg *)arg);
 		break;
 	case RKMODULE_SET_QUICK_STREAM:
 
@@ -1077,6 +960,14 @@
 		else
 			ret = gc2053_write_reg(gc2053->client, GC2053_REG_CTRL_MODE,
 					       GC2053_MODE_SW_STANDBY);
+		break;
+	case RKMODULE_GET_SYNC_MODE:
+		sync_mode = (u32 *)arg;
+		*sync_mode = gc2053->sync_mode;
+		break;
+	case RKMODULE_SET_SYNC_MODE:
+		sync_mode = (u32 *)arg;
+		gc2053->sync_mode = *sync_mode;
 		break;
 	default:
 		ret = -ENOTTY;
@@ -1091,9 +982,12 @@
 {
 	void __user *up = compat_ptr(arg);
 	struct rkmodule_inf *inf;
+	struct rkmodule_awb_cfg *awb_cfg;
+	struct rkmodule_lsc_cfg *lsc_cfg;
 	struct rkmodule_hdr_cfg *hdr;
 	long ret = 0;
 	u32 stream = 0;
+	u32 sync_mode;
 
 	switch (cmd) {
 	case RKMODULE_GET_MODULE_INFO:
@@ -1110,6 +1004,36 @@
 				ret = -EFAULT;
 		}
 		kfree(inf);
+		break;
+	case RKMODULE_AWB_CFG:
+		awb_cfg = kzalloc(sizeof(*awb_cfg), GFP_KERNEL);
+		if (!awb_cfg) {
+			ret = -ENOMEM;
+			return ret;
+		}
+
+		if (copy_from_user(awb_cfg, up, sizeof(*awb_cfg))) {
+			kfree(awb_cfg);
+			return -EFAULT;
+		}
+
+		ret = gc2053_ioctl(sd, cmd, awb_cfg);
+		kfree(awb_cfg);
+		break;
+	case RKMODULE_LSC_CFG:
+		lsc_cfg = kzalloc(sizeof(*lsc_cfg), GFP_KERNEL);
+		if (!lsc_cfg) {
+			ret = -ENOMEM;
+			return ret;
+		}
+
+		if (copy_from_user(lsc_cfg, up, sizeof(*lsc_cfg))) {
+			kfree(lsc_cfg);
+			return -EFAULT;
+		}
+
+		ret = gc2053_ioctl(sd, cmd, lsc_cfg);
+		kfree(lsc_cfg);
 		break;
 	case RKMODULE_GET_HDR_CFG:
 		hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
@@ -1133,8 +1057,10 @@
 			return ret;
 		}
 
-		if (copy_from_user(hdr, up, sizeof(*hdr)))
+		if (copy_from_user(hdr, up, sizeof(*hdr))) {
+			kfree(hdr);
 			return -EFAULT;
+		}
 
 		ret = gc2053_ioctl(sd, cmd, hdr);
 		kfree(hdr);
@@ -1145,8 +1071,23 @@
 
 		ret = gc2053_ioctl(sd, cmd, &stream);
 		break;
+	case RKMODULE_GET_SYNC_MODE:
+		ret = gc2053_ioctl(sd, cmd, &sync_mode);
+		if (!ret) {
+			ret = copy_to_user(up, &sync_mode, sizeof(u32));
+			if (ret)
+				ret = -EFAULT;
+		}
+		break;
+	case RKMODULE_SET_SYNC_MODE:
+		ret = copy_from_user(&sync_mode, up, sizeof(u32));
+		if (!ret)
+			ret = gc2053_ioctl(sd, cmd, &sync_mode);
+		else
+			ret = -EFAULT;
+		break;
 	default:
-		ret = -ENOIOCTLCMD;
+		ret = -ENOTTY;
 		break;
 	}
 	return ret;
@@ -1195,22 +1136,14 @@
 	struct gc2053 *gc2053 = to_gc2053(sd);
 	const struct gc2053_mode *mode = gc2053->cur_mode;
 
-	mutex_lock(&gc2053->mutex);
 	fi->interval = mode->max_fps;
-	mutex_unlock(&gc2053->mutex);
 
 	return 0;
 }
 
-static int gc2053_g_mbus_config(struct v4l2_subdev *sd,
+static int gc2053_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
 				struct v4l2_mbus_config *config)
 {
-#if USE_DVP_INTERFACE
-	config->type = V4L2_MBUS_PARALLEL;
-	config->flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |
-			V4L2_MBUS_VSYNC_ACTIVE_LOW |
-			V4L2_MBUS_PCLK_SAMPLE_RISING;
-#else
 	struct gc2053 *gc2053 = to_gc2053(sd);
 	const struct gc2053_mode *mode = gc2053->cur_mode;
 	u32 val = 0;
@@ -1220,9 +1153,8 @@
 		V4L2_MBUS_CSI2_CHANNEL_0 |
 		V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
 
-	config->type = V4L2_MBUS_CSI2;
+	config->type = V4L2_MBUS_CSI2_DPHY;
 	config->flags = val;
-#endif
 	return 0;
 }
 static int gc2053_enum_mbus_code(struct v4l2_subdev *sd,
@@ -1409,7 +1341,6 @@
 static const struct v4l2_subdev_video_ops gc2053_video_ops = {
 	.s_stream = gc2053_s_stream,
 	.g_frame_interval = gc2053_g_frame_interval,
-	.g_mbus_config = gc2053_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops gc2053_pad_ops = {
@@ -1418,6 +1349,7 @@
 	.enum_frame_interval = gc2053_enum_frame_interval,
 	.get_fmt = gc2053_get_fmt,
 	.set_fmt = gc2053_set_fmt,
+	.get_mbus_config = gc2053_g_mbus_config,
 };
 
 static const struct v4l2_subdev_ops gc2053_subdev_ops = {
@@ -1426,7 +1358,7 @@
 	.pad    = &gc2053_pad_ops,
 };
 
-static int gc2053_runtime_resume(struct device *dev)
+static int __maybe_unused gc2053_runtime_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
@@ -1436,7 +1368,7 @@
 	return 0;
 }
 
-static int gc2053_runtime_suspend(struct device *dev)
+static int __maybe_unused gc2053_runtime_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
@@ -1460,6 +1392,7 @@
 	struct v4l2_subdev *sd;
 	char facing[2];
 	int ret;
+	const char *sync_mode_name = NULL;
 
 	dev_info(dev, "driver version: %02x.%02x.%02x",
 		DRIVER_VERSION >> 16,
@@ -1483,6 +1416,20 @@
 		dev_err(dev,
 			"could not get module information!\n");
 		return -EINVAL;
+	}
+
+	ret = of_property_read_string(node, RKMODULE_CAMERA_SYNC_MODE,
+				      &sync_mode_name);
+	if (ret) {
+		gc2053->sync_mode = NO_SYNC_MODE;
+		dev_err(dev, "could not get sync mode!\n");
+	} else {
+		if (strcmp(sync_mode_name, RKMODULE_EXTERNAL_MASTER_MODE) == 0)
+			gc2053->sync_mode = EXTERNAL_MASTER_MODE;
+		else if (strcmp(sync_mode_name, RKMODULE_INTERNAL_MASTER_MODE) == 0)
+			gc2053->sync_mode = INTERNAL_MASTER_MODE;
+		else if (strcmp(sync_mode_name, RKMODULE_SLAVE_MODE) == 0)
+			gc2053->sync_mode = SLAVE_MODE;
 	}
 
 	gc2053->xvclk = devm_clk_get(&client->dev, "xvclk");
@@ -1509,20 +1456,9 @@
 		return ret;
 	}
 
-#if USE_DVP_INTERFACE
-	gc2053->cur_mode = &supported_modes[0];
-	gc2053->cfg_num = 1;
-	gc2053->cur_vts = gc2053->cur_mode->vts_def;
-
-	gc2053->pixel_rate = gc2053->cur_mode->width *
-			     gc2053->cur_mode->height * 8 * 30 / 8;
-
-#else
-	ret = gc2053_parse_of_mipi(gc2053);
+	ret = gc2053_parse_of(gc2053);
 	if (ret != 0)
 		return -EINVAL;
-
-#endif
 
 	gc2053->pinctrl = devm_pinctrl_get(dev);
 	if (!IS_ERR(gc2053->pinctrl)) {

--
Gitblit v1.6.2