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/ov7251.c | 1001 ++++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 658 insertions(+), 343 deletions(-)

diff --git a/kernel/drivers/media/i2c/ov7251.c b/kernel/drivers/media/i2c/ov7251.c
index 75e416b..c144428 100644
--- a/kernel/drivers/media/i2c/ov7251.c
+++ b/kernel/drivers/media/i2c/ov7251.c
@@ -2,16 +2,12 @@
 /*
  * ov7251 driver
  *
- * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
  *
- * V0.0X01.0X01 add poweron function.
- * V0.0X01.0X02 fix mclk issue when probe multiple camera.
- * V0.0X01.0X03 add enum_frame_interval function.
- * V0.0X01.0X04 add quick stream on/off
- * V0.0X01.0X05 add function g_mbus_config
- * V0.0X01.0X06 support 640x480@120fps mode
+ * V0.0X01.0X01 first version
  */
 
+//#define DEBUG
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/delay.h>
@@ -19,28 +15,33 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/regulator/consumer.h>
 #include <linux/sysfs.h>
 #include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/rk-camera-module.h>
+#include <linux/rk-preisp.h>
 #include <media/media-entity.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-subdev.h>
+#include <linux/pinctrl/consumer.h>
 
-#define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x06)
+#define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x01)
 
 #ifndef V4L2_CID_DIGITAL_GAIN
 #define V4L2_CID_DIGITAL_GAIN		V4L2_CID_GAIN
 #endif
 
-/* 48Mhz */
-#define OV7251_PIXEL_RATE		(48 * 1000 * 1000)
+#define OV7251_LANES			1
+#define OV7251_BITS_PER_SAMPLE		10
+#define OV7251_LINK_FREQ_240		240000000
+
+#define PIXEL_RATE_WITH_240M_10BIT	(OV7251_LINK_FREQ_240 * 2 * \
+					OV7251_LANES / OV7251_BITS_PER_SAMPLE)
 #define OV7251_XVCLK_FREQ		24000000
 
-#define CHIP_ID				0x007750
+#define CHIP_ID				0x77
 #define OV7251_REG_CHIP_ID		0x300a
 #define OV7251_REG_MOD_VENDOR_ID	0x3d10
 #define OV7251_REG_OPT_LOAD_CTRL	0x3d81
@@ -53,7 +54,6 @@
 #define OV7251_EXPOSURE_MIN		4
 #define OV7251_EXPOSURE_STEP		0xf
 #define OV7251_VTS_MAX			0xffff
-#define OV7251_REG_VTS			0x380e
 
 #define OV7251_REG_ANALOG_GAIN		0x350a
 #define ANALOG_GAIN_MASK		0x3ff
@@ -66,23 +66,29 @@
 #define	OV7251_TEST_PATTERN_ENABLE	0x80
 #define	OV7251_TEST_PATTERN_DISABLE	0x0
 
+#define OV7251_REG_VTS			0x380e
+
+#define OV7251_MIRROR_REG		0x3821
+#define OV7251_FLIP_REG		0x3820
+
+#define OV7251_FETCH_MIRROR(VAL, ENABLE)	(ENABLE ? VAL | 0x01 : VAL & 0xf9)
+#define OV7251_FETCH_FLIP(VAL, ENABLE)		(ENABLE ? VAL | 0x01 : VAL & 0x9f)
+
+#define REG_DELAY			0xFFFE
 #define REG_NULL			0xFFFF
 
 #define OV7251_REG_VALUE_08BIT		1
 #define OV7251_REG_VALUE_16BIT		2
 #define OV7251_REG_VALUE_24BIT		3
 
-#define OV7251_NAME			"ov7251"
-#define OV7251_LANES			1
-#define PIX_FORMAT			MEDIA_BUS_FMT_Y10_1X10
-
 #define OF_CAMERA_PINCTRL_STATE_DEFAULT	"rockchip,camera_default"
 #define OF_CAMERA_PINCTRL_STATE_SLEEP	"rockchip,camera_sleep"
+#define OV7251_NAME			"ov7251"
 
 static const char * const ov7251_supply_names[] = {
 	"avdd",		/* Analog power */
 	"dovdd",	/* Digital I/O power */
-	"dvdd",		/* Digital core power  not needed*/
+	"dvdd",		/* Digital core power */
 };
 
 #define OV7251_NUM_SUPPLIES ARRAY_SIZE(ov7251_supply_names)
@@ -93,6 +99,7 @@
 };
 
 struct ov7251_mode {
+	u32 bus_fmt;
 	u32 width;
 	u32 height;
 	struct v4l2_fract max_fps;
@@ -101,6 +108,7 @@
 	u32 exp_def;
 	const struct regval *reg_list;
 	u32 hdr_mode;
+	u32 vc[PAD_MAX];
 };
 
 struct ov7251 {
@@ -109,9 +117,11 @@
 	struct gpio_desc	*reset_gpio;
 	struct gpio_desc	*pwdn_gpio;
 	struct regulator_bulk_data supplies[OV7251_NUM_SUPPLIES];
+
 	struct pinctrl		*pinctrl;
 	struct pinctrl_state	*pins_default;
 	struct pinctrl_state	*pins_sleep;
+
 	struct v4l2_subdev	subdev;
 	struct media_pad	pad;
 	struct v4l2_ctrl_handler ctrl_handler;
@@ -125,26 +135,25 @@
 	bool			streaming;
 	bool			power_on;
 	const struct ov7251_mode *cur_mode;
+	struct v4l2_fract	cur_fps;
 	u32			module_index;
 	const char		*module_facing;
 	const char		*module_name;
 	const char		*len_name;
+	u32			cur_vts;
 };
 
 #define to_ov7251(sd) container_of(sd, struct ov7251, subdev)
 
 /*
  * Xclk 24Mhz
- * Pclk 48Mhz
- * PCLK = HTS * VTS * FPS
- * linelength 775(0x302)
- * framelength 516(0x204)
- * grabwindow_width 640
- * grabwindow_height 480
- * max_framerate 120fps
- * mipi_datarate per lane 640Mbps
  */
-static const struct regval ov7251_640x480_120fps_regs[] = {
+static const struct regval ov7251_global_regs[] = {
+	{REG_NULL, 0x00},
+};
+
+
+static __maybe_unused const struct regval ov7251_640x480_120fps_regs[] = {
 	{0x0103, 0x01},
 	{0x0100, 0x00},
 	{0x3005, 0x00},
@@ -289,159 +298,424 @@
 
 /*
  * Xclk 24Mhz
- * Pclk 48Mhz
- * PCLK = HTS * VTS * FPS
- * linelength 928(0x3a0)
- * framelength 1720(0x6b8)
- * grabwindow_width 640
- * grabwindow_height 480
  * max_framerate 30fps
- * mipi_datarate per lane 640Mbps
+ * mipi_datarate per lane 630Mbps, 2lane
  */
-static const struct regval ov7251_640x480_30fps_regs[] = {
-	{0x0100, 0x00},
-	{0x0103, 0x01},
-	{0x3001, 0x62},
-	{0x3005, 0x00},
-	{0x3012, 0xc0},
-	{0x3013, 0xd2},
-	{0x3014, 0x04},
-	{0x3016, 0x10},
-	{0x3017, 0x00},
-	{0x3018, 0x00},
-	{0x301a, 0x00},
-	{0x301b, 0x00},
-	{0x301c, 0x20},
-	{0x3023, 0x05},
-	{0x3037, 0xf0},
-	{0x3098, 0x04},
-	{0x3099, 0x28},
-	{0x309a, 0x05},
-	{0x309b, 0x04},
-	{0x30b0, 0x0a},
-	{0x30b1, 0x01},
-	{0x30b3, 0x64},
-	{0x30b4, 0x03},
-	{0x30b5, 0x05},
-	{0x3106, 0xda},
-	{0x3500, 0x00},
-	{0x3501, 0x1f},
-	{0x3502, 0x80},
-	{0x3503, 0x07},
-	{0x3509, 0x10},
-	{0x350b, 0x10},
-	{0x3600, 0x1c},
-	{0x3602, 0x62},
-	{0x3620, 0xb7},
-	{0x3622, 0x04},
-	{0x3626, 0x21},
-	{0x3627, 0x30},
-	{0x3630, 0x44},
-	{0x3631, 0x35},
-	{0x3634, 0x60},
-	{0x3636, 0x00},
-	{0x3662, 0x01},
-	{0x3663, 0x70},
-	{0x3664, 0xf0},
-	{0x3666, 0x0a},
-	{0x3669, 0x1a},
-	{0x366a, 0x00},
-	{0x366b, 0x50},
-	{0x3673, 0x01},
-	{0x3674, 0xff},
-	{0x3675, 0x03},
-	{0x3705, 0xc1},
-	{0x3709, 0x40},
-	{0x373c, 0x08},
-	{0x3742, 0x00},
-	{0x3757, 0xb3},
-	{0x3788, 0x00},
-	{0x37a8, 0x01},
-	{0x37a9, 0xc0},
-	{0x3800, 0x00},
-	{0x3801, 0x04},
-	{0x3802, 0x00},
-	{0x3803, 0x04},
-	{0x3804, 0x02},
-	{0x3805, 0x8b},
-	{0x3806, 0x01},
-	{0x3807, 0xeb},
-	{0x3808, 0x02},
-	{0x3809, 0x80},
-	{0x380a, 0x01},
-	{0x380b, 0xe0},
-	{0x380c, 0x03},
-	{0x380d, 0xa0},
-	{0x380e, 0x06},
-	{0x380f, 0xb8},
-	{0x3810, 0x00},
-	{0x3811, 0x02},
-	{0x3812, 0x00},
-	{0x3813, 0x02},
-	{0x3814, 0x11},
-	{0x3815, 0x11},
-	{0x3820, 0x40},
-	{0x3821, 0x00},
-	{0x382f, 0x0e},
-	{0x3832, 0x00},
-	{0x3833, 0x05},
-	{0x3834, 0x00},
-	{0x3835, 0x0c},
-	{0x3837, 0x00},
-	{0x3b80, 0x00},
-	{0x3b81, 0xa5},
-	{0x3b82, 0x10},
-	{0x3b83, 0x00},
-	{0x3b84, 0x08},
-	{0x3b85, 0x00},
-	{0x3b86, 0x01},
-	{0x3b87, 0x00},
-	{0x3b88, 0x00},
-	{0x3b89, 0x00},
-	{0x3b8a, 0x00},
-	{0x3b8b, 0x05},
-	{0x3b8c, 0x00},
-	{0x3b8d, 0x00},
-	{0x3b8e, 0x00},
-	{0x3b8f, 0x1a},
-	{0x3b94, 0x05},
-	{0x3b95, 0xf2},
-	{0x3b96, 0x40},
-	{0x3c00, 0x89},
-	{0x3c01, 0x63},
-	{0x3c02, 0x01},
-	{0x3c03, 0x00},
-	{0x3c04, 0x00},
-	{0x3c05, 0x03},
-	{0x3c06, 0x00},
-	{0x3c07, 0x06},
-	{0x3c0c, 0x01},
-	{0x3c0d, 0xd0},
-	{0x3c0e, 0x02},
-	{0x3c0f, 0x04},
-	{0x4001, 0x42},
-	{0x4004, 0x04},
-	{0x4005, 0x00},
-	{0x404e, 0x01},
-	{0x4241, 0x00},
-	{0x4242, 0x00},
-	{0x4300, 0xff},
-	{0x4301, 0x00},
-	{0x4501, 0x48},
-	{0x4600, 0x00},
-	{0x4601, 0x4e},
-	{0x4801, 0x0f},
-	{0x4806, 0x0f},
-	{0x4819, 0xaa},
-	{0x4823, 0x3e},
-	{0x4837, 0x19},
-	{0x4a0d, 0x00},
-	{0x4a47, 0x7f},
-	{0x4a49, 0xf0},
-	{0x4a4b, 0x30},
-	{0x5000, 0x85},
-	{0x5001, 0x80},
-	{REG_NULL, 0x00},
+static __maybe_unused const struct regval ov7251_setting_vga_30fps[] = {
+	{ 0x3005, 0x00 },
+	{ 0x3012, 0xc0 },
+	{ 0x3013, 0xd2 },
+	{ 0x3014, 0x04 },
+	{ 0x3016, 0xf0 },
+	{ 0x3017, 0xf0 },
+	{ 0x3018, 0xf0 },
+	{ 0x301a, 0xf0 },
+	{ 0x301b, 0xf0 },
+	{ 0x301c, 0xf0 },
+	{ 0x3023, 0x05 },
+	{ 0x3037, 0xf0 },
+	{ 0x3098, 0x04 }, /* pll2 pre divider */
+	{ 0x3099, 0x28 }, /* pll2 multiplier */
+	{ 0x309a, 0x05 }, /* pll2 sys divider */
+	{ 0x309b, 0x04 }, /* pll2 adc divider */
+	{ 0x309d, 0x00 }, /* pll2 divider */
+	{ 0x30b0, 0x0a }, /* pll1 pix divider */
+	{ 0x30b1, 0x01 }, /* pll1 divider */
+	{ 0x30b3, 0x64 }, /* pll1 multiplier */
+	{ 0x30b4, 0x03 }, /* pll1 pre divider */
+	{ 0x30b5, 0x05 }, /* pll1 mipi divider */
+	{ 0x3106, 0xda },
+	{ 0x3503, 0x07 },
+	{ 0x3509, 0x10 },
+	{ 0x3600, 0x1c },
+	{ 0x3602, 0x62 },
+	{ 0x3620, 0xb7 },
+	{ 0x3622, 0x04 },
+	{ 0x3626, 0x21 },
+	{ 0x3627, 0x30 },
+	{ 0x3630, 0x44 },
+	{ 0x3631, 0x35 },
+	{ 0x3634, 0x60 },
+	{ 0x3636, 0x00 },
+	{ 0x3662, 0x01 },
+	{ 0x3663, 0x70 },
+	{ 0x3664, 0x50 },
+	{ 0x3666, 0x0a },
+	{ 0x3669, 0x1a },
+	{ 0x366a, 0x00 },
+	{ 0x366b, 0x50 },
+	{ 0x3673, 0x01 },
+	{ 0x3674, 0xff },
+	{ 0x3675, 0x03 },
+	{ 0x3705, 0xc1 },
+	{ 0x3709, 0x40 },
+	{ 0x373c, 0x08 },
+	{ 0x3742, 0x00 },
+	{ 0x3757, 0xb3 },
+	{ 0x3788, 0x00 },
+	{ 0x37a8, 0x01 },
+	{ 0x37a9, 0xc0 },
+	{ 0x3800, 0x00 },
+	{ 0x3801, 0x04 },
+	{ 0x3802, 0x00 },
+	{ 0x3803, 0x04 },
+	{ 0x3804, 0x02 },
+	{ 0x3805, 0x8b },
+	{ 0x3806, 0x01 },
+	{ 0x3807, 0xeb },
+	{ 0x3808, 0x02 }, /* width high */
+	{ 0x3809, 0x80 }, /* width low */
+	{ 0x380a, 0x01 }, /* height high */
+	{ 0x380b, 0xe0 }, /* height low */
+	{ 0x380c, 0x03 }, /* total horiz timing high */
+	{ 0x380d, 0xa0 }, /* total horiz timing low */
+	{ 0x380e, 0x06 }, /* total vertical timing high */
+	{ 0x380f, 0xbc }, /* total vertical timing low */
+	{ 0x3810, 0x00 },
+	{ 0x3811, 0x04 },
+	{ 0x3812, 0x00 },
+	{ 0x3813, 0x05 },
+	{ 0x3814, 0x11 },
+	{ 0x3815, 0x11 },
+	{ 0x3820, 0x40 },
+	{ 0x3821, 0x00 },
+	{ 0x382f, 0x0e },
+	{ 0x3832, 0x00 },
+	{ 0x3833, 0x05 },
+	{ 0x3834, 0x00 },
+	{ 0x3835, 0x0c },
+	{ 0x3837, 0x00 },
+	{ 0x3b80, 0x00 },
+	{ 0x3b81, 0xa5 },
+	{ 0x3b82, 0x10 },
+	{ 0x3b83, 0x00 },
+	{ 0x3b84, 0x08 },
+	{ 0x3b85, 0x00 },
+	{ 0x3b86, 0x01 },
+	{ 0x3b87, 0x00 },
+	{ 0x3b88, 0x00 },
+	{ 0x3b89, 0x00 },
+	{ 0x3b8a, 0x00 },
+	{ 0x3b8b, 0x05 },
+	{ 0x3b8c, 0x00 },
+	{ 0x3b8d, 0x00 },
+	{ 0x3b8e, 0x00 },
+	{ 0x3b8f, 0x1a },
+	{ 0x3b94, 0x05 },
+	{ 0x3b95, 0xf2 },
+	{ 0x3b96, 0x40 },
+	{ 0x3c00, 0x89 },
+	{ 0x3c01, 0x63 },
+	{ 0x3c02, 0x01 },
+	{ 0x3c03, 0x00 },
+	{ 0x3c04, 0x00 },
+	{ 0x3c05, 0x03 },
+	{ 0x3c06, 0x00 },
+	{ 0x3c07, 0x06 },
+	{ 0x3c0c, 0x01 },
+	{ 0x3c0d, 0xd0 },
+	{ 0x3c0e, 0x02 },
+	{ 0x3c0f, 0x0a },
+	{ 0x4001, 0x42 },
+	{ 0x4004, 0x04 },
+	{ 0x4005, 0x00 },
+	{ 0x404e, 0x01 },
+	{ 0x4300, 0xff },
+	{ 0x4301, 0x00 },
+	{ 0x4315, 0x00 },
+	{ 0x4501, 0x48 },
+	{ 0x4600, 0x00 },
+	{ 0x4601, 0x4e },
+	{ 0x4801, 0x0f },
+	{ 0x4806, 0x0f },
+	{ 0x4819, 0xaa },
+	{ 0x4823, 0x3e },
+	{ 0x4837, 0x19 },
+	{ 0x4a0d, 0x00 },
+	{ 0x4a47, 0x7f },
+	{ 0x4a49, 0xf0 },
+	{ 0x4a4b, 0x30 },
+	{ 0x5000, 0x85 },
+	{ 0x5001, 0x80 },
+	{REG_NULL, 0x00 },
+};
+
+static __maybe_unused const struct regval ov7251_setting_vga_60fps[] = {
+	{ 0x3005, 0x00 },
+	{ 0x3012, 0xc0 },
+	{ 0x3013, 0xd2 },
+	{ 0x3014, 0x04 },
+	{ 0x3016, 0x10 },
+	{ 0x3017, 0x00 },
+	{ 0x3018, 0x00 },
+	{ 0x301a, 0x00 },
+	{ 0x301b, 0x00 },
+	{ 0x301c, 0x00 },
+	{ 0x3023, 0x05 },
+	{ 0x3037, 0xf0 },
+	{ 0x3098, 0x04 }, /* pll2 pre divider */
+	{ 0x3099, 0x28 }, /* pll2 multiplier */
+	{ 0x309a, 0x05 }, /* pll2 sys divider */
+	{ 0x309b, 0x04 }, /* pll2 adc divider */
+	{ 0x309d, 0x00 }, /* pll2 divider */
+	{ 0x30b0, 0x0a }, /* pll1 pix divider */
+	{ 0x30b1, 0x01 }, /* pll1 divider */
+	{ 0x30b3, 0x64 }, /* pll1 multiplier */
+	{ 0x30b4, 0x03 }, /* pll1 pre divider */
+	{ 0x30b5, 0x05 }, /* pll1 mipi divider */
+	{ 0x3106, 0xda },
+	{ 0x3503, 0x07 },
+	{ 0x3509, 0x10 },
+	{ 0x3600, 0x1c },
+	{ 0x3602, 0x62 },
+	{ 0x3620, 0xb7 },
+	{ 0x3622, 0x04 },
+	{ 0x3626, 0x21 },
+	{ 0x3627, 0x30 },
+	{ 0x3630, 0x44 },
+	{ 0x3631, 0x35 },
+	{ 0x3634, 0x60 },
+	{ 0x3636, 0x00 },
+	{ 0x3662, 0x01 },
+	{ 0x3663, 0x70 },
+	{ 0x3664, 0x50 },
+	{ 0x3666, 0x0a },
+	{ 0x3669, 0x1a },
+	{ 0x366a, 0x00 },
+	{ 0x366b, 0x50 },
+	{ 0x3673, 0x01 },
+	{ 0x3674, 0xff },
+	{ 0x3675, 0x03 },
+	{ 0x3705, 0xc1 },
+	{ 0x3709, 0x40 },
+	{ 0x373c, 0x08 },
+	{ 0x3742, 0x00 },
+	{ 0x3757, 0xb3 },
+	{ 0x3788, 0x00 },
+	{ 0x37a8, 0x01 },
+	{ 0x37a9, 0xc0 },
+	{ 0x3800, 0x00 },
+	{ 0x3801, 0x04 },
+	{ 0x3802, 0x00 },
+	{ 0x3803, 0x04 },
+	{ 0x3804, 0x02 },
+	{ 0x3805, 0x8b },
+	{ 0x3806, 0x01 },
+	{ 0x3807, 0xeb },
+	{ 0x3808, 0x02 }, /* width high */
+	{ 0x3809, 0x80 }, /* width low */
+	{ 0x380a, 0x01 }, /* height high */
+	{ 0x380b, 0xe0 }, /* height low */
+	{ 0x380c, 0x03 }, /* total horiz timing high */
+	{ 0x380d, 0xa0 }, /* total horiz timing low */
+	{ 0x380e, 0x03 }, /* total vertical timing high */
+	{ 0x380f, 0x5c }, /* total vertical timing low */
+	{ 0x3810, 0x00 },
+	{ 0x3811, 0x04 },
+	{ 0x3812, 0x00 },
+	{ 0x3813, 0x05 },
+	{ 0x3814, 0x11 },
+	{ 0x3815, 0x11 },
+	{ 0x3820, 0x40 },
+	{ 0x3821, 0x00 },
+	{ 0x382f, 0x0e },
+	{ 0x3832, 0x00 },
+	{ 0x3833, 0x05 },
+	{ 0x3834, 0x00 },
+	{ 0x3835, 0x0c },
+	{ 0x3837, 0x00 },
+	{ 0x3b80, 0x00 },
+	{ 0x3b81, 0xa5 },
+	{ 0x3b82, 0x10 },
+	{ 0x3b83, 0x00 },
+	{ 0x3b84, 0x08 },
+	{ 0x3b85, 0x00 },
+	{ 0x3b86, 0x01 },
+	{ 0x3b87, 0x00 },
+	{ 0x3b88, 0x00 },
+	{ 0x3b89, 0x00 },
+	{ 0x3b8a, 0x00 },
+	{ 0x3b8b, 0x05 },
+	{ 0x3b8c, 0x00 },
+	{ 0x3b8d, 0x00 },
+	{ 0x3b8e, 0x00 },
+	{ 0x3b8f, 0x1a },
+	{ 0x3b94, 0x05 },
+	{ 0x3b95, 0xf2 },
+	{ 0x3b96, 0x40 },
+	{ 0x3c00, 0x89 },
+	{ 0x3c01, 0x63 },
+	{ 0x3c02, 0x01 },
+	{ 0x3c03, 0x00 },
+	{ 0x3c04, 0x00 },
+	{ 0x3c05, 0x03 },
+	{ 0x3c06, 0x00 },
+	{ 0x3c07, 0x06 },
+	{ 0x3c0c, 0x01 },
+	{ 0x3c0d, 0xd0 },
+	{ 0x3c0e, 0x02 },
+	{ 0x3c0f, 0x0a },
+	{ 0x4001, 0x42 },
+	{ 0x4004, 0x04 },
+	{ 0x4005, 0x00 },
+	{ 0x404e, 0x01 },
+	{ 0x4300, 0xff },
+	{ 0x4301, 0x00 },
+	{ 0x4315, 0x00 },
+	{ 0x4501, 0x48 },
+	{ 0x4600, 0x00 },
+	{ 0x4601, 0x4e },
+	{ 0x4801, 0x0f },
+	{ 0x4806, 0x0f },
+	{ 0x4819, 0xaa },
+	{ 0x4823, 0x3e },
+	{ 0x4837, 0x19 },
+	{ 0x4a0d, 0x00 },
+	{ 0x4a47, 0x7f },
+	{ 0x4a49, 0xf0 },
+	{ 0x4a4b, 0x30 },
+	{ 0x5000, 0x85 },
+	{ 0x5001, 0x80 },
+	{REG_NULL, 0x00 },
+};
+
+static __maybe_unused const struct regval ov7251_setting_vga_90fps[] = {
+	{ 0x3005, 0x00 },
+	{ 0x3012, 0xc0 },
+	{ 0x3013, 0xd2 },
+	{ 0x3014, 0x04 },
+	{ 0x3016, 0x10 },
+	{ 0x3017, 0x00 },
+	{ 0x3018, 0x00 },
+	{ 0x301a, 0x00 },
+	{ 0x301b, 0x00 },
+	{ 0x301c, 0x00 },
+	{ 0x3023, 0x05 },
+	{ 0x3037, 0xf0 },
+	{ 0x3098, 0x04 }, /* pll2 pre divider */
+	{ 0x3099, 0x28 }, /* pll2 multiplier */
+	{ 0x309a, 0x05 }, /* pll2 sys divider */
+	{ 0x309b, 0x04 }, /* pll2 adc divider */
+	{ 0x309d, 0x00 }, /* pll2 divider */
+	{ 0x30b0, 0x0a }, /* pll1 pix divider */
+	{ 0x30b1, 0x01 }, /* pll1 divider */
+	{ 0x30b3, 0x64 }, /* pll1 multiplier */
+	{ 0x30b4, 0x03 }, /* pll1 pre divider */
+	{ 0x30b5, 0x05 }, /* pll1 mipi divider */
+	{ 0x3106, 0xda },
+	{ 0x3503, 0x07 },
+	{ 0x3509, 0x10 },
+	{ 0x3600, 0x1c },
+	{ 0x3602, 0x62 },
+	{ 0x3620, 0xb7 },
+	{ 0x3622, 0x04 },
+	{ 0x3626, 0x21 },
+	{ 0x3627, 0x30 },
+	{ 0x3630, 0x44 },
+	{ 0x3631, 0x35 },
+	{ 0x3634, 0x60 },
+	{ 0x3636, 0x00 },
+	{ 0x3662, 0x01 },
+	{ 0x3663, 0x70 },
+	{ 0x3664, 0x50 },
+	{ 0x3666, 0x0a },
+	{ 0x3669, 0x1a },
+	{ 0x366a, 0x00 },
+	{ 0x366b, 0x50 },
+	{ 0x3673, 0x01 },
+	{ 0x3674, 0xff },
+	{ 0x3675, 0x03 },
+	{ 0x3705, 0xc1 },
+	{ 0x3709, 0x40 },
+	{ 0x373c, 0x08 },
+	{ 0x3742, 0x00 },
+	{ 0x3757, 0xb3 },
+	{ 0x3788, 0x00 },
+	{ 0x37a8, 0x01 },
+	{ 0x37a9, 0xc0 },
+	{ 0x3800, 0x00 },
+	{ 0x3801, 0x04 },
+	{ 0x3802, 0x00 },
+	{ 0x3803, 0x04 },
+	{ 0x3804, 0x02 },
+	{ 0x3805, 0x8b },
+	{ 0x3806, 0x01 },
+	{ 0x3807, 0xeb },
+	{ 0x3808, 0x02 }, /* width high */
+	{ 0x3809, 0x80 }, /* width low */
+	{ 0x380a, 0x01 }, /* height high */
+	{ 0x380b, 0xe0 }, /* height low */
+	{ 0x380c, 0x03 }, /* total horiz timing high */
+	{ 0x380d, 0xa0 }, /* total horiz timing low */
+	{ 0x380e, 0x02 }, /* total vertical timing high */
+	{ 0x380f, 0x3c }, /* total vertical timing low */
+	{ 0x3810, 0x00 },
+	{ 0x3811, 0x04 },
+	{ 0x3812, 0x00 },
+	{ 0x3813, 0x05 },
+	{ 0x3814, 0x11 },
+	{ 0x3815, 0x11 },
+	{ 0x3820, 0x40 },
+	{ 0x3821, 0x00 },
+	{ 0x382f, 0x0e },
+	{ 0x3832, 0x00 },
+	{ 0x3833, 0x05 },
+	{ 0x3834, 0x00 },
+	{ 0x3835, 0x0c },
+	{ 0x3837, 0x00 },
+	{ 0x3b80, 0x00 },
+	{ 0x3b81, 0xa5 },
+	{ 0x3b82, 0x10 },
+	{ 0x3b83, 0x00 },
+	{ 0x3b84, 0x08 },
+	{ 0x3b85, 0x00 },
+	{ 0x3b86, 0x01 },
+	{ 0x3b87, 0x00 },
+	{ 0x3b88, 0x00 },
+	{ 0x3b89, 0x00 },
+	{ 0x3b8a, 0x00 },
+	{ 0x3b8b, 0x05 },
+	{ 0x3b8c, 0x00 },
+	{ 0x3b8d, 0x00 },
+	{ 0x3b8e, 0x00 },
+	{ 0x3b8f, 0x1a },
+	{ 0x3b94, 0x05 },
+	{ 0x3b95, 0xf2 },
+	{ 0x3b96, 0x40 },
+	{ 0x3c00, 0x89 },
+	{ 0x3c01, 0x63 },
+	{ 0x3c02, 0x01 },
+	{ 0x3c03, 0x00 },
+	{ 0x3c04, 0x00 },
+	{ 0x3c05, 0x03 },
+	{ 0x3c06, 0x00 },
+	{ 0x3c07, 0x06 },
+	{ 0x3c0c, 0x01 },
+	{ 0x3c0d, 0xd0 },
+	{ 0x3c0e, 0x02 },
+	{ 0x3c0f, 0x0a },
+	{ 0x4001, 0x42 },
+	{ 0x4004, 0x04 },
+	{ 0x4005, 0x00 },
+	{ 0x404e, 0x01 },
+	{ 0x4300, 0xff },
+	{ 0x4301, 0x00 },
+	{ 0x4315, 0x00 },
+	{ 0x4501, 0x48 },
+	{ 0x4600, 0x00 },
+	{ 0x4601, 0x4e },
+	{ 0x4801, 0x0f },
+	{ 0x4806, 0x0f },
+	{ 0x4819, 0xaa },
+	{ 0x4823, 0x3e },
+	{ 0x4837, 0x19 },
+	{ 0x4a0d, 0x00 },
+	{ 0x4a47, 0x7f },
+	{ 0x4a49, 0xf0 },
+	{ 0x4a4b, 0x30 },
+	{ 0x5000, 0x85 },
+	{ 0x5001, 0x80 },
+	{REG_NULL, 0x00 },
 };
 
 static const struct ov7251_mode supported_modes[] = {
@@ -455,44 +729,34 @@
 		.exp_def = 0x00f8,
 		.hts_def = 0x03a1,
 		.vts_def = 0x021a,
+		.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
 		.reg_list = ov7251_640x480_120fps_regs,
-		.hdr_mode = 0,
-	},
-	{
-		.width = 640,
-		.height = 480,
-		.max_fps = {
-			.numerator = 10000,
-			.denominator = 300000,
-		},
-		.exp_def = 0x061c,
-		.hts_def = 0x03a0,
-		.vts_def = 0x06b8,
-		.reg_list = ov7251_640x480_30fps_regs,
-		.hdr_mode = 0,
+		.hdr_mode = NO_HDR,
+		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
 	}
 };
 
-#define OV7251_LINK_FREQ_320MHZ		320000000
 static const s64 link_freq_menu_items[] = {
-	OV7251_LINK_FREQ_320MHZ
+	OV7251_LINK_FREQ_240
 };
 
 static const char * const ov7251_test_pattern_menu[] = {
 	"Disabled",
-	"Vertical Color Bar",
+	"Vertical Color Bar Type 1",
+	"Vertical Color Bar Type 2",
+	"Vertical Color Bar Type 3",
+	"Vertical Color Bar Type 4"
 };
 
 /* Write registers up to 4 at a time */
 static int ov7251_write_reg(struct i2c_client *client, u16 reg,
-			    int len, u32 val)
+			    u32 len, u32 val)
 {
 	u32 buf_i, val_i;
 	u8 buf[6];
 	u8 *val_p;
 	__be32 val_be;
 
-	usleep_range(1500, 1600);
 	if (len > 4)
 		return -EINVAL;
 
@@ -509,26 +773,25 @@
 
 	if (i2c_master_send(client, buf, len + 2) != len + 2)
 		return -EIO;
-
 	return 0;
 }
 
 static int ov7251_write_array(struct i2c_client *client,
-			      const struct regval *regs)
+			       const struct regval *regs)
 {
 	u32 i;
 	int ret = 0;
 
-	for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++)
+	for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) {
 		ret = ov7251_write_reg(client, regs[i].addr,
-				       OV7251_REG_VALUE_08BIT, regs[i].val);
-
+					OV7251_REG_VALUE_08BIT, regs[i].val);
+	}
 	return ret;
 }
 
 /* Read registers up to 4 at a time */
 static int ov7251_read_reg(struct i2c_client *client, u16 reg, unsigned int len,
-			   u32 *val)
+			    u32 *val)
 {
 	struct i2c_msg msgs[2];
 	u8 *data_be_p;
@@ -561,8 +824,10 @@
 	return 0;
 }
 
+
+
 static int ov7251_get_reso_dist(const struct ov7251_mode *mode,
-				struct v4l2_mbus_framefmt *framefmt)
+				 struct v4l2_mbus_framefmt *framefmt)
 {
 	return abs(mode->width - framefmt->width) +
 	       abs(mode->height - framefmt->height);
@@ -575,7 +840,7 @@
 	int dist;
 	int cur_best_fit = 0;
 	int cur_best_fit_dist = -1;
-	size_t i;
+	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
 		dist = ov7251_get_reso_dist(&supported_modes[i], framefmt);
@@ -589,8 +854,8 @@
 }
 
 static int ov7251_set_fmt(struct v4l2_subdev *sd,
-			  struct v4l2_subdev_pad_config *cfg,
-			  struct v4l2_subdev_format *fmt)
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
 {
 	struct ov7251 *ov7251 = to_ov7251(sd);
 	const struct ov7251_mode *mode;
@@ -599,7 +864,7 @@
 	mutex_lock(&ov7251->mutex);
 
 	mode = ov7251_find_best_fit(fmt);
-	fmt->format.code = PIX_FORMAT;
+	fmt->format.code = mode->bus_fmt;
 	fmt->format.width = mode->width;
 	fmt->format.height = mode->height;
 	fmt->format.field = V4L2_FIELD_NONE;
@@ -619,6 +884,7 @@
 		__v4l2_ctrl_modify_range(ov7251->vblank, vblank_def,
 					 OV7251_VTS_MAX - mode->height,
 					 1, vblank_def);
+		ov7251->cur_fps = mode->max_fps;
 	}
 
 	mutex_unlock(&ov7251->mutex);
@@ -627,8 +893,8 @@
 }
 
 static int ov7251_get_fmt(struct v4l2_subdev *sd,
-			  struct v4l2_subdev_pad_config *cfg,
-			  struct v4l2_subdev_format *fmt)
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
 {
 	struct ov7251 *ov7251 = to_ov7251(sd);
 	const struct ov7251_mode *mode = ov7251->cur_mode;
@@ -644,8 +910,13 @@
 	} else {
 		fmt->format.width = mode->width;
 		fmt->format.height = mode->height;
-		fmt->format.code = PIX_FORMAT;
+		fmt->format.code = mode->bus_fmt;
 		fmt->format.field = V4L2_FIELD_NONE;
+		/* format info: width/height/data type/virctual channel */
+		if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR)
+			fmt->reserved[0] = mode->vc[fmt->pad];
+		else
+			fmt->reserved[0] = mode->vc[PAD0];
 	}
 	mutex_unlock(&ov7251->mutex);
 
@@ -653,24 +924,26 @@
 }
 
 static int ov7251_enum_mbus_code(struct v4l2_subdev *sd,
-				 struct v4l2_subdev_pad_config *cfg,
-				 struct v4l2_subdev_mbus_code_enum *code)
+				  struct v4l2_subdev_pad_config *cfg,
+				  struct v4l2_subdev_mbus_code_enum *code)
 {
+	struct ov7251 *ov7251 = to_ov7251(sd);
+
 	if (code->index != 0)
 		return -EINVAL;
-	code->code = PIX_FORMAT;
+	code->code = ov7251->cur_mode->bus_fmt;
 
 	return 0;
 }
 
 static int ov7251_enum_frame_sizes(struct v4l2_subdev *sd,
-				   struct v4l2_subdev_pad_config *cfg,
-				   struct v4l2_subdev_frame_size_enum *fse)
+				    struct v4l2_subdev_pad_config *cfg,
+				    struct v4l2_subdev_frame_size_enum *fse)
 {
 	if (fse->index >= ARRAY_SIZE(supported_modes))
 		return -EINVAL;
 
-	if (fse->code != PIX_FORMAT)
+	if (fse->code != supported_modes[0].bus_fmt)
 		return -EINVAL;
 
 	fse->min_width  = supported_modes[fse->index].width;
@@ -695,20 +968,42 @@
 }
 
 static int ov7251_g_frame_interval(struct v4l2_subdev *sd,
-				   struct v4l2_subdev_frame_interval *fi)
+				    struct v4l2_subdev_frame_interval *fi)
 {
 	struct ov7251 *ov7251 = to_ov7251(sd);
 	const struct ov7251_mode *mode = ov7251->cur_mode;
 
-	mutex_lock(&ov7251->mutex);
-	fi->interval = mode->max_fps;
-	mutex_unlock(&ov7251->mutex);
+	if (ov7251->streaming)
+		fi->interval = ov7251->cur_fps;
+	else
+		fi->interval = mode->max_fps;
+
+	return 0;
+}
+
+static int ov7251_g_mbus_config(struct v4l2_subdev *sd,
+				unsigned int pad_id,
+				struct v4l2_mbus_config *config)
+{
+	struct ov7251 *ov7251 = to_ov7251(sd);
+	const struct ov7251_mode *mode = ov7251->cur_mode;
+	u32 val = 1 << (OV7251_LANES - 1) |
+		V4L2_MBUS_CSI2_CHANNEL_0 |
+		V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+	if (mode->hdr_mode != NO_HDR)
+		val |= V4L2_MBUS_CSI2_CHANNEL_1;
+	if (mode->hdr_mode == HDR_X3)
+		val |= V4L2_MBUS_CSI2_CHANNEL_2;
+
+	config->type = V4L2_MBUS_CSI2_DPHY;
+	config->flags = val;
 
 	return 0;
 }
 
 static void ov7251_get_module_inf(struct ov7251 *ov7251,
-				  struct rkmodule_inf *inf)
+				   struct rkmodule_inf *inf)
 {
 	memset(inf, 0, sizeof(*inf));
 	strscpy(inf->base.sensor, OV7251_NAME, sizeof(inf->base.sensor));
@@ -721,6 +1016,7 @@
 {
 	struct ov7251 *ov7251 = to_ov7251(sd);
 	struct rkmodule_hdr_cfg *hdr;
+	u32 i, h, w;
 	long ret = 0;
 	u32 stream = 0;
 
@@ -735,20 +1031,44 @@
 		break;
 	case RKMODULE_SET_HDR_CFG:
 		hdr = (struct rkmodule_hdr_cfg *)arg;
-		if (hdr->hdr_mode != 0)
-			ret = -1;
+		w = ov7251->cur_mode->width;
+		h = ov7251->cur_mode->height;
+		for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
+			if (w == supported_modes[i].width &&
+			    h == supported_modes[i].height &&
+			    supported_modes[i].hdr_mode == hdr->hdr_mode) {
+				ov7251->cur_mode = &supported_modes[i];
+				break;
+			}
+		}
+		if (i == ARRAY_SIZE(supported_modes)) {
+			dev_err(&ov7251->client->dev,
+				"not find hdr mode:%d %dx%d config\n",
+				hdr->hdr_mode, w, h);
+			ret = -EINVAL;
+		} else {
+			w = ov7251->cur_mode->hts_def - ov7251->cur_mode->width;
+			h = ov7251->cur_mode->vts_def - ov7251->cur_mode->height;
+			__v4l2_ctrl_modify_range(ov7251->hblank, w, w, 1, w);
+			__v4l2_ctrl_modify_range(ov7251->vblank, h,
+						 OV7251_VTS_MAX - ov7251->cur_mode->height, 1, h);
+		}
+		break;
+	case PREISP_CMD_SET_HDRAE_EXP:
 		break;
 	case RKMODULE_SET_QUICK_STREAM:
+
 		stream = *((u32 *)arg);
+
 		if (stream)
 			ret = ov7251_write_reg(ov7251->client, OV7251_REG_CTRL_MODE,
-				OV7251_REG_VALUE_08BIT, OV7251_MODE_STREAMING);
+				 OV7251_REG_VALUE_08BIT, OV7251_MODE_STREAMING);
 		else
 			ret = ov7251_write_reg(ov7251->client, OV7251_REG_CTRL_MODE,
-				OV7251_REG_VALUE_08BIT, OV7251_MODE_SW_STANDBY);
+				 OV7251_REG_VALUE_08BIT, OV7251_MODE_SW_STANDBY);
 		break;
 	default:
-		ret = -ENOTTY;
+		ret = -ENOIOCTLCMD;
 		break;
 	}
 
@@ -757,11 +1077,12 @@
 
 #ifdef CONFIG_COMPAT
 static long ov7251_compat_ioctl32(struct v4l2_subdev *sd,
-				  unsigned int cmd, unsigned long arg)
+				   unsigned int cmd, unsigned long arg)
 {
 	void __user *up = compat_ptr(arg);
 	struct rkmodule_inf *inf;
 	struct rkmodule_hdr_cfg *hdr;
+	struct preisp_hdrae_exp_s *hdrae;
 	long ret;
 	u32 stream = 0;
 
@@ -775,8 +1096,7 @@
 
 		ret = ov7251_ioctl(sd, cmd, inf);
 		if (!ret) {
-			ret = copy_to_user(up, inf, sizeof(*inf));
-			if (ret)
+			if (copy_to_user(up, inf, sizeof(*inf)))
 				ret = -EFAULT;
 		}
 		kfree(inf);
@@ -790,8 +1110,7 @@
 
 		ret = ov7251_ioctl(sd, cmd, hdr);
 		if (!ret) {
-			ret = copy_to_user(up, hdr, sizeof(*hdr));
-			if (ret)
+			if (copy_to_user(up, hdr, sizeof(*hdr)))
 				ret = -EFAULT;
 		}
 		kfree(hdr);
@@ -803,19 +1122,33 @@
 			return ret;
 		}
 
-		if (copy_from_user(hdr, up, sizeof(*hdr))) {
-			kfree(hdr);
-			return -EFAULT;
-		}
-
-		ret = ov7251_ioctl(sd, cmd, hdr);
+		ret = copy_from_user(hdr, up, sizeof(*hdr));
+		if (!ret)
+			ret = ov7251_ioctl(sd, cmd, hdr);
+		else
+			ret = -EFAULT;
 		kfree(hdr);
 		break;
-	case RKMODULE_SET_QUICK_STREAM:
-		if (copy_from_user(&stream, up, sizeof(u32)))
-			return -EFAULT;
+	case PREISP_CMD_SET_HDRAE_EXP:
+		hdrae = kzalloc(sizeof(*hdrae), GFP_KERNEL);
+		if (!hdrae) {
+			ret = -ENOMEM;
+			return ret;
+		}
 
-		ret = ov7251_ioctl(sd, cmd, &stream);
+		ret = copy_from_user(hdrae, up, sizeof(*hdrae));
+		if (!ret)
+			ret = ov7251_ioctl(sd, cmd, hdrae);
+		else
+			ret = -EFAULT;
+		kfree(hdrae);
+		break;
+	case RKMODULE_SET_QUICK_STREAM:
+		ret = copy_from_user(&stream, up, sizeof(u32));
+		if (!ret)
+			ret = ov7251_ioctl(sd, cmd, &stream);
+		else
+			ret = -EFAULT;
 		break;
 	default:
 		ret = -ENOIOCTLCMD;
@@ -835,20 +1168,18 @@
 		return ret;
 
 	/* In case these controls are set before streaming */
-	mutex_unlock(&ov7251->mutex);
-	ret = v4l2_ctrl_handler_setup(&ov7251->ctrl_handler);
-	mutex_lock(&ov7251->mutex);
+	ret = __v4l2_ctrl_handler_setup(&ov7251->ctrl_handler);
 	if (ret)
 		return ret;
 
 	return ov7251_write_reg(ov7251->client, OV7251_REG_CTRL_MODE,
-				OV7251_REG_VALUE_08BIT, OV7251_MODE_STREAMING);
+				 OV7251_REG_VALUE_08BIT, OV7251_MODE_STREAMING);
 }
 
 static int __ov7251_stop_stream(struct ov7251 *ov7251)
 {
 	return ov7251_write_reg(ov7251->client, OV7251_REG_CTRL_MODE,
-				OV7251_REG_VALUE_08BIT, OV7251_MODE_SW_STANDBY);
+				 OV7251_REG_VALUE_08BIT, OV7251_MODE_SW_STANDBY);
 }
 
 static int ov7251_s_stream(struct v4l2_subdev *sd, int on)
@@ -868,6 +1199,7 @@
 			pm_runtime_put_noidle(&client->dev);
 			goto unlock_and_return;
 		}
+
 		ret = __ov7251_start_stream(ov7251);
 		if (ret) {
 			v4l2_err(sd, "start stream failed while write regs\n");
@@ -907,6 +1239,13 @@
 			goto unlock_and_return;
 		}
 
+		ret = ov7251_write_array(ov7251->client, ov7251_global_regs);
+		if (ret) {
+			v4l2_err(sd, "could not set init registers\n");
+			pm_runtime_put_noidle(&client->dev);
+			goto unlock_and_return;
+		}
+
 		ov7251->power_on = true;
 	} else {
 		pm_runtime_put(&client->dev);
@@ -937,12 +1276,11 @@
 		if (ret < 0)
 			dev_err(dev, "could not set pins\n");
 	}
-
 	ret = clk_set_rate(ov7251->xvclk, OV7251_XVCLK_FREQ);
 	if (ret < 0)
-		dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
+		dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
 	if (clk_get_rate(ov7251->xvclk) != OV7251_XVCLK_FREQ)
-		dev_err(dev, "xvclk mismatched, modes are based on 24MHz\n");
+		dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
 	ret = clk_prepare_enable(ov7251->xvclk);
 	if (ret < 0) {
 		dev_err(dev, "Failed to enable xvclk\n");
@@ -950,7 +1288,7 @@
 	}
 
 	if (!IS_ERR(ov7251->reset_gpio))
-		gpiod_set_value_cansleep(ov7251->reset_gpio, 1);
+		gpiod_set_value_cansleep(ov7251->reset_gpio, 0);
 
 	ret = regulator_bulk_enable(OV7251_NUM_SUPPLIES, ov7251->supplies);
 	if (ret < 0) {
@@ -958,13 +1296,18 @@
 		goto disable_clk;
 	}
 
-	usleep_range(1000, 1100);
-
+	usleep_range(5 * 1000, 10 * 1000);
 	if (!IS_ERR(ov7251->reset_gpio))
-		gpiod_set_value_cansleep(ov7251->reset_gpio, 0);
+		gpiod_set_value_cansleep(ov7251->reset_gpio, 1);
 
+	usleep_range(500, 1000);
 	if (!IS_ERR(ov7251->pwdn_gpio))
 		gpiod_set_value_cansleep(ov7251->pwdn_gpio, 1);
+
+	if (!IS_ERR(ov7251->reset_gpio))
+		usleep_range(6000, 8000);
+	else
+		usleep_range(12000, 16000);
 
 	/* 8192 cycles prior to first SCCB transaction */
 	delay_us = ov7251_cal_delay(8192);
@@ -975,9 +1318,6 @@
 disable_clk:
 	clk_disable_unprepare(ov7251->xvclk);
 
-	if (!IS_ERR_OR_NULL(ov7251->pins_sleep))
-		pinctrl_select_state(ov7251->pinctrl, ov7251->pins_sleep);
-
 	return ret;
 }
 
@@ -986,17 +1326,17 @@
 	int ret;
 	struct device *dev = &ov7251->client->dev;
 
+	if (!IS_ERR(ov7251->pwdn_gpio))
+		gpiod_set_value_cansleep(ov7251->pwdn_gpio, 0);
+	clk_disable_unprepare(ov7251->xvclk);
+	if (!IS_ERR(ov7251->reset_gpio))
+		gpiod_set_value_cansleep(ov7251->reset_gpio, 0);
 	if (!IS_ERR_OR_NULL(ov7251->pins_sleep)) {
 		ret = pinctrl_select_state(ov7251->pinctrl,
 					   ov7251->pins_sleep);
 		if (ret < 0)
 			dev_dbg(dev, "could not set pins\n");
 	}
-	if (!IS_ERR(ov7251->pwdn_gpio))
-		gpiod_set_value_cansleep(ov7251->pwdn_gpio, 0);
-	clk_disable_unprepare(ov7251->xvclk);
-	if (!IS_ERR(ov7251->reset_gpio))
-		gpiod_set_value_cansleep(ov7251->reset_gpio, 1);
 	regulator_bulk_disable(OV7251_NUM_SUPPLIES, ov7251->supplies);
 }
 
@@ -1032,7 +1372,7 @@
 	/* Initialize try_fmt */
 	try_fmt->width = def_mode->width;
 	try_fmt->height = def_mode->height;
-	try_fmt->code = PIX_FORMAT;
+	try_fmt->code = def_mode->bus_fmt;
 	try_fmt->field = V4L2_FIELD_NONE;
 
 	mutex_unlock(&ov7251->mutex);
@@ -1049,56 +1389,12 @@
 	if (fie->index >= ARRAY_SIZE(supported_modes))
 		return -EINVAL;
 
-	if (fie->code != PIX_FORMAT)
-		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;
 	return 0;
-}
-
-static int ov7251_g_mbus_config(struct v4l2_subdev *sd,
-				struct v4l2_mbus_config *config)
-{
-	u32 val = 0;
-
-	val = 1 << (OV7251_LANES - 1) |
-	      V4L2_MBUS_CSI2_CHANNEL_0 |
-	      V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
-	config->type = V4L2_MBUS_CSI2;
-	config->flags = val;
-
-	return 0;
-}
-
-#define CROP_START(SRC, DST) (((SRC) - (DST)) / 2 / 4 * 4)
-#define DST_WIDTH 640
-#define DST_HEIGHT 480
-
-/*
- * The resolution of the driver configuration needs to be exactly
- * the same as the current output resolution of the sensor,
- * the input width of the isp needs to be 16 aligned,
- * the input height of the isp needs to be 8 aligned.
- * Can be cropped to standard resolution by this function,
- * otherwise it will crop out strange resolution according
- * to the alignment rules.
- */
-static int ov7251_get_selection(struct v4l2_subdev *sd,
-				struct v4l2_subdev_pad_config *cfg,
-				struct v4l2_subdev_selection *sel)
-{
-	struct ov7251 *ov7251 = to_ov7251(sd);
-
-	if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) {
-		sel->r.left = CROP_START(ov7251->cur_mode->width, DST_WIDTH);
-		sel->r.width = DST_WIDTH;
-		sel->r.top = CROP_START(ov7251->cur_mode->height, DST_HEIGHT);
-		sel->r.height = DST_HEIGHT;
-		return 0;
-	}
-	return -EINVAL;
 }
 
 static const struct dev_pm_ops ov7251_pm_ops = {
@@ -1123,7 +1419,6 @@
 static const struct v4l2_subdev_video_ops ov7251_video_ops = {
 	.s_stream = ov7251_s_stream,
 	.g_frame_interval = ov7251_g_frame_interval,
-	.g_mbus_config = ov7251_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops ov7251_pad_ops = {
@@ -1132,7 +1427,7 @@
 	.enum_frame_interval = ov7251_enum_frame_interval,
 	.get_fmt = ov7251_get_fmt,
 	.set_fmt = ov7251_set_fmt,
-	.get_selection = ov7251_get_selection,
+	.get_mbus_config = ov7251_g_mbus_config,
 };
 
 static const struct v4l2_subdev_ops ov7251_subdev_ops = {
@@ -1144,10 +1439,11 @@
 static int ov7251_set_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct ov7251 *ov7251 = container_of(ctrl->handler,
-					     struct ov7251, ctrl_handler);
+					       struct ov7251, ctrl_handler);
 	struct i2c_client *client = ov7251->client;
 	s64 max;
 	int ret = 0;
+	u32 val = 0;
 
 	/* Propagate change of current control to all related controls */
 	switch (ctrl->id) {
@@ -1183,6 +1479,21 @@
 	case V4L2_CID_TEST_PATTERN:
 		ret = ov7251_enable_test_pattern(ov7251, ctrl->val);
 		break;
+	case V4L2_CID_HFLIP:
+		ret = ov7251_read_reg(ov7251->client, OV7251_MIRROR_REG,
+				       OV7251_REG_VALUE_08BIT, &val);
+		ret |= ov7251_write_reg(ov7251->client, OV7251_MIRROR_REG,
+					 OV7251_REG_VALUE_08BIT,
+					 OV7251_FETCH_MIRROR(val, ctrl->val));
+		break;
+	case V4L2_CID_VFLIP:
+		ret = ov7251_read_reg(ov7251->client, OV7251_FLIP_REG,
+				       OV7251_REG_VALUE_08BIT, &val);
+		ret |= ov7251_write_reg(ov7251->client, OV7251_FLIP_REG,
+					 OV7251_REG_VALUE_08BIT,
+					 OV7251_FETCH_FLIP(val, ctrl->val));
+		break;
+
 	default:
 		dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
 			 __func__, ctrl->id, ctrl->val);
@@ -1209,7 +1520,7 @@
 
 	handler = &ov7251->ctrl_handler;
 	mode = ov7251->cur_mode;
-	ret = v4l2_ctrl_handler_init(handler, 8);
+	ret = v4l2_ctrl_handler_init(handler, 9);
 	if (ret)
 		return ret;
 	handler->lock = &ov7251->mutex;
@@ -1220,36 +1531,38 @@
 		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
 	v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
-			  0, OV7251_PIXEL_RATE, 1, OV7251_PIXEL_RATE);
+			  0, PIXEL_RATE_WITH_240M_10BIT, 1, PIXEL_RATE_WITH_240M_10BIT);
 
 	h_blank = mode->hts_def - mode->width;
 	ov7251->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
-				h_blank, h_blank, 1, h_blank);
+					    h_blank, h_blank, 1, h_blank);
 	if (ov7251->hblank)
 		ov7251->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
 	vblank_def = mode->vts_def - mode->height;
 	ov7251->vblank = v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
-				V4L2_CID_VBLANK, vblank_def,
-				OV7251_VTS_MAX - mode->height,
-				1, vblank_def);
-
+					    V4L2_CID_VBLANK, vblank_def,
+					    OV7251_VTS_MAX - mode->height,
+					    1, vblank_def);
+	ov7251->cur_fps = mode->max_fps;
 	exposure_max = mode->vts_def - 20;
 	ov7251->exposure = v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
-				V4L2_CID_EXPOSURE, OV7251_EXPOSURE_MIN,
-				exposure_max, OV7251_EXPOSURE_STEP,
-				mode->exp_def);
-
+					      V4L2_CID_EXPOSURE, OV7251_EXPOSURE_MIN,
+					      exposure_max, OV7251_EXPOSURE_STEP,
+					      mode->exp_def);
 	ov7251->anal_gain = v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
 				V4L2_CID_ANALOGUE_GAIN, ANALOG_GAIN_MIN,
 				ANALOG_GAIN_MAX, ANALOG_GAIN_STEP,
 				ANALOG_GAIN_DEFAULT);
 
 	ov7251->test_pattern = v4l2_ctrl_new_std_menu_items(handler,
-				&ov7251_ctrl_ops, V4L2_CID_TEST_PATTERN,
-				ARRAY_SIZE(ov7251_test_pattern_menu) - 1,
-				0, 0, ov7251_test_pattern_menu);
-
+							    &ov7251_ctrl_ops,
+					V4L2_CID_TEST_PATTERN,
+					ARRAY_SIZE(ov7251_test_pattern_menu) - 1,
+					0, 0, ov7251_test_pattern_menu);
+	v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
+				V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
+				V4L2_CID_VFLIP, 0, 1, 1, 0);
 	if (handler->error) {
 		ret = handler->error;
 		dev_err(&ov7251->client->dev,
@@ -1268,14 +1581,14 @@
 }
 
 static int ov7251_check_sensor_id(struct ov7251 *ov7251,
-				  struct i2c_client *client)
+				   struct i2c_client *client)
 {
 	struct device *dev = &ov7251->client->dev;
 	u32 id = 0;
 	int ret;
 
 	ret = ov7251_read_reg(client, OV7251_REG_CHIP_ID,
-			      OV7251_REG_VALUE_16BIT, &id);
+			       OV7251_REG_VALUE_08BIT, &id);
 	if (id != CHIP_ID) {
 		dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);
 		return -ENODEV;
@@ -1288,7 +1601,7 @@
 
 static int ov7251_configure_regulators(struct ov7251 *ov7251)
 {
-	size_t i;
+	unsigned int i;
 
 	for (i = 0; i < OV7251_NUM_SUPPLIES; i++)
 		ov7251->supplies[i].supply = ov7251_supply_names[i];
@@ -1299,7 +1612,7 @@
 }
 
 static int ov7251_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
+			 const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
 	struct device_node *node = dev->of_node;
@@ -1309,9 +1622,9 @@
 	int ret;
 
 	dev_info(dev, "driver version: %02x.%02x.%02x",
-		DRIVER_VERSION >> 16,
-		(DRIVER_VERSION & 0xff00) >> 8,
-		DRIVER_VERSION & 0x00ff);
+		 DRIVER_VERSION >> 16,
+		 (DRIVER_VERSION & 0xff00) >> 8,
+		 DRIVER_VERSION & 0x00ff);
 
 	ov7251 = devm_kzalloc(dev, sizeof(*ov7251), GFP_KERNEL);
 	if (!ov7251)
@@ -1347,27 +1660,29 @@
 	if (IS_ERR(ov7251->pwdn_gpio))
 		dev_warn(dev, "Failed to get pwdn-gpios\n");
 
-	ret = ov7251_configure_regulators(ov7251);
-	if (ret) {
-		dev_err(dev, "Failed to get power regulators\n");
-		return ret;
-	}
 	ov7251->pinctrl = devm_pinctrl_get(dev);
 	if (!IS_ERR(ov7251->pinctrl)) {
 		ov7251->pins_default =
 			pinctrl_lookup_state(ov7251->pinctrl,
 					     OF_CAMERA_PINCTRL_STATE_DEFAULT);
 		if (IS_ERR(ov7251->pins_default))
-			dev_info(dev, "could not get default pinstate\n");
+			dev_err(dev, "could not get default pinstate\n");
 
 		ov7251->pins_sleep =
 			pinctrl_lookup_state(ov7251->pinctrl,
 					     OF_CAMERA_PINCTRL_STATE_SLEEP);
 		if (IS_ERR(ov7251->pins_sleep))
-			dev_info(dev, "could not get sleep pinstate\n");
+			dev_err(dev, "could not get sleep pinstate\n");
 	} else {
-		dev_info(dev, "no pinctrl\n");
+		dev_err(dev, "no pinctrl\n");
 	}
+
+	ret = ov7251_configure_regulators(ov7251);
+	if (ret) {
+		dev_err(dev, "Failed to get power regulators\n");
+		return ret;
+	}
+
 	mutex_init(&ov7251->mutex);
 
 	sd = &ov7251->subdev;

--
Gitblit v1.6.2