Re: [PATCH 2/2] media: i2c: Add OV1063x sensor driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Sakari,

On Mon, Jan 04, 2021 at 01:41:15PM +0200, Sakari Ailus wrote:
> Hi Laurent,
> 
> Thanks for the patchset.
> 
> On Mon, Jan 04, 2021 at 07:39:45AM +0200, Laurent Pinchart wrote:
> > Add a new V4L2 subdev driver for the OmniVision OV10633 and OV10635
> > camera sensors. The work is based on the driver from the TI BSP, itself
> > based on original work by Phil Edworthy posted to the linux-media
> > mailing list ([1]). This version of the code is a large rewrite of many
> > parts.
> 
> The driver seems generally quite nice. It doesn't check known-good link
> frequencies are not defined in bindings nor checked by the driver. Could
> you add them?

Good point.

> Same or the assigned-clock-rates in bindings.
> 
> Please see more comments below.
> 
> > [1] http://www.spinics.net/lists/linux-media/msg64347.html
> > 
> > Signed-off-by: Nikhil Devshatwar <nikhil.nd@xxxxxx>
> > Signed-off-by: Benoit Parrot <bparrot@xxxxxx>
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
> > ---
> >  MAINTAINERS                      |    2 +
> >  drivers/media/i2c/Kconfig        |   12 +
> >  drivers/media/i2c/Makefile       |    1 +
> >  drivers/media/i2c/ov1063x.c      | 1692 ++++++++++++++++++++++++++++++
> >  drivers/media/i2c/ov1063x_regs.h |  626 +++++++++++
> >  5 files changed, 2333 insertions(+)
> >  create mode 100644 drivers/media/i2c/ov1063x.c
> >  create mode 100644 drivers/media/i2c/ov1063x_regs.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 9dc3a7d75460..4b94061130cf 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -12873,6 +12873,8 @@ L:	linux-media@xxxxxxxxxxxxxxx
> >  S:	Maintained
> >  T:	git git://linuxtv.org/media_tree.git
> >  F:	Documentation/devicetree/bindings/media/i2c/ov1063x.yaml
> > +F:	drivers/media/i2c/ov1063x.c
> > +F:	drivers/media/i2c/ov1063x_regs.h
> >  
> >  OMNIVISION OV13858 SENSOR DRIVER
> >  M:	Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx>
> > diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> > index 878f66ef2719..84a97989775e 100644
> > --- a/drivers/media/i2c/Kconfig
> > +++ b/drivers/media/i2c/Kconfig
> > @@ -1050,6 +1050,18 @@ config VIDEO_OV9650
> >  	  This is a V4L2 sensor driver for the Omnivision
> >  	  OV9650 and OV9652 camera sensors.
> >  
> > +config VIDEO_OV10633
> > +	tristate "OmniVision OV10633/OV10635 sensor support"
> > +	depends on I2C && VIDEO_V4L2
> > +	depends on GPIOLIB && OF
> > +	select MEDIA_CONTROLLER
> > +	select REGMAP_I2C
> > +	select V4L2_FWNODE
> > +	select VIDEO_V4L2_SUBDEV_API
> > +	help
> > +	  This is a Video4Linux2 driver for the OmniVision
> > +	  OV10633 and OV10635 camera sensors.
> > +
> >  config VIDEO_OV13858
> >  	tristate "OmniVision OV13858 sensor support"
> >  	depends on I2C && VIDEO_V4L2
> > diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
> > index f0a77473979d..6eef97e2423d 100644
> > --- a/drivers/media/i2c/Makefile
> > +++ b/drivers/media/i2c/Makefile
> > @@ -83,6 +83,7 @@ obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
> >  obj-$(CONFIG_VIDEO_OV8856) += ov8856.o
> >  obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
> >  obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
> > +obj-$(CONFIG_VIDEO_OV10633) += ov1063x.o
> >  obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
> >  obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
> >  obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
> > diff --git a/drivers/media/i2c/ov1063x.c b/drivers/media/i2c/ov1063x.c
> > new file mode 100644
> > index 000000000000..5b25ed5e766b
> > --- /dev/null
> > +++ b/drivers/media/i2c/ov1063x.c
> > @@ -0,0 +1,1692 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * OmniVision OV10633/OV10635 Camera Driver
> > + *
> > + * Based on the original driver written by Phil Edworthy.
> > + * Copyright (C) 2013 Phil Edworthy
> > + * Copyright (C) 2013 Renesas Electronics
> > + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
> > + * Copyright (C) 2020 Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/i2c.h>
> > +#include <linux/init.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/regmap.h>
> > +#include <linux/slab.h>
> > +#include <linux/v4l2-mediabus.h>
> > +#include <linux/videodev2.h>
> > +
> > +#include <media/v4l2-common.h>
> > +#include <media/v4l2-ctrls.h>
> > +#include <media/v4l2-event.h>
> > +#include <media/v4l2-fwnode.h>
> > +#include <media/v4l2-subdev.h>
> > +
> > +/* Register definitions */
> > +#define OV1063X_REG_8BIT(n)			((1 << 16) | (n))
> > +#define OV1063X_REG_16BIT(n)			((2 << 16) | (n))
> > +#define OV1063X_REG_24BIT(n)			((3 << 16) | (n))
> > +#define OV1063X_REG_32BIT(n)			((4 << 16) | (n))
> > +#define OV1063X_REG_SIZE_SHIFT			16
> > +#define OV1063X_REG_ADDR_MASK			0xffff
> > +
> > +#define OV1063X_STREAM_MODE			OV1063X_REG_8BIT(0x0100)
> > +#define OV1063X_STREAM_MODE_ON			BIT(0)
> > +#define OV1063X_SOFTWARE_RESET			OV1063X_REG_8BIT(0x0103)
> > +
> > +#define OV1063X_SC_CMMN_PLL_CTRL0		OV1063X_REG_8BIT(0x3003)
> > +#define OV1063X_SC_CMMN_PLL_SCLK_CP(n)		((n) << 6)
> > +#define OV1063X_SC_CMMN_PLL_SCLK_MULTI(n)	((n) << 0)
> > +#define OV1063X_SC_CMMN_PLL_CTRL1		OV1063X_REG_8BIT(0x3004)
> > +#define OV1063X_SC_CMMN_PLL_SCLK_BYPASS		BIT(7)
> > +#define OV1063X_SC_CMMN_PLL_SCLK_PRE_DIV(n)	((n) << 4)	/* /1, /1.5, /2, /3, /4, /5, /6, /7 */
> > +#define OV1063X_SC_CMMN_PLL_SCLK_CP2(n)		((n) << 3)
> > +#define OV1063X_SC_CMMN_PLL_SCLK_DIV(n)		((n) << 0)	/* Divider = 2 * (1 + n) */
> > +#define OV1063X_SC_CMMN_PLL_CTRL2		OV1063X_REG_8BIT(0x3005)
> > +#define OV1063X_SC_CMMN_PLL_PCLK_CP(n)		((n) << 6)
> > +#define OV1063X_SC_CMMN_PLL_PCLK_MULTI(n)	((n) << 0)
> > +#define OV1063X_SC_CMMN_PLL_CTRL3		OV1063X_REG_8BIT(0x3006)
> > +#define OV1063X_SC_CMMN_PLL_PCLK_BYPASS		BIT(7)
> > +#define OV1063X_SC_CMMN_PLL_PCLK_PRE_DIV(n)	((n) << 4)	/* /1, /1.5, /2, /3, /4, /5, /6, /7 */
> > +#define OV1063X_SC_CMMN_PLL_PCLK_CP2(n)		((n) << 3)
> > +#define OV1063X_SC_CMMN_PLL_PCLK_DIV(n)		((n) << 0)	/* Divider = 2 * (1 + n) */
> > +#define OV1063X_SC_CMMN_PCLK_DIV_CTRL		OV1063X_REG_8BIT(0x3007)
> > +#define OV1063X_PID				OV1063X_REG_16BIT(0x300a)
> > +#define OV1063X_SC_CMMN_SCCB_ID			OV1063X_REG_8BIT(0x300c)
> > +#define OV1063X_SC_CMMN_SCCB_ID_ADDR(n)		((n) << 1)
> > +#define OV1063X_SC_CMMN_SCCB_ID_SEL		BIT(0)
> > +#define OV1063X_SC_CMMN_PAD			OV1063X_REG_8BIT(0x3011)
> > +#define OV1063X_SC_CMMN_PAD_DRIVE(n)		((n) << 6)
> > +#define OV1063X_SC_CMMN_CLKRST0			OV1063X_REG_8BIT(0x301a)
> > +#define OV1063X_SC_CMMN_CLKRST0_SCLK		GENMASK(7, 4)
> > +#define OV1063X_SC_CMMN_CLKRST0_RST		GENMASK(3, 0)
> > +#define OV1063X_SC_CMMN_CLKRST1			OV1063X_REG_8BIT(0x301b)
> > +#define OV1063X_SC_CMMN_CLKRST1_SCLK		GENMASK(7, 4)
> > +#define OV1063X_SC_CMMN_CLKRST1_RST		GENMASK(3, 0)
> > +#define OV1063X_SC_CMMN_CLKRST2			OV1063X_REG_8BIT(0x301c)
> > +#define OV1063X_SC_CMMN_CLKRST2_PCLK_DVP	BIT(7)
> > +#define OV1063X_SC_CMMN_CLKRST2_SCLK		GENMASK(6, 4)
> > +#define OV1063X_SC_CMMN_CLKRST2_RST_DVP		BIT(3)
> > +#define OV1063X_SC_CMMN_CLKRST2_RST		GENMASK(2, 0)
> > +#define OV1063X_SC_CMMN_CLOCK_SEL		OV1063X_REG_8BIT(0x3020)
> > +#define OV1063X_SC_CMMN_MISC_CTRL		OV1063X_REG_8BIT(0x3021)
> > +#define OV1063X_SC_CMMN_MISC_CTRL_PCLK_INV	BIT(7)
> > +#define OV1063X_SC_CMMN_MISC_CTRL_SCLK_INV	BIT(6)
> > +#define OV1063X_SC_CMMN_MISC_CTRL_SCLK2X_INV	BIT(5)
> > +#define OV1063X_SC_CMMN_MISC_CTRL_CEN_GLOBAL_O	BIT(0)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_1		OV1063X_REG_8BIT(0x3022)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_2		OV1063X_REG_8BIT(0x3023)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_BIST_EN	BIT(5)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_CLK_SWITCH	BIT(4)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_3		OV1063X_REG_8BIT(0x3024)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_RAW_LONG	(0U << 4)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_RAW_SHORT	(1U << 4)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_RAW_LONG_SHORT	(2U << 4)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_RAW_COMBINED	(0U << 4)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_YUV_LONG	(1U << 1)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_YUV_SHORT	(2U << 1)
> > +#define OV1063X_SC_CMMN_CORE_CTRL_PCLK_SYS	(0U << 0)	/* PCLK from system PLL */
> > +#define OV1063X_SC_CMMN_CORE_CTRL_PCLK_SEC	(1U << 0)	/* PCLK from secondary PLL */
> > +#define OV1063X_SC_CMMN_CORE_CTRL1		OV1063X_REG_8BIT(0x3025)
> > +#define OV1063X_SC_CMMN_PWDN_CTRL2		OV1063X_REG_8BIT(0x302d)
> > +#define OV1063X_SC_CMMN_PWDN_CTRL2_RST_DIG1	BIT(3)
> > +#define OV1063X_SC_CMMN_PWDN_CTRL2_RST_DIG2	BIT(2)
> > +#define OV1063X_SC_CMMN_PWDN_CTRL2_RST_ISP	BIT(1)
> > +#define OV1063X_SC_CMMN_PWDN_CTRL2_SEQUENCE	BIT(0)
> > +#define OV1063X_SC_CMMN_SCLK2X_SEL		OV1063X_REG_8BIT(0x3033)
> > +#define OV1063X_SC_CMMN_SCLK2X_SEL_DIV2		(1U << 2)
> > +#define OV1063X_SC_CMMN_SCLK2X_SEL_DIV4		(2U << 2)
> > +#define OV1063X_SC_SOC_CLKRST7			OV1063X_REG_8BIT(0x3042)
> > +#define OV1063X_SC_SOC_CLKRST7_SCLK		GENMASK(7, 4)
> > +#define OV1063X_SC_SOC_CLKRST7_RST		GENMASK(3, 0)
> > +
> > +#define OV1063X_AEC_PK_MANUAL			OV1063X_REG_8BIT(0x3503)
> > +#define OV1063X_AEC_PK_MANUAL_GAIN_DELAY	BIT(5)
> > +#define OV1063X_AEC_PK_MANUAL_DELAY		BIT(4)
> > +#define OV1063X_AEC_PK_MAN_DONE			OV1063X_REG_8BIT(0x3504)
> > +#define OV1063X_AEC_PK_MAN_DONE_AEC_DONE	BIT(0)
> > +
> > +#define OV1063X_ANA_ADC1			OV1063X_REG_8BIT(0x3600)
> > +#define OV1063X_ANA_ADC2			OV1063X_REG_8BIT(0x3601)
> > +#define OV1063X_ANA_ADC3			OV1063X_REG_8BIT(0x3602)
> > +#define OV1063X_ANA_ADC4			OV1063X_REG_8BIT(0x3603)
> > +#define OV1063X_ANA_ANALOG1			OV1063X_REG_8BIT(0x3610)
> > +#define OV1063X_ANA_ANALOG2			OV1063X_REG_8BIT(0x3611)
> > +#define OV1063X_ANA_ANALOG3			OV1063X_REG_8BIT(0x3612)
> > +#define OV1063X_ANA_ARRAY1			OV1063X_REG_8BIT(0x3621)
> > +#define OV1063X_ANA_ARRAY1_FULL			(0 << 3)
> > +#define OV1063X_ANA_ARRAY1_CROP_768		(1 << 3)
> > +#define OV1063X_ANA_ARRAY1_CROP_656		(2 << 3)
> > +#define OV1063X_ANA_ARRAY1_DELAY(n)		((n) << 0)
> > +#define OV1063X_ANA_PWC1			OV1063X_REG_8BIT(0x3630)
> > +#define OV1063X_ANA_PWC2			OV1063X_REG_8BIT(0x3631)
> > +#define OV1063X_ANA_PWC3			OV1063X_REG_8BIT(0x3632)
> > +#define OV1063X_ANA_PWC4			OV1063X_REG_8BIT(0x3633)
> > +
> > +#define OV1063X_SENSOR_RSTGOLOW			OV1063X_REG_8BIT(0x3702)
> > +#define OV1063X_SENSOR_HLDWIDTH			OV1063X_REG_8BIT(0x3703)
> > +#define OV1063X_SENSOR_TXWIDTH			OV1063X_REG_8BIT(0x3704)
> > +#define OV1063X_SENSOR_REG9			OV1063X_REG_8BIT(0x3709)
> > +#define OV1063X_SENSOR_REGD			OV1063X_REG_8BIT(0x370d)
> > +#define OV1063X_SENSOR_RSTYZ_GOLOW		OV1063X_REG_16BIT(0x3712)
> > +#define OV1063X_SENSOR_EQ_GOLOW			OV1063X_REG_8BIT(0x3714)
> > +#define OV1063X_SENSOR_REG15			OV1063X_REG_8BIT(0x3715)
> > +#define OV1063X_SENSOR_BITSW_GO			OV1063X_REG_16BIT(0x371c)
> > +
> > +#define OV1063X_TIMING_X_START_ADDR		OV1063X_REG_16BIT(0x3800)
> > +#define OV1063X_TIMING_Y_START_ADDR		OV1063X_REG_16BIT(0x3802)
> > +#define OV1063X_TIMING_X_END_ADDR		OV1063X_REG_16BIT(0x3804)
> > +#define OV1063X_TIMING_Y_END_ADDR		OV1063X_REG_16BIT(0x3806)
> > +#define OV1063X_TIMING_X_OUTPUT_SIZE		OV1063X_REG_16BIT(0x3808)
> > +#define OV1063X_TIMING_Y_OUTPUT_SIZE		OV1063X_REG_16BIT(0x380a)
> > +#define OV1063X_TIMING_HTS			OV1063X_REG_16BIT(0x380c)
> > +#define OV1063X_TIMING_VTS			OV1063X_REG_16BIT(0x380e)
> > +#define OV1063X_TIMING_ISP_X_WIN		OV1063X_REG_16BIT(0x3810)
> > +#define OV1063X_TIMING_ISP_Y_WIN		OV1063X_REG_16BIT(0x3812)
> > +#define OV1063X_TIMING_CTRL15			OV1063X_REG_8BIT(0x3815)
> > +#define OV1063X_TIMING_CTRL15_BLACK_LINE_HREF	BIT(7)
> > +#define OV1063X_TIMING_CTRL15_RIP_SOF		BIT(5)
> > +#define OV1063X_TIMING_CTRL15_BLACK_LINES(n)	((n) << 0)
> > +#define OV1063X_TIMING_CTRL1C			OV1063X_REG_8BIT(0x381c)
> > +#define OV1063X_TIMING_CTRL1C_VFLIP_DIG		BIT(7)
> > +#define OV1063X_TIMING_CTRL1C_VFLIP_ARRAY	BIT(6)
> > +#define OV1063X_TIMING_CTRL1C_VSUB4		BIT(1)
> > +#define OV1063X_TIMING_CTRL1C_VSUB2		BIT(0)
> > +#define OV1063X_TIMING_CTRL1D			OV1063X_REG_8BIT(0x381d)
> > +#define OV1063X_TIMING_CTRL1D_VFLIP_BLACK_LINE	BIT(7)
> > +#define OV1063X_TIMING_CTRL1D_WDR		BIT(6)
> > +#define OV1063X_TIMING_CTRL1D_HFLIP_DIG		BIT(1)
> > +#define OV1063X_TIMING_CTRL1D_HFLIP_ARRAY	BIT(0)
> > +#define OV1063X_VSTART_OFFSET			OV1063X_REG_16BIT(0x381e)
> > +
> > +#define OV1063X_START_LINE			OV1063X_REG_8BIT(0x4001)
> > +#define OV1063X_LINE_NUM			OV1063X_REG_8BIT(0x4004)	/* Black lines */
> > +#define OV1063X_BLC_CTRL05			OV1063X_REG_8BIT(0x4005)
> > +#define OV1063X_BLC_CTRL05_ONE_LINE_MODE	BIT(5)
> > +#define OV1063X_BLC_CTRL05_REMOVE_BLACK_LINE	BIT(4)
> > +#define OV1063X_BLC_CTRL05_ONE_MAN_OFFSET_MODE	BIT(3)
> > +#define OV1063X_BLC_CTRL05_BL_RBLUE_RVS		BIT(2)
> > +#define OV1063X_BLC_CTRL05_BLC_ALWAYS_DO	BIT(1)
> > +#define OV1063X_BLC_AVG_CTRL1			OV1063X_REG_8BIT(0x4050)
> > +#define OV1063X_BLC_AVG_CTRL2			OV1063X_REG_8BIT(0x4051)
> > +#define OV1063X_BLC_OFFSET_TOP_LIMIT		OV1063X_REG_16BIT(0x4056)
> > +#define OV1063X_BLC_OFFSET_BOT_LIMIT		OV1063X_REG_16BIT(0x4058)
> > +#define OV1063X_BLC_CTRL5A			OV1063X_REG_8BIT(0x405a)
> > +
> > +#define OV1063X_FC_R2				OV1063X_REG_8BIT(0x4202)
> > +
> > +#define OV1063X_FORMAT_CTRL00			OV1063X_REG_8BIT(0x4300)
> > +#define OV1063X_FORMAT_YUYV			0x38
> > +#define OV1063X_FORMAT_YYYU			0x39
> > +#define OV1063X_FORMAT_UYVY			0x3a
> > +#define OV1063X_FORMAT_VYUY			0x3b
> > +#define OV1063X_FORMAT_YMAX			OV1063X_REG_16BIT(0x4302)
> > +#define OV1063X_FORMAT_YMIN			OV1063X_REG_16BIT(0x4304)
> > +#define OV1063X_FORMAT_UMAX			OV1063X_REG_16BIT(0x4306)
> > +#define OV1063X_FORMAT_UMIN			OV1063X_REG_16BIT(0x4308)
> > +
> > +#define OV1063X_VFIFO_LLEN_FIRS1_SEL		OV1063X_REG_8BIT(0x4605)
> > +#define OV1063X_VFIFO_LLEN_FIRS1_SEL_8B_YUV	BIT(3)
> > +#define OV1063X_VFIFO_LINE_LENGTH_MAN		OV1063X_REG_16BIT(0x4606)
> > +#define OV1063X_VFIFO_READ_START		OV1063X_REG_16BIT(0x4608)
> > +#define OV1063X_VFIFO_HSYNC_START_POSITION	OV1063X_REG_16BIT(0x460a)
> > +#define OV1063X_VFIFO_HSYNC_CTRL		OV1063X_REG_8BIT(0x460c)
> > +#define OV1063X_VFIFO_HSYNC_CTRL_HEADER_WIDTH(n)	((n) << 4)
> > +#define OV1063X_VFIFO_HSYNC_CTRL_TRAILER_WIDTH(n)	((n) << 0)
> > +#define OV1063X_VFIFO_EMBD_LINE_CTRL		OV1063X_REG_8BIT(0x460e)
> > +#define OV1063X_VFIFO_EMBD_LINE_CTRL_SOF_CLR_RAM	BIT(3)
> > +#define OV1063X_VFIFO_EMBD_LINE_CTRL_ST_MOD	BIT(2)
> > +#define OV1063X_VFIFO_EMBD_LINE_CTRL_EMBD_ROM	BIT(1)
> > +#define OV1063X_VFIFO_EMBD_LINE_CTRL_EMBD_EN	BIT(0)
> > +#define OV1063X_VFIFO_EMBD_LINE_NUM		OV1063X_REG_8BIT(0x460f)
> > +#define OV1063X_ROI_CTRL0			OV1063X_REG_8BIT(0x4620)
> > +#define OV1063X_ROI_CTRL0_SYNC_BYP		BIT(7)
> > +#define OV1063X_ROI_CTRL0_FR_COMP		BIT(6)
> > +#define OV1063X_ROI_CTRL0_FULL_DAT_MOD		BIT(5)
> > +#define OV1063X_ROI_CTRL0_EN_3			BIT(3)
> > +#define OV1063X_ROI_CTRL0_EN_2			BIT(2)
> > +#define OV1063X_ROI_CTRL0_EN_1			BIT(1)
> > +#define OV1063X_ROI_CTRL0_FUNC_E		BIT(0)
> > +
> > +#define OV1063X_DVP_MOD_SEL			OV1063X_REG_8BIT(0x4700)
> > +#define OV1063X_DVP_MOD_SEL_CCIR_V		BIT(3)
> > +#define OV1063X_DVP_MOD_SEL_CCIR_F		BIT(2)
> > +#define OV1063X_DVP_MOD_SEL_CCIR_656		BIT(1)
> > +#define OV1063X_DVP_MOD_SEL_HSYNC		BIT(0)
> > +#define OV1063X_DVP_VSYNC_WIDTH			OV1063X_REG_8BIT(0x4701)
> > +#define OV1063X_DVP_HSYVSY_NEG_WIDTH		OV1063X_REG_16BIT(0x4702)
> > +#define OV1063X_DVP_VSYNC_MODE			OV1063X_REG_8BIT(0x4704)
> > +#define OV1063X_DVP_VSYNC_MODE_VSYNCOUT_SEL(n)	((n) << 2)
> > +#define OV1063X_DVP_VSYNC_MODE_VSYNC3_MOD	BIT(1)
> > +#define OV1063X_DVP_VSYNC_MODE_VSYNC2_MOD	BIT(0)
> > +#define OV1063X_DVP_EOF_VSYNC_DELAY		OV1063X_REG_24BIT(0x4705)
> > +
> > +#define OV1063X_ISP_RW00			OV1063X_REG_8BIT(0x5000)
> > +#define OV1063X_ISP_RW00_COLOR_MATRIX_EN	BIT(7)
> > +#define OV1063X_ISP_RW00_COLOR_INTERP_EN	BIT(6)
> > +#define OV1063X_ISP_RW00_DENOISE_EN		BIT(5)
> > +#define OV1063X_ISP_RW00_WHITE_DPC_EN		BIT(4)	/* White defect pixel correction enable */
> > +#define OV1063X_ISP_RW00_BLACK_DPC_EN		BIT(3)	/* Black defect pixel connection enable */
> > +#define OV1063X_ISP_RW00_AWB_STATS_EN		BIT(2)
> > +#define OV1063X_ISP_RW00_AWB_GAIN_EN		BIT(1)
> > +#define OV1063X_ISP_RW00_LSC_EN			BIT(0)
> > +#define OV1063X_ISP_RW01			OV1063X_REG_8BIT(0x5001)
> > +#define OV1063X_ISP_RW01_DATA_WEIGHT_SYNC_EN	BIT(7)
> > +#define OV1063X_ISP_RW01_BLACK_WHITE_MODE_EN	BIT(6)
> > +#define OV1063X_ISP_RW01_DARK_LEVEL_FILTER_EN	BIT(5)
> > +#define OV1063X_ISP_RW01_BUFFER_CONTROL_EN	BIT(4)
> > +#define OV1063X_ISP_RW01_AEC_EN			BIT(3)
> > +#define OV1063X_ISP_RW01_TONE_MAPPING_EN	BIT(2)
> > +#define OV1063X_ISP_RW01_NORMALIZE_EN		BIT(1)
> > +#define OV1063X_ISP_RW01_LONG_SHORT_COMB_EN	BIT(0)
> > +#define OV1063X_ISP_RW02			OV1063X_REG_8BIT(0x5002)
> > +#define OV1063X_ISP_RW02_DIGITAL_GAIN_EN	BIT(3)
> > +#define OV1063X_ISP_RW02_WINDOW_BORDER_CUT_EN	BIT(2)
> > +#define OV1063X_ISP_RW02_DITHERING_EN		BIT(1)
> > +#define OV1063X_ISP_RW02_LSLS			(0U << 0)
> > +#define OV1063X_ISP_RW02_SLSL			(1U << 0)
> > +#define OV1063X_ISP_RW05			OV1063X_REG_8BIT(0x5005)
> > +#define OV1063X_ISP_RW05_VERT_SUB_EN		BIT(7)	/* Enable vertical subsampling */
> > +#define OV1063X_ISP_RW05_LSC_CENTER_AUTO	BIT(6)	/* Set LSC center automatically based on image window */
> > +#define OV1063X_ISP_RW05_SUB_OUT_ROW_2ND	BIT(5)	/* Output 2nd (1) or 1st (0) row when skipping */
> > +#define OV1063X_ISP_RW05_SUB_OUT_COL_2ND	BIT(4)	/* Output 2nd (1) or 1st (0) column when skipping */
> > +#define OV1063X_ISP_RW05_SUB_AVG		BIT(3)	/* Average (1) or sum (0) when binning */
> > +#define OV1063X_ISP_RW05_SUB_G_DROP		BIT(2)	/* Skip (1) or bin (0) Green / Y */
> > +#define OV1063X_ISP_RW05_SUB_RB_DROP		BIT(1)	/* Skip (1) or bin (0) Red Blue / UV */
> > +#define OV1063X_ISP_RW05_SUB_ENABLE		BIT(0)	/* Enable sub-sampling */
> > +#define OV1063X_ISP_RW06			OV1063X_REG_8BIT(0x5006)
> > +#define OV1063X_ISP_RW06_RAW_MODE_MAN(n)	((n) << 6)
> > +#define OV1063X_ISP_RW06_YUV_MODE_MAN(n)	((n) << 4)
> > +#define OV1063X_ISP_RW06_RAW_MODE_MAN_EN	BIT(3)
> > +#define OV1063X_ISP_RW06_YUV_MODE_MAN_EN	BIT(2)
> > +#define OV1063X_ISP_CTRL3D			OV1063X_REG_8BIT(0x503d)
> > +#define OV1063X_ISP_CTRL3D_TEST_PATTERN_EN	BIT(7)
> > +#define OV1063X_ISP_CTRL3D_COLOR_BAR(n)		((n) << 4)
> > +#define OV1063X_ISP_CTRL3D_ROLLING_BAR_EN	BIT(2)
> > +#define OV1063X_ISP_CTRL3E			OV1063X_REG_8BIT(0x503e)
> > +#define OV1063X_ISP_CTRL3E_SQUARE_BW		BIT(3)
> > +#define OV1063X_ISP_CTRL3E_TRANSPARENT_EN	BIT(2)
> > +#define OV1063X_ISP_CTRL3E_PATTERN_BARS		(0U << 0)
> > +#define OV1063X_ISP_CTRL3E_PATTERN_RANDOM	(1U << 0)
> > +#define OV1063X_ISP_CTRL3E_PATTERN_SQUARES	(2U << 0)
> > +
> > +#define OV1063X_GAIN_AWB_MAN_GAIN_B_LONG	OV1063X_REG_16BIT(0x5100)
> > +#define OV1063X_GAIN_AWB_MAN_GAIN_GB_LONG	OV1063X_REG_16BIT(0x5102)
> > +#define OV1063X_GAIN_AWB_MAN_GAIN_GR_LONG	OV1063X_REG_16BIT(0x5104)
> > +#define OV1063X_GAIN_AWB_MAN_GAIN_R_LONG	OV1063X_REG_16BIT(0x5106)
> > +#define OV1063X_GAIN_AWB_MAN_OFFSET_B_LONG	OV1063X_REG_16BIT(0x5108)
> > +#define OV1063X_GAIN_AWB_MAN_OFFSET_GB_LONG	OV1063X_REG_16BIT(0x510a)
> > +#define OV1063X_GAIN_AWB_MAN_OFFSET_GR_LONG	OV1063X_REG_16BIT(0x510c)
> > +#define OV1063X_GAIN_AWB_MAN_OFFSET_R_LONG	OV1063X_REG_16BIT(0x510e)
> > +#define OV1063X_GAIN_AWB_MAN_GAIN_B_SHORT	OV1063X_REG_16BIT(0x5110)
> > +#define OV1063X_GAIN_AWB_MAN_GAIN_GB_SHORT	OV1063X_REG_16BIT(0x5112)
> > +#define OV1063X_GAIN_AWB_MAN_GAIN_GR_SHORT	OV1063X_REG_16BIT(0x5114)
> > +#define OV1063X_GAIN_AWB_MAN_GAIN_R_SHORT	OV1063X_REG_16BIT(0x5116)
> > +#define OV1063X_GAIN_AWB_MAN_OFFSET_B_SHORT	OV1063X_REG_16BIT(0x5118)
> > +#define OV1063X_GAIN_AWB_MAN_OFFSET_GB_SHORT	OV1063X_REG_16BIT(0x511a)
> > +#define OV1063X_GAIN_AWB_MAN_OFFSET_GR_SHORT	OV1063X_REG_16BIT(0x511c)
> > +#define OV1063X_GAIN_AWB_MAN_OFFSET_R_SHORT	OV1063X_REG_16BIT(0x511e)
> > +#define OV1063X_GAIN_AWB_CTRL32			OV1063X_REG_8BIT(0x5120)
> > +#define OV1063X_GAIN_AWB_CTRL32_MANUAL_EN	BIT(0)
> > +
> > +#define OV1063X_DNS_NOISE_Y_LIST_LONG(n)	OV1063X_REG_8BIT(0x521a + (n))
> > +#define OV1063X_DNS_NOISE_UV_LIST_LONG(n)	OV1063X_REG_16BIT(0x5222 + (n) * 2)
> > +#define OV1063X_DNS_GBGR_EXTRA_SHORT		OV1063X_REG_8BIT(0x5241)
> > +#define OV1063X_DNS_NOISE_Y_LIST_SHORT(n)	OV1063X_REG_8BIT(0x5242 + (n))
> > +#define OV1063X_DNS_NOISE_UV_LIST_SHORT(n)	OV1063X_REG_16BIT(0x5249 + (n) * 2)
> > +#define OV1063X_CIP_UNSHARPEN_MASK_LONG(n)	OV1063X_REG_8BIT(0x5288 + (n))
> > +#define OV1063X_CIP_MAX_SHARPEN_LONG		OV1063X_REG_8BIT(0x528d)
> > +#define OV1063X_CIP_SHARPEN_ALPHA_LONG		OV1063X_REG_8BIT(0x5293)
> > +#define OV1063X_CIP_UNSHARPEN_MASK_SHORT(n)	OV1063X_REG_8BIT(0x52c8 + (n))
> > +#define OV1063X_CIP_MAX_SHARPEN_SHORT		OV1063X_REG_8BIT(0x52cd)
> > +#define OV1063X_CIP_SHARPEN_ALPHA_SHORT		OV1063X_REG_8BIT(0x52d3)
> > +#define OV1063X_CIP_HFREQ_COEF_SHORT		OV1063X_REG_8BIT(0x52d7)
> > +
> > +#define OV1063X_LLF_MAX_LOW_LEVEL		OV1063X_REG_16BIT(0x5381)
> > +
> > +#define OV1063X_AWB_CT_CTRL1			OV1063X_REG_8BIT(0x5581)
> > +#define OV1063X_AWB_CT_CTRL1_GAIN_STEP_NORMAL(n)	((n) << 6)
> > +#define OV1063X_AWB_CT_CTRL1_GAIN_STEP_FAST(n)	((n) << 4)
> > +#define OV1063X_AWB_CT_CTRL1_SCALE_LONG_2X	(0 << 2)
> > +#define OV1063X_AWB_CT_CTRL1_SCALE_LONG_4X	(1 << 2)
> > +#define OV1063X_AWB_CT_CTRL1_SCALE_LONG_8X	(2 << 2)
> > +#define OV1063X_AWB_M_RNG_LONG			OV1063X_REG_8BIT(0x5586)
> > +#define OV1063X_AWB_L_XRNG_LONG			OV1063X_REG_8BIT(0x5587)
> > +#define OV1063X_AWB_H_YRNG_LONG			OV1063X_REG_8BIT(0x5588)
> > +#define OV1063X_AWB_M_X_LONG			OV1063X_REG_8BIT(0x5589)
> > +#define OV1063X_AWB_M_Y_LONG			OV1063X_REG_8BIT(0x558a)
> > +#define OV1063X_AWB_L_K_LONG			OV1063X_REG_8BIT(0x558b)
> > +#define OV1063X_AWB_H_K_LONG			OV1063X_REG_8BIT(0x558c)
> > +#define OV1063X_AWB_H_LMT_LONG			OV1063X_REG_8BIT(0x558d)
> > +#define OV1063X_AWB_L_LMT_LONG			OV1063X_REG_8BIT(0x558e)
> > +#define OV1063X_AWB_DATA_ULMT_LONG		OV1063X_REG_8BIT(0x5591)
> > +#define OV1063X_AWB_DATA_LLMT_LONG		OV1063X_REG_8BIT(0x5592)
> > +#define OV1063X_AWB_M_RNG_SHORT			OV1063X_REG_8BIT(0x559f)
> > +#define OV1063X_AWB_L_XRNG_SHORT		OV1063X_REG_8BIT(0x55a0)
> > +#define OV1063X_AWB_H_YRNG_SHORT		OV1063X_REG_8BIT(0x55a1)
> > +#define OV1063X_AWB_M_X_SHORT			OV1063X_REG_8BIT(0x55a2)
> > +#define OV1063X_AWB_M_Y_SHORT			OV1063X_REG_8BIT(0x55a3)
> > +#define OV1063X_AWB_L_K_SHORT			OV1063X_REG_8BIT(0x55a4)
> > +#define OV1063X_AWB_H_K_SHORT			OV1063X_REG_8BIT(0x55a5)
> > +#define OV1063X_AWB_H_LMT_SHORT			OV1063X_REG_8BIT(0x55a6)
> > +#define OV1063X_AWB_L_LMT_SHORT			OV1063X_REG_8BIT(0x55a7)
> > +#define OV1063X_AWB_DATA_ULMT_SHORT		OV1063X_REG_8BIT(0x55aa)
> > +#define OV1063X_AWB_DATA_LLMT_SHORT		OV1063X_REG_8BIT(0x55ab)
> > +
> > +#define OV1063X_AEC_CTRL07			OV1063X_REG_16BIT(0x5607)
> > +#define OV1063X_AEC_WIN_LEFT_LONG		OV1063X_REG_16BIT(0x5609)
> > +#define OV1063X_AEC_WIN_LEFT_SHORT		OV1063X_REG_16BIT(0x560b)
> > +#define OV1063X_AEC_WIN_TOP_LONG		OV1063X_REG_16BIT(0x560d)
> > +#define OV1063X_AEC_WIN_TOP_SHORT		OV1063X_REG_16BIT(0x560f)
> > +#define OV1063X_AEC_WIN_WIDTH_LONG		OV1063X_REG_16BIT(0x5611)
> > +#define OV1063X_AEC_WIN_WIDTH_SHORT		OV1063X_REG_16BIT(0x5613)
> > +#define OV1063X_AEC_WIN_HEIGHT_LONG		OV1063X_REG_16BIT(0x5615)
> > +#define OV1063X_AEC_WIN_HEIGHT_SHORT		OV1063X_REG_16BIT(0x5617)
> > +#define OV1063X_AEC_WEIGHT_SHORT(n)		OV1063X_REG_8BIT(0x563b + (n))
> > +#define OV1063X_AEC_FINAL_SATURATE_THRESH	OV1063X_REG_16BIT(0x5651)
> > +#define OV1063X_AEC_CTRLD0			OV1063X_REG_8BIT(0x56d0)
> > +#define OV1063X_AEC_CTRLD0_R_MAN_EN(n)		((n) << 0)
> > +#define OV1063X_AEC_CTRLD5			OV1063X_REG_32BIT(0x56d5)	/* r_exp_l_m */
> > +#define OV1063X_AEC_CTRLD9			OV1063X_REG_32BIT(0x56d9)	/* r_exp_s_m */
> > +#define OV1063X_AEC_CTRLE8			OV1063X_REG_16BIT(0x56e8)	/* r_snrgain_l_m */
> > +#define OV1063X_AEC_CTRLEA			OV1063X_REG_16BIT(0x56ea)	/* r_snrgain_s_m */
> > +
> > +#define OV1063X_TPM_CTRL0			OV1063X_REG_8BIT(0x6706)
> > +#define OV1063X_TPM_CTRL0_CLK_DIV(n)		((n) << 0)
> > +
> > +#define OV1063X_GROUP_WRITER_COMMAND		OV1063X_REG_8BIT(0x6f00)
> > +#define OV1063X_GROUP_WRITER_COMMAND_OP(n)	((n) << 6)
> > +#define OV1063X_GROUP_WRITER_COMMAND_ID(n)	((n) << 4)
> > +#define OV1063X_GROUP_WRITER_COMMAND_EN		(3U << 0)
> > +#define OV1063X_PARI_ADDR_MIN			OV1063X_REG_16BIT(0x6f06)
> > +#define OV1063X_PARI_ADDR_MAX			OV1063X_REG_16BIT(0x6f0a)
> > +
> > +#define OV1063X_EMB_LINE_EN			OV1063X_REG_8BIT(0x6800)
> > +#define OV1063X_EMB_LINE_EN_ENABLE		BIT(0)
> > +#define OV1063X_EMB_SIZE_MANU_EN		OV1063X_REG_8BIT(0x6804)
> > +#define OV1063X_EMB_SIZE_EN_ENABLE		BIT(0)
> > +#define OV1063X_EMB_SIZE_MANU			OV1063X_REG_16BIT(0x6805)
> > +
> > +#define OV1063X_HORIZ_COLORCORRECT		OV1063X_REG_8BIT(0x6900)
> > +#define OV1063X_HORIZ_COLORCORRECT_ON		BIT(0)
> > +
> > +#define OV1063X_AEC_TARGET_NUM			OV1063X_REG_8BIT(0xc450)
> > +#define OV1063X_AEC_TARGET_NUM_AA_MODE		(1U << 0)
> > +#define OV1063X_AEC_TARGET_NUM_AB_MODE		(2U << 0)
> > +#define OV1063X_AEC_TARGET_NUM_ABC_MODE		(3U << 0)
> > +#define OV1063X_AEC_LS_SENS_RATIO		OV1063X_REG_16BIT(0xc452)
> > +#define OV1063X_AEC_NONWDR_EN			OV1063X_REG_8BIT(0xc454)
> > +#define OV1063X_AEC_NONWDR_SWITCH		OV1063X_REG_8BIT(0xc455)
> > +#define OV1063X_AEC_FIXED_RATIO_EN		OV1063X_REG_8BIT(0xc456)
> > +#define OV1063X_AEC_GP_MODE_EN			OV1063X_REG_8BIT(0xc457)
> > +#define OV1063X_AEC_NIGHT_MODE_EN		OV1063X_REG_8BIT(0xc458)
> > +#define OV1063X_AEC_NIGHT_MODE_CTRL		OV1063X_REG_8BIT(0xc459)
> > +#define OV1063X_AEC_NIGHT_MODE_CTRL_INSERT	BIT(0)
> > +#define OV1063X_AEC_FRACTAL_EXP_EN		OV1063X_REG_8BIT(0xc45a)
> > +#define OV1063X_AEC_NONLINEAR_GAIN_EN		OV1063X_REG_8BIT(0xc45b)
> > +#define OV1063X_AEC_MANU_GAMMA_EN		OV1063X_REG_8BIT(0xc45c)
> > +#define OV1063X_AEC_HOLD_BAND_EN		OV1063X_REG_8BIT(0xc45d)
> > +#define OV1063X_AEC_BAND_FILTER_FLAG		OV1063X_REG_8BIT(0xc45e)
> > +#define OV1063X_AEC_BAND_FILTER_FLAG_0HZ	(0U << 0)
> > +#define OV1063X_AEC_BAND_FILTER_FLAG_60HZ	(1U << 0)
> > +#define OV1063X_AEC_BAND_FILTER_FLAG_50HZ	(2U << 0)
> > +#define OV1063X_AEC_BAND_FILTER_EN		OV1063X_REG_8BIT(0xc45f)
> > +#define OV1063X_AEC_BAND_FILTER_SHORT		OV1063X_REG_8BIT(0xc460)
> > +#define OV1063X_AEC_LESS_1BAND_EN		OV1063X_REG_8BIT(0xc461)
> > +#define OV1063X_AEC_LESS_1BAND_SHORT		OV1063X_REG_8BIT(0xc462)
> > +#define OV1063X_AEC_WDR_GAIN_LIMIT_EN		OV1063X_REG_8BIT(0xc463)
> > +#define OV1063X_AEC_LOG_TARGET(n)		OV1063X_REG_16BIT(0xc464 + (n) * 2)
> > +#define OV1063X_AEC_TARGET_LONG(n)		OV1063X_REG_8BIT(0xc46a + (n))
> > +#define OV1063X_AEC_TARGET_SHORT(n)		OV1063X_REG_8BIT(0xc46d + (n))
> > +#define OV1063X_AEC_MAX_SHORT_LE		OV1063X_REG_32BIT(0xc47c)
> > +#define OV1063X_AEC_MAX_GAIN_LONG		OV1063X_REG_16BIT(0xc480)
> > +#define OV1063X_AEC_MAX_GAIN_SHORT		OV1063X_REG_16BIT(0xc482)
> > +#define OV1063X_AEC_MIN_GAIN_LONG		OV1063X_REG_16BIT(0xc484)
> > +#define OV1063X_AEC_MIN_GAIN_SHORT		OV1063X_REG_16BIT(0xc486)
> > +#define OV1063X_AEC_MAX_EXP_LONG		OV1063X_REG_16BIT(0xc488)
> > +#define OV1063X_AEC_MAX_EXP_SHORT		OV1063X_REG_16BIT(0xc48a)
> > +#define OV1063X_AEC_MIN_EXP_LONG		OV1063X_REG_16BIT(0xc48c)
> > +#define OV1063X_AEC_MIN_EXP_SHORT		OV1063X_REG_16BIT(0xc48e)
> > +#define OV1063X_AEC_FIXED_RATIO			OV1063X_REG_8BIT(0xc490)
> > +#define OV1063X_AEC_GP_MODE_RATIO_B2A		OV1063X_REG_8BIT(0xc492)
> > +#define OV1063X_AEC_GP_MODE_RATIO_C2A		OV1063X_REG_8BIT(0xc493)
> > +#define OV1063X_AEC_MIN_GAMMA_LIST(n)		OV1063X_REG_16BIT(0xc498 + (n) * 2)
> > +#define OV1063X_AEC_MAX_GAMMA_LIST(n)		OV1063X_REG_16BIT(0xc49e + (n) * 2)
> > +#define OV1063X_AEC_DR_LIST(n)			OV1063X_REG_16BIT(0xc4a4 + (n) * 2)
> > +#define OV1063X_AEC_BAND_VALUE_60HZ		OV1063X_REG_16BIT(0xc4aa)
> > +#define OV1063X_AEC_BAND_VALUE_50HZ		OV1063X_REG_16BIT(0xc4ac)
> > +
> > +#define OV1063X_AWB_SIMPLE_MIN_NUM		OV1063X_REG_16BIT(0xc4cc)
> > +#define OV1063X_AWB_CT_MIN_NUM			OV1063X_REG_16BIT(0xc4ce)
> > +
> > +#define OV1063X_VTS_ADDR			OV1063X_REG_16BIT(0xc518)
> > +#define OV1063X_HTS_ADDR			OV1063X_REG_16BIT(0xc51a)
> > +
> > +#include "ov1063x_regs.h"
> > +
> > +/* IDs */
> > +#define OV10633_VERSION_REG			0xa630
> > +#define OV10635_VERSION_REG			0xa635
> > +
> > +enum ov1063x_model {
> > +	SENSOR_OV10633,
> > +	SENSOR_OV10635,
> > +};
> > +
> > +#define OV1063X_SENSOR_WIDTH			1312
> > +#define OV1063X_SENSOR_HEIGHT			814
> > +
> > +struct ov1063x_priv {
> > +	struct device			*dev;
> > +
> > +	struct regmap			*regmap;
> > +	struct clk			*clk;
> > +	struct gpio_desc		*reset_gpio;
> > +	struct gpio_desc		*pwdn_gpio;
> > +
> > +	int				model;
> > +	const char			*name;
> > +	unsigned long			clk_rate;
> > +
> > +	struct v4l2_subdev		subdev;
> > +	struct media_pad		pad;
> > +
> > +	struct v4l2_ctrl_handler	hdl;
> > +
> > +	/*
> > +	 * The streaming and format fields are protected by the control handler
> > +	 * lock.
> > +	 */
> > +	bool				streaming;
> > +	struct v4l2_rect		analog_crop;
> > +	struct v4l2_rect		digital_crop;
> > +	struct v4l2_mbus_framefmt	format;
> > +
> > +	unsigned int			fps_numerator;
> > +	unsigned int			fps_denominator;
> > +};
> > +
> > +/*
> > + * TODO: Expose multiple subdevs to control cropping and subsampling separately
> > + * from userspace instead of hardcoding resolutions.
> > + *
> > + * TODO: Resolutions with an analog crop rectangle width equal to 768 or higher
> > + * don't work properly.
> > + */
> > +static const struct v4l2_area ov1063x_framesizes[] = {
> > +	{
> > +		.width		= 1280,
> > +		.height		= 800,
> > +	}, {
> > +		.width		= 1280,
> > +		.height		= 720,
> > +	}, {
> > +		.width		= 752,
> > +		.height		= 480,
> > +	}, {
> > +		.width		= 640,
> > +		.height		= 480,
> > +	}, {
> > +		.width		= 600,
> > +		.height		= 400,
> > +	}, {
> > +		.width		= 352,
> > +		.height		= 288,
> > +	}, {
> > +		.width		= 320,
> > +		.height		= 240,
> > +	},
> > +};
> > +
> > +static const u32 ov1063x_mbus_formats[] = {
> > +	MEDIA_BUS_FMT_YUYV8_2X8,
> > +	MEDIA_BUS_FMT_UYVY8_2X8,
> > +	MEDIA_BUS_FMT_VYUY8_2X8,
> > +	MEDIA_BUS_FMT_YVYU8_2X8,
> > +};
> > +
> > +static inline struct ov1063x_priv *to_ov1063x(struct v4l2_subdev *sd)
> > +{
> > +	return container_of(sd, struct ov1063x_priv, subdev);
> > +}
> > +
> > +/* -----------------------------------------------------------------------------
> > + * Read/Write Helpers
> > + */
> > +
> > +static int ov1063x_read(struct ov1063x_priv *priv, u32 reg, u32 *val)
> > +{
> > +	unsigned int len = (reg >> OV1063X_REG_SIZE_SHIFT) & 3;
> > +	u16 addr = reg & OV1063X_REG_ADDR_MASK;
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	*val = 0;
> > +
> > +	for (i = 0; i < len; ++i) {
> > +		u32 byte;
> > +
> > +		ret = regmap_read(priv->regmap, addr, &byte);
> > +		if (ret)
> > +			return ret;
> > +
> > +		*val = (*val << 8) | byte;
> > +		addr++;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_write(struct ov1063x_priv *priv, u32 reg, u32 val, int *err)
> > +{
> > +	unsigned int len = (reg >> OV1063X_REG_SIZE_SHIFT) & 7;
> > +	u16 addr = reg & OV1063X_REG_ADDR_MASK;
> > +	unsigned int shift = (len - 1) * 8;
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	if (err && *err)
> > +		return *err;
> > +
> > +	for (i = 0; i < len; ++i) {
> > +		ret = regmap_write(priv->regmap, addr, (val >> shift) & 0xff);
> > +		if (ret) {
> > +			if (err)
> > +				*err = ret;
> > +			return ret;
> > +		}
> > +
> > +		shift -= 8;
> > +		addr++;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_write_array(struct ov1063x_priv *priv,
> > +			       const struct ov1063x_reg *regs,
> > +			       unsigned int nr_regs)
> > +{
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	for (i = 0; i < nr_regs; i++) {
> > +		ret = ov1063x_write(priv, regs[i].reg, regs[i].val, NULL);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_update(struct ov1063x_priv *priv, u32 reg, u32 mask, u32 val,
> > +			  int *err)
> > +{
> > +	unsigned int len = (reg >> OV1063X_REG_SIZE_SHIFT) & 7;
> > +	u16 addr = reg & OV1063X_REG_ADDR_MASK;
> > +	unsigned int shift = (len - 1) * 8;
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	if (err && *err)
> > +		return *err;
> > +
> > +	for (i = 0; i < len; ++i) {
> > +		ret = regmap_update_bits(priv->regmap, addr,
> > +					 (mask >> shift) & 0xff,
> > +					 (val >> shift) & 0xff);
> > +		if (ret) {
> > +			if (err)
> > +				*err = ret;
> > +			return ret;
> > +		}
> > +
> > +		shift -= 8;
> > +		addr++;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/* -----------------------------------------------------------------------------
> > + * Hardware Configuration
> > + */
> > +
> > +struct ov1063x_pll_config {
> > +	unsigned int pre_div;
> > +	unsigned int mult;
> > +	unsigned int div;
> > +	unsigned int clk_out;
> > +};
> > +
> > +static int ov1063x_pll_setup(unsigned int clk_rate,
> > +			     unsigned int *htsmin, unsigned int vts,
> > +			     unsigned int fps_numerator,
> > +			     unsigned int fps_denominator,
> > +			     struct ov1063x_pll_config *cfg)
> > +{
> > +	static const unsigned int pre_divs[] = { 2, 3, 4, 6, 8, 10, 12, 14 };
> > +
> > +	unsigned int best_pclk = UINT_MAX;
> > +	unsigned int best_pre_div;
> > +	unsigned int best_mult;
> > +	unsigned int best_div;
> > +	unsigned int best_hts;
> > +	unsigned int max_pre_div;
> > +	unsigned int pre_div;
> > +	unsigned int hts;
> > +
> > +	/*
> > +	 *  XVCLK --> pre-div -------> mult ----------> div --> output
> > +	 * 6-27 MHz           3-27 MHz      200-500 MHz       Max 96 MHz
> > +	 *
> > +	 * Valid pre-divider values are 1, 1.5, 2, 3, 4, 5, 6 and 7. The
> > +	 * pre_divs array stores the pre-dividers multiplied by two, indexed by
> > +	 * register values.
> > +	 *
> > +	 * Valid multiplier values are [1, 63], stored as-is in registers.
> > +	 *
> > +	 * Valid divider values are 2 to 16 with a step of 2, stored in
> > +	 * registers as (div / 2) - 1.
> > +	 */
> > +
> > +	if (clk_rate < 6 * 1000 * 1000 || clk_rate > 27 * 1000 * 1000)
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * We try all valid combinations of settings for the 3 blocks to get
> > +	 * the pixel clock, and from that calculate the actual hts/vts to use.
> > +	 * The vts is extended so as to achieve the required frame rate.
> > +	 */
> > +
> > +	max_pre_div = max(clk_rate / (3 * 1000 * 1000),
> > +			  ARRAY_SIZE(pre_divs) - 1);
> > +
> > +	for (pre_div = 0; pre_div <= max_pre_div; pre_div++) {
> > +		unsigned int clk1 = clk_rate * 2 / pre_divs[pre_div];
> > +		unsigned int min_mult;
> > +		unsigned int max_mult;
> > +		unsigned int mult;
> > +
> > +		if (clk1 < 3 * 1000 * 1000 || clk1 > 27 * 1000 * 1000)
> > +			continue;
> > +
> > +		min_mult = DIV_ROUND_UP(200 * 1000 * 1000, clk1);
> > +		max_mult = min(500 * 1000 * 1000 / clk1, 63U);
> > +
> > +		for (mult = min_mult; mult <= max_mult; mult++) {
> > +			unsigned int clk2 = clk1 * mult;
> > +			unsigned int min_div;
> > +			unsigned int div;
> > +
> > +			min_div = DIV_ROUND_UP(clk2, 96 * 1000 * 1000);
> > +			min_div = round_up(min_div, 2);
> > +
> > +			for (div = min_div; div <= 16; div += 2) {
> > +				unsigned int pclk = clk2 / div;
> > +				unsigned int min_pclk;
> > +
> > +				/*
> > +				 * TODO: HTS calculation should ideally be split
> > +				 * from the PLL calculations. This requires
> > +				 * figuring out where the pclk / 300000 comes
> > +				 * from.
> > +				 */
> > +				hts = *htsmin + pclk / (300*1000);
> > +
> > +				/* 2 clock cycles for every YUV422 pixel. */
> > +				min_pclk = hts * vts / fps_denominator
> > +					 * fps_numerator * 2;
> > +				if (pclk < min_pclk)
> > +					continue;
> > +
> > +				if (pclk < best_pclk) {
> > +					best_pclk = pclk;
> > +					best_hts = hts;
> > +					best_pre_div = pre_div;
> > +					best_mult = mult;
> > +					best_div = div;
> 
> Can the requested frame rate exceed the highest possible rate here?

The frame rate is hardcoded to 30fps. It's a leftover of the old driver,
it shouldn't be taken into account at all in this function. Ideally it
should be configured from userspace through hts/vts. I however wonder
what pclk frequency the driver should select in that case.

> You already control the sensor's PLL and other capabilities such as
> analogue cropping directly. You could make these all configurable from the
> user space the same way the ccs driver does. What do you think?

Please see the cover letter :-) I'd appreciate advices on how to solve
the problem mentioned there.

> > +				}
> > +			}
> > +		}
> > +	}
> > +
> > +	if (best_pclk == UINT_MAX)
> > +		return -EINVAL;
> > +
> > +	cfg->mult = best_mult;
> > +	cfg->pre_div = best_pre_div;
> > +	cfg->div = (best_div / 2) - 1;
> > +	cfg->clk_out = best_pclk;
> > +
> > +	*htsmin = best_hts;
> > +
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_isp_reset(struct ov1063x_priv *priv, bool reset)
> > +{
> > +	unsigned int i;
> > +	int ret = 0;
> > +
> > +	if (!reset) {
> > +		/*
> > +		 * Enable ISP blocks. Why OV1063X_SC_SOC_CLKRST7 needs to be
> > +		 * written 26 times is unknown.
> > +		 */
> > +		for (i = 0; i < 26; ++i)
> > +			ov1063x_write(priv, OV1063X_SC_SOC_CLKRST7,
> > +				      OV1063X_SC_SOC_CLKRST7_SCLK, &ret);
> > +
> > +		ov1063x_write(priv, OV1063X_SC_CMMN_CLKRST1,
> > +			      OV1063X_SC_CMMN_CLKRST1_SCLK, &ret);
> > +		ov1063x_write(priv, OV1063X_SC_CMMN_CLKRST2,
> > +			      OV1063X_SC_CMMN_CLKRST2_PCLK_DVP |
> > +			      OV1063X_SC_CMMN_CLKRST2_SCLK, &ret);
> > +		ov1063x_write(priv, OV1063X_SC_CMMN_CLKRST0,
> > +			      OV1063X_SC_CMMN_CLKRST0_SCLK, &ret);
> > +	} else {
> > +		/* Reset the ISP. */
> > +		ov1063x_write(priv, OV1063X_SC_CMMN_CLKRST1,
> > +			      OV1063X_SC_CMMN_CLKRST1_SCLK |
> > +			      OV1063X_SC_CMMN_CLKRST1_RST, &ret);
> > +		ov1063x_write(priv, OV1063X_SC_CMMN_CLKRST2,
> > +			      OV1063X_SC_CMMN_CLKRST2_PCLK_DVP |
> > +			      OV1063X_SC_CMMN_CLKRST2_SCLK |
> > +			      OV1063X_SC_CMMN_CLKRST2_RST_DVP |
> > +			      OV1063X_SC_CMMN_CLKRST2_RST, &ret);
> > +		ov1063x_write(priv, OV1063X_SC_CMMN_CLKRST0,
> > +			      OV1063X_SC_CMMN_CLKRST0_SCLK |
> > +			      OV1063X_SC_CMMN_CLKRST0_RST, &ret);
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int ov1063x_configure(struct ov1063x_priv *priv)
> > +{
> > +	struct ov1063x_pll_config pll_cfg;
> > +	unsigned int width_pre_subsample;
> > +	unsigned int nr_isp_pixels;
> > +	unsigned int hts, vts;
> > +	u32 val;
> > +	int ret;
> > +
> > +	/* Minimum values for HTS anv VTS. */
> > +	hts = priv->analog_crop.width + 200;
> > +	vts = priv->analog_crop.height + 50;
> > +
> > +	/*
> > +	 * Get the best PCLK and adjust HTS accordingly. Adjust VTS to get as
> > +	 * close to the desired frame rate as we can.
> > +	 */
> > +	ret = ov1063x_pll_setup(priv->clk_rate, &hts, vts,
> > +				priv->fps_numerator, priv->fps_denominator,
> > +				&pll_cfg);
> > +	if (ret < 0)
> > +		return -EINVAL;
> > +
> > +	vts = pll_cfg.clk_out
> > +	    / (hts * 2 * priv->fps_numerator / priv->fps_denominator);
> > +
> > +	dev_dbg(priv->dev, "active %ux%u (total %ux%u) %u/%u fps, @%u MP/s\n",
> > +		priv->format.width, priv->format.height,
> > +		hts, vts, priv->fps_numerator, priv->fps_denominator,
> > +		pll_cfg.clk_out);
> > +	dev_dbg(priv->dev, "PLL pre-div %u mult %u div %u\n",
> > +		pll_cfg.pre_div, pll_cfg.mult, pll_cfg.div);
> > +
> > +	/* Reset the ISP and configure the PLL. */
> > +	ret = ov1063x_isp_reset(priv, true);
> > +
> > +	ov1063x_write(priv, OV1063X_SC_CMMN_PLL_CTRL0, pll_cfg.mult, &ret);
> > +	ov1063x_write(priv, OV1063X_SC_CMMN_PLL_CTRL1,
> > +		      (pll_cfg.pre_div << 4) | pll_cfg.div, &ret);
> > +
> > +	/* Analog array configuration (including horizontal cropping) */
> > +	switch (priv->analog_crop.width) {
> > +	case OV1063X_SENSOR_WIDTH:
> > +	default:
> > +		val = 0x60 | OV1063X_ANA_ARRAY1_FULL
> > +		    | OV1063X_ANA_ARRAY1_DELAY(3);
> > +		break;
> > +	case 768:
> > +		val = 0x60 | OV1063X_ANA_ARRAY1_CROP_768
> > +		    | OV1063X_ANA_ARRAY1_DELAY(3);
> > +		break;
> > +	case 656:
> > +		val = 0x60 | OV1063X_ANA_ARRAY1_CROP_656
> > +		    | OV1063X_ANA_ARRAY1_DELAY(3);
> > +		break;
> > +	}
> > +
> > +	ov1063x_write(priv, OV1063X_ANA_ARRAY1, val, &ret);
> > +
> > +	/* Sensor configuration */
> > +	ov1063x_write(priv, OV1063X_SENSOR_RSTGOLOW,
> > +		      (pll_cfg.clk_out + 1500000) / 3000000, &ret);
> > +	ov1063x_write(priv, OV1063X_SENSOR_HLDWIDTH,
> > +		      (pll_cfg.clk_out + 666666) / 1333333, &ret);
> > +	ov1063x_write(priv, OV1063X_SENSOR_TXWIDTH,
> > +		      (pll_cfg.clk_out + 961500) / 1923000, &ret);
> > +
> > +	/*
> > +	 * Timings (including cropping)
> > +	 *
> > +	 * TODO: The vertical size is set to the height of the analog crop
> > +	 * rectangle plus 4 pixels. This margin is probably used by the ISP for
> > +	 * CFA interpolation, and should be moved to the crop rectangle height
> > +	 * after investigating how the ISP operates.
> > +	 */
> > +	ov1063x_write(priv, OV1063X_TIMING_Y_START_ADDR,
> > +		      priv->analog_crop.top, &ret);
> > +	ov1063x_write(priv, OV1063X_TIMING_Y_END_ADDR,
> > +		      priv->analog_crop.top + priv->analog_crop.height + 3,
> > +		      &ret);
> > +	ov1063x_write(priv, OV1063X_TIMING_ISP_X_WIN, priv->digital_crop.left,
> > +		      &ret);
> > +	ov1063x_write(priv, OV1063X_TIMING_ISP_Y_WIN, priv->digital_crop.top,
> > +		      &ret);
> > +	ov1063x_write(priv, OV1063X_TIMING_X_OUTPUT_SIZE, priv->format.width,
> > +		      &ret);
> > +	ov1063x_write(priv, OV1063X_TIMING_Y_OUTPUT_SIZE, priv->format.height,
> > +		      &ret);
> > +	ov1063x_write(priv, OV1063X_TIMING_HTS, hts, &ret);
> > +	ov1063x_write(priv, OV1063X_TIMING_VTS, vts, &ret);
> > +
> > +	/*
> > +	 * Sub-sampling. Horizontal sub-sampling is applied in the ISP, vertical
> > +	 * sub-sampling in the pixel array.
> > +	 */
> > +	if (priv->format.width <= 640) {
> > +		ov1063x_write(priv, OV1063X_ISP_RW05, OV1063X_ISP_RW05_SUB_AVG |
> > +			      OV1063X_ISP_RW05_SUB_ENABLE, &ret);
> > +		ov1063x_write(priv, OV1063X_SC_CMMN_PCLK_DIV_CTRL, 2, &ret);
> > +	} else {
> > +		ov1063x_write(priv, OV1063X_ISP_RW05, OV1063X_ISP_RW05_SUB_AVG,
> > +			      &ret);
> > +		ov1063x_write(priv, OV1063X_SC_CMMN_PCLK_DIV_CTRL, 1, &ret);
> > +	}
> > +
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	if (priv->format.height <= 400)
> > +		ret = ov1063x_write_array(priv, ov1063x_regs_vert_sub2,
> > +					  ARRAY_SIZE(ov1063x_regs_vert_sub2));
> > +	else
> > +		ret = ov1063x_write_array(priv, ov1063x_regs_vert_no_sub,
> > +					  ARRAY_SIZE(ov1063x_regs_vert_no_sub));
> > +
> > +	/*
> > +	 * AEC & AWB
> > +	 *
> > +	 * TODO: The number of pixels fed to the ISP is computed using the
> > +	 * analog crop width and the vertical output size, to account for the
> > +	 * fact that vertical sub-sampling is applied in the pixel array while
> > +	 * horizontal sub-sampling is applied in the ISP. The 4 pixels margin
> > +	 * seems incorrect when sub-sampling, as the vertical timing start and
> > +	 * stop registers are programmed with a 4 pixels margin before
> > +	 * sub-sampling, the ISP should thus receive a 2 pixels margin only.
> > +	 * This needs to be investigated.
> > +	 *
> > +	 * TODO: When applying vertical digital crop, the output height is
> > +	 * likely the wrong value to compute the total number of pixels fed to
> > +	 * the ISP.
> > +	 */
> > +	val = (vts - 8) * 16;
> > +	ov1063x_write(priv, OV1063X_AEC_MAX_EXP_LONG, val, &ret);
> > +	ov1063x_write(priv, OV1063X_AEC_MAX_EXP_SHORT, val, &ret);
> > +
> > +	nr_isp_pixels = priv->analog_crop.width * (priv->format.height + 4);
> > +	ov1063x_write(priv, OV1063X_AWB_SIMPLE_MIN_NUM, nr_isp_pixels / 256, &ret);
> > +	ov1063x_write(priv, OV1063X_AWB_CT_MIN_NUM, nr_isp_pixels / 256, &ret);
> > +	ov1063x_write(priv, OV1063X_REG_16BIT(0xc512), nr_isp_pixels / 16,
> > +		      &ret);
> > +
> > +	ov1063x_write(priv, OV1063X_VTS_ADDR, vts, &ret);
> > +	ov1063x_write(priv, OV1063X_HTS_ADDR, hts, &ret);
> > +
> > +	/* FIFO */
> > +	ov1063x_write(priv, OV1063X_VFIFO_LLEN_FIRS1_SEL,
> > +		      OV1063X_VFIFO_LLEN_FIRS1_SEL_8B_YUV, &ret);
> > +	width_pre_subsample = priv->format.width <= 640
> > +			    ? priv->format.width * 2 : priv->format.width;
> > +	ov1063x_write(priv, OV1063X_VFIFO_LINE_LENGTH_MAN, 2 * hts, &ret);
> > +	ov1063x_write(priv, OV1063X_VFIFO_HSYNC_START_POSITION,
> > +		      2 * (hts - width_pre_subsample), &ret);
> > +
> > +	/* Output interface (DVP). */
> > +	switch (priv->format.code) {
> > +	case MEDIA_BUS_FMT_UYVY8_2X8:
> > +		val = OV1063X_FORMAT_UYVY;
> > +		break;
> > +	case MEDIA_BUS_FMT_VYUY8_2X8:
> > +		val = OV1063X_FORMAT_VYUY;
> > +		break;
> > +	case MEDIA_BUS_FMT_YUYV8_2X8:
> > +		val = OV1063X_FORMAT_YUYV;
> > +		break;
> > +	case MEDIA_BUS_FMT_YVYU8_2X8:
> > +		val = OV1063X_FORMAT_YYYU;
> > +		break;
> > +	default:
> > +		val = OV1063X_FORMAT_UYVY;
> > +		break;
> > +	}
> > +
> > +	ov1063x_write(priv, OV1063X_FORMAT_CTRL00, val, &ret);
> > +	ov1063x_write(priv, OV1063X_DVP_MOD_SEL, 0, &ret);
> > +
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* Take the ISP out of reset. */
> > +	return ov1063x_isp_reset(priv, false);
> > +}
> > +
> > +/* -----------------------------------------------------------------------------
> > + * V4L2 Control Operations
> > + */
> > +
> > +static const char * const ov1063x_test_pattern_menu[] = {
> > +	"Disabled",
> > +	"Color Bars, Plain",
> > +	"Color Bars, Vertical Gradient",
> > +	"Color Bars, Horizontal Gradient",
> > +	"Color Bars, Repeating",
> > +	"Random Data",
> > +	"Squares, Color",
> > +	"Squares, Black & White",
> > +};
> > +
> > +struct ov1063x_tpg_config {
> > +	u8 ctrl3d;
> > +	u8 ctrl3e;
> > +};
> > +
> > +static const struct ov1063x_tpg_config
> > +ov1063x_tpg_configs[ARRAY_SIZE(ov1063x_test_pattern_menu) - 1] = {
> > +	{
> > +		.ctrl3d = OV1063X_ISP_CTRL3D_TEST_PATTERN_EN
> > +			| OV1063X_ISP_CTRL3D_COLOR_BAR(0),
> > +		.ctrl3e = OV1063X_ISP_CTRL3E_PATTERN_BARS,
> > +	}, {
> > +		.ctrl3d = OV1063X_ISP_CTRL3D_TEST_PATTERN_EN
> > +			| OV1063X_ISP_CTRL3D_COLOR_BAR(1),
> > +		.ctrl3e = OV1063X_ISP_CTRL3E_PATTERN_BARS,
> > +	}, {
> > +		.ctrl3d = OV1063X_ISP_CTRL3D_TEST_PATTERN_EN
> > +			| OV1063X_ISP_CTRL3D_COLOR_BAR(2),
> > +		.ctrl3e = OV1063X_ISP_CTRL3E_PATTERN_BARS,
> > +	}, {
> > +		.ctrl3d = OV1063X_ISP_CTRL3D_TEST_PATTERN_EN
> > +			| OV1063X_ISP_CTRL3D_COLOR_BAR(3),
> > +		.ctrl3e = OV1063X_ISP_CTRL3E_PATTERN_BARS,
> > +	}, {
> > +		.ctrl3d = OV1063X_ISP_CTRL3D_TEST_PATTERN_EN,
> > +		.ctrl3e = OV1063X_ISP_CTRL3E_PATTERN_RANDOM,
> > +	}, {
> > +		.ctrl3d = OV1063X_ISP_CTRL3D_TEST_PATTERN_EN,
> > +		.ctrl3e = OV1063X_ISP_CTRL3E_PATTERN_SQUARES,
> > +	}, {
> > +		.ctrl3d = OV1063X_ISP_CTRL3D_TEST_PATTERN_EN,
> > +		.ctrl3e = OV1063X_ISP_CTRL3E_SQUARE_BW
> > +			| OV1063X_ISP_CTRL3E_PATTERN_SQUARES,
> > +	},
> > +};
> > +
> > +static int ov1063x_tpg_setup(struct ov1063x_priv *priv, struct v4l2_ctrl *ctrl)
> > +{
> > +	const struct ov1063x_tpg_config *cfg;
> > +	int ret = 0;
> > +
> > +	if (!ctrl->val)
> > +		return ov1063x_write_array(priv, ov1063x_regs_colorbar_disable,
> > +					   ARRAY_SIZE(ov1063x_regs_colorbar_disable));
> > +
> > +	if (!ctrl->cur.val) {
> > +		/*
> > +		 * Only write the full settings when the test pattern was
> > +		 * disabled, not when we're just changing the test pattern type.
> > +		 */
> > +		ret = ov1063x_write_array(priv, ov1063x_regs_colorbar_enable,
> > +					  ARRAY_SIZE(ov1063x_regs_colorbar_enable));
> > +		if (ret < 0)
> > +			return ret;
> > +	}
> > +
> > +	cfg = &ov1063x_tpg_configs[ctrl->val - 1];
> > +
> > +	/* TODO: Add support for the moving bar overlay. */
> > +	ov1063x_write(priv, OV1063X_ISP_CTRL3D, cfg->ctrl3d, &ret);
> > +	ov1063x_write(priv, OV1063X_ISP_CTRL3E, cfg->ctrl3e, &ret);
> > +
> > +	return ret;
> > +}
> > +
> > +static int ov1063x_s_ctrl(struct v4l2_ctrl *ctrl)
> > +{
> > +	struct ov1063x_priv *priv = container_of(ctrl->handler,
> > +					struct ov1063x_priv, hdl);
> > +	int ret = 0;
> > +
> > +	if (!priv->streaming)
> > +		return 0;
> > +
> > +	switch (ctrl->id) {
> > +	case V4L2_CID_VFLIP: {
> > +		const u32 vflip = OV1063X_TIMING_CTRL1C_VFLIP_DIG
> > +				| OV1063X_TIMING_CTRL1C_VFLIP_ARRAY;
> > +
> > +		return ov1063x_update(priv, OV1063X_TIMING_CTRL1C, vflip,
> > +				      ctrl->val ? vflip : 0, NULL);
> > +	}
> > +
> > +	case V4L2_CID_HFLIP: {
> > +		const u32 hflip = OV1063X_TIMING_CTRL1D_HFLIP_DIG
> > +				| OV1063X_TIMING_CTRL1D_HFLIP_ARRAY;
> > +
> > +		ov1063x_update(priv, OV1063X_HORIZ_COLORCORRECT,
> > +			       OV1063X_HORIZ_COLORCORRECT_ON,
> > +			       ctrl->val ? OV1063X_HORIZ_COLORCORRECT_ON : 0,
> > +			       &ret);
> > +		ov1063x_update(priv, OV1063X_TIMING_CTRL1D, hflip,
> > +			       ctrl->val ? hflip : 0, &ret);
> > +		return ret;
> > +	}
> > +
> > +	case V4L2_CID_TEST_PATTERN:
> > +		return ov1063x_tpg_setup(priv, ctrl);
> > +	}
> > +
> > +	return -EINVAL;
> > +}
> > +
> > +static const struct v4l2_ctrl_ops ov1063x_ctrl_ops = {
> > +	.s_ctrl = ov1063x_s_ctrl,
> > +};
> > +
> > +/* -----------------------------------------------------------------------------
> > + * V4L2 Subdev Operations
> > + */
> > +
> > +static int ov1063x_s_stream(struct v4l2_subdev *sd, int enable)
> > +{
> > +	struct ov1063x_priv *priv = to_ov1063x(sd);
> > +	int ret = 0;
> > +
> > +	if (!enable) {
> > +		ov1063x_write(priv, OV1063X_STREAM_MODE, 0, &ret);
> > +		ov1063x_write(priv, OV1063X_SC_CMMN_CLKRST2,
> > +			      OV1063X_SC_CMMN_CLKRST2_SCLK, &ret);
> > +
> > +		pm_runtime_mark_last_busy(priv->dev);
> > +		pm_runtime_put_autosuspend(priv->dev);
> > +
> > +		mutex_lock(priv->hdl.lock);
> > +		priv->streaming = false;
> > +		mutex_unlock(priv->hdl.lock);
> > +
> > +		return ret;
> > +	}
> > +
> > +	mutex_lock(priv->hdl.lock);
> > +
> > +	/* Streaming needs to be true for ov1063x_s_ctrl() to proceed. */
> > +	priv->streaming = true;
> > +
> > +	ret = pm_runtime_get_sync(priv->dev);
> > +	if (ret < 0)
> > +		goto done;
> > +
> > +	ret = ov1063x_configure(priv);
> > +	if (ret < 0)
> > +		goto done;
> > +
> > +	ret = __v4l2_ctrl_handler_setup(&priv->hdl);
> > +	if (ret < 0)
> > +		goto done;
> > +
> > +	ret = 0;
> > +	ov1063x_write(priv, OV1063X_STREAM_MODE, OV1063X_STREAM_MODE_ON, &ret);
> > +	ov1063x_write(priv, OV1063X_SC_CMMN_CLKRST2,
> > +		      OV1063X_SC_CMMN_CLKRST2_PCLK_DVP |
> > +		      OV1063X_SC_CMMN_CLKRST2_SCLK, &ret);
> > +
> > +done:
> > +	if (ret < 0) {
> > +		/*
> > +		 * In case of error, turn the power off synchronously as the
> > +		 * device likely has no other chance to recover.
> > +		 */
> > +		pm_runtime_put_sync(priv->dev);
> > +		priv->streaming = false;
> > +	}
> > +
> > +	mutex_unlock(priv->hdl.lock);
> > +
> > +	return ret;
> > +}
> > +
> > +static struct v4l2_mbus_framefmt *
> > +__ov1063x_get_pad_format(struct ov1063x_priv *priv,
> > +			 struct v4l2_subdev_pad_config *cfg,
> > +			 unsigned int pad, u32 which)
> > +{
> > +	switch (which) {
> > +	case V4L2_SUBDEV_FORMAT_TRY:
> > +		return v4l2_subdev_get_try_format(&priv->subdev, cfg, pad);
> > +	case V4L2_SUBDEV_FORMAT_ACTIVE:
> > +		return &priv->format;
> > +	default:
> > +		return NULL;
> > +	}
> > +}
> > +
> > +static int ov1063x_init_cfg(struct v4l2_subdev *sd,
> > +			    struct v4l2_subdev_pad_config *cfg)
> > +{
> > +	u32 which = cfg ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
> > +	struct ov1063x_priv *priv = to_ov1063x(sd);
> > +	struct v4l2_mbus_framefmt *format;
> > +
> > +	format = __ov1063x_get_pad_format(priv, cfg, 0, which);
> > +	format->code = ov1063x_mbus_formats[0];
> > +	format->width = ov1063x_framesizes[0].width;
> > +	format->height = ov1063x_framesizes[0].height;
> > +	format->field = V4L2_FIELD_NONE;
> > +	format->colorspace = V4L2_COLORSPACE_SMPTE170M;
> > +
> > +	if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> > +		/*
> > +		 * This assumes that ov1063x_mbus_formats[0] doesn't
> > +		 * sub-sample.
> > +		 */
> > +		priv->analog_crop.width = OV1063X_SENSOR_WIDTH;
> > +		priv->analog_crop.height = format->height;
> > +		priv->analog_crop.left = ((OV1063X_SENSOR_WIDTH -
> > +					   priv->analog_crop.width) / 2) & ~1;
> > +		priv->analog_crop.top = ((OV1063X_SENSOR_HEIGHT -
> > +					  priv->analog_crop.height) / 2) & ~1;
> > +
> > +		priv->digital_crop.width = format->width;
> > +		priv->digital_crop.height = format->height;
> > +		priv->digital_crop.left = ((priv->analog_crop.width -
> > +					    priv->digital_crop.width) / 2) & ~1;
> > +		priv->digital_crop.top = 0;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_enum_mbus_code(struct v4l2_subdev *sd,
> > +				  struct v4l2_subdev_pad_config *cfg,
> > +				  struct v4l2_subdev_mbus_code_enum *code)
> > +{
> > +	if (code->index >= ARRAY_SIZE(ov1063x_mbus_formats))
> > +		return -EINVAL;
> > +
> > +	code->code = ov1063x_mbus_formats[code->index];
> > +
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_enum_frame_sizes(struct v4l2_subdev *sd,
> > +				    struct v4l2_subdev_pad_config *cfg,
> > +				    struct v4l2_subdev_frame_size_enum *fse)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(ov1063x_mbus_formats); ++i) {
> > +		if (ov1063x_mbus_formats[i] == fse->code)
> > +			break;
> > +	}
> > +
> > +	if (i == ARRAY_SIZE(ov1063x_mbus_formats))
> > +		return -EINVAL;
> > +
> > +	if (fse->index >= ARRAY_SIZE(ov1063x_framesizes))
> > +		return -EINVAL;
> > +
> > +	fse->min_width  = ov1063x_framesizes[fse->index].width;
> > +	fse->max_width  = fse->min_width;
> > +	fse->max_height = ov1063x_framesizes[fse->index].height;
> > +	fse->min_height = fse->max_height;
> > +
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_get_fmt(struct v4l2_subdev *sd,
> > +			   struct v4l2_subdev_pad_config *cfg,
> > +			   struct v4l2_subdev_format *fmt)
> > +{
> > +	struct ov1063x_priv *priv = to_ov1063x(sd);
> > +
> > +	fmt->format = *__ov1063x_get_pad_format(priv, cfg, fmt->pad,
> > +						fmt->which);
> > +
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_set_fmt(struct v4l2_subdev *sd,
> > +			   struct v4l2_subdev_pad_config *cfg,
> > +			   struct v4l2_subdev_format *fmt)
> > +{
> > +	struct ov1063x_priv *priv = to_ov1063x(sd);
> > +	struct v4l2_mbus_framefmt *format;
> > +	const struct v4l2_area *fsize;
> > +	unsigned int i;
> > +	u32 code;
> > +	int ret = 0;
> > +
> > +	/*
> > +	 * Validate the media bus code, defaulting to the first one if the
> > +	 * requested code isn't supported.
> > +	 */
> > +	for (i = 0; i < ARRAY_SIZE(ov1063x_mbus_formats); ++i) {
> > +		if (ov1063x_mbus_formats[i] == fmt->format.code) {
> > +			code = fmt->format.code;
> > +			break;
> > +		}
> > +	}
> > +
> > +	if (i == ARRAY_SIZE(ov1063x_mbus_formats))
> > +		code = ov1063x_mbus_formats[0];
> 
> You could do this assignment unconditionally in variable initialisation.

That's true. Do you mind it being separate though ? I like that it's
kept close to the for loop, to group all the related code together.

> > +
> > +	/* Find the nearest supported frame size. */
> > +	fsize = v4l2_find_nearest_size(ov1063x_framesizes,
> > +				       ARRAY_SIZE(ov1063x_framesizes),
> > +				       width, height, fmt->format.width,
> > +				       fmt->format.height);
> > +
> > +	/* Update the stored format and return it. */
> > +	format = __ov1063x_get_pad_format(priv, cfg, fmt->pad, fmt->which);
> > +
> > +	mutex_lock(priv->hdl.lock);
> > +
> > +	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->streaming) {
> > +		ret = -EBUSY;
> > +		goto done;
> > +	}
> > +
> > +	format->code = code;
> > +	format->width = fsize->width;
> > +	format->height = fsize->height;
> > +
> > +	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> > +		unsigned int hsub;
> > +		unsigned int vsub;
> > +
> > +		/*
> > +		 * Enable horizontal or vertical sub-sampling automatically when
> > +		 * the width or height are smaller than half the maximum
> > +		 * resolution.
> > +		 */
> > +		hsub = format->width <= 640 ? 2 : 1;
> > +		vsub = format->height <= 400 ? 2 : 1;
> > +
> > +		/*
> > +		 * The analog horizontal crop is restricted to the full sensor
> > +		 * width (1312 pixels), 768 or 656 pixels. Additional cropping
> > +		 * will be applied in the digital domain.
> > +		 */
> > +		priv->analog_crop.width = format->width * hsub;
> > +		priv->analog_crop.height = format->height * vsub;
> > +
> > +		if (priv->analog_crop.width > 768)
> > +			priv->analog_crop.width = OV1063X_SENSOR_WIDTH;
> > +		else if (priv->analog_crop.width > 656)
> > +			priv->analog_crop.width = 768;
> > +		else
> > +			priv->analog_crop.width = 656;
> > +
> > +		/*
> > +		 * The digital crop is applied at the ISP input, before
> > +		 * horizontal sub-sampling but after vertical sub-sampling as
> > +		 * the latter is applied in the pixel array.
> > +		 */
> > +		priv->digital_crop.width = format->width * hsub;
> > +		priv->digital_crop.height = format->height;
> > +
> > +		/*
> > +		 * Center the crop rectangles, rounding coordinates to a
> > +		 * multiple of 2 to avoid changing the Bayer pattern.
> > +		 */
> > +		priv->analog_crop.left = ((OV1063X_SENSOR_WIDTH -
> > +					   priv->analog_crop.width) / 2) & ~1;
> > +		priv->analog_crop.top = ((OV1063X_SENSOR_HEIGHT -
> > +					  priv->analog_crop.height) / 2) & ~1;
> > +		priv->digital_crop.left = ((priv->analog_crop.width -
> > +					    priv->digital_crop.width) / 2) & ~1;
> > +		priv->analog_crop.top = 0;
> > +	}
> > +
> > +	fmt->format = *format;
> > +
> > +done:
> > +	mutex_unlock(priv->hdl.lock);
> > +
> > +	return ret;
> > +}
> > +
> > +static const struct v4l2_subdev_core_ops ov1063x_subdev_core_ops = {
> > +	.log_status		= v4l2_ctrl_subdev_log_status,
> > +	.subscribe_event	= v4l2_ctrl_subdev_subscribe_event,
> > +	.unsubscribe_event	= v4l2_event_subdev_unsubscribe,
> > +};
> > +
> > +static const struct v4l2_subdev_video_ops ov1063x_subdev_video_ops = {
> > +	.s_stream	= ov1063x_s_stream,
> > +};
> > +
> > +static const struct v4l2_subdev_pad_ops ov1063x_subdev_pad_ops = {
> > +	.init_cfg		= ov1063x_init_cfg,
> > +	.enum_mbus_code		= ov1063x_enum_mbus_code,
> > +	.enum_frame_size	= ov1063x_enum_frame_sizes,
> > +	.get_fmt		= ov1063x_get_fmt,
> > +	.set_fmt		= ov1063x_set_fmt,
> > +};
> > +
> > +static const struct v4l2_subdev_ops ov1063x_subdev_ops = {
> > +	.core	= &ov1063x_subdev_core_ops,
> > +	.video	= &ov1063x_subdev_video_ops,
> > +	.pad	= &ov1063x_subdev_pad_ops,
> > +};
> > +
> > +/* -----------------------------------------------------------------------------
> > + * Power Management
> > + */
> > +
> > +static int ov1063x_power_on_init(struct ov1063x_priv *priv)
> > +{
> > +	struct i2c_client *client = to_i2c_client(priv->dev);
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	ret = ov1063x_write(priv, OV1063X_SOFTWARE_RESET, 0x01, NULL);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ov1063x_isp_reset(priv, true);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	/*
> > +	 * Why the I2C address has to be written 23 times (or, actually, at
> > +	 * all) is unknown. This may not be required.
> > +	 */
> > +	for (i = 0; i < 23; ++i) {
> > +		ret = ov1063x_write(priv, OV1063X_SC_CMMN_SCCB_ID,
> > +				    OV1063X_SC_CMMN_SCCB_ID_ADDR(client->addr) |
> > +				    OV1063X_SC_CMMN_SCCB_ID_SEL, NULL);
> > +		if (ret < 0)
> > +			return ret;
> > +	}
> > +
> > +	ret = ov1063x_write_array(priv, ov1063x_regs_default,
> > +				  ARRAY_SIZE(ov1063x_regs_default));
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ov1063x_isp_reset(priv, false);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	usleep_range(500, 510);
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_power_on(struct ov1063x_priv *priv)
> > +{
> > +	int ret;
> > +
> > +	ret = clk_prepare_enable(priv->clk);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	if (priv->pwdn_gpio) {
> > +		gpiod_set_value_cansleep(priv->pwdn_gpio, 0);
> > +		usleep_range(1000, 1200);
> > +	}
> > +
> > +	if (priv->reset_gpio) {
> > +		gpiod_set_value_cansleep(priv->reset_gpio, 0);
> > +		usleep_range(250000, 260000);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void ov1063x_power_off(struct ov1063x_priv *priv)
> > +{
> > +	gpiod_set_value_cansleep(priv->pwdn_gpio, 1);
> > +	gpiod_set_value_cansleep(priv->reset_gpio, 1);
> > +
> > +	clk_disable_unprepare(priv->clk);
> > +}
> > +
> > +static int ov1063x_runtime_resume(struct device *dev)
> > +{
> > +	struct i2c_client *client = to_i2c_client(dev);
> > +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> > +	struct ov1063x_priv *priv = to_ov1063x(subdev);
> > +	int ret;
> > +
> > +	ret = ov1063x_power_on(priv);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ov1063x_power_on_init(priv);
> > +	if (ret < 0) {
> > +		ov1063x_power_off(priv);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int ov1063x_runtime_suspend(struct device *dev)
> > +{
> > +	struct i2c_client *client = to_i2c_client(dev);
> > +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> > +	struct ov1063x_priv *priv = to_ov1063x(subdev);
> > +
> > +	ov1063x_power_off(priv);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct dev_pm_ops ov1063x_pm_ops = {
> > +	SET_RUNTIME_PM_OPS(ov1063x_runtime_suspend, ov1063x_runtime_resume, NULL)
> > +};
> > +
> > +/* -----------------------------------------------------------------------------
> > + * I2C Driver, Probe & Remove
> > + */
> > +
> > +static int ov1063x_detect(struct ov1063x_priv *priv)
> > +{
> > +	u32 pid;
> > +	int ret;
> > +
> > +	/* Read and check the product ID. */
> > +	ret = ov1063x_read(priv, OV1063X_PID, &pid);
> > +	if (ret)
> > +		return ret;
> > +
> > +	switch (pid) {
> > +	case OV10633_VERSION_REG:
> > +		priv->model = SENSOR_OV10633;
> > +		priv->name = "ov10633";
> > +		break;
> > +	case OV10635_VERSION_REG:
> > +		priv->model = SENSOR_OV10635;
> > +		priv->name = "ov10635";
> > +		break;
> > +	default:
> > +		dev_err(priv->dev, "Unknown product ID %04x\n", pid);
> > +		return -ENODEV;
> > +	}
> > +
> > +	dev_dbg(priv->dev, "%s detected\n", priv->name);
> 
> You print the name of the sensor at the end of probe already.

Note that this is a debug message, which could be useful in case probe
fails after the call to ov1063x_detect(). Should I drop it ?

> > +
> > +	return 0;
> > +}
> > +
> > +static const struct regmap_config ov1063x_regmap_config = {
> > +	.reg_bits = 16,
> > +	.val_bits = 8,
> > +};
> > +
> > +static int ov1063x_probe(struct i2c_client *client)
> > +{
> > +	struct ov1063x_priv *priv;
> > +	struct v4l2_subdev *sd;
> > +	int ret;
> > +
> > +	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	priv->dev = &client->dev;
> > +
> > +	/* Acquire resources: regmap, GPIOs and clock. The GPIOs are optional. */
> > +	priv->regmap = devm_regmap_init_i2c(client, &ov1063x_regmap_config);
> > +	if (IS_ERR(priv->regmap))
> > +		return PTR_ERR(priv->regmap);
> > +
> > +	priv->pwdn_gpio = devm_gpiod_get_optional(priv->dev, "powerdown",
> > +						  GPIOD_OUT_HIGH);
> > +	if (IS_ERR(priv->pwdn_gpio))
> > +		return PTR_ERR(priv->pwdn_gpio);
> > +
> > +	priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset",
> > +						   GPIOD_OUT_HIGH);
> > +	if (IS_ERR(priv->reset_gpio))
> > +		return PTR_ERR(priv->reset_gpio);
> > +	priv->clk = devm_clk_get(priv->dev, "xvclk");
> > +	if (IS_ERR(priv->clk)) {
> > +		ret = PTR_ERR(priv->clk);
> > +		dev_err(priv->dev, "Failed to get xvclk clock: %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	priv->clk_rate = clk_get_rate(priv->clk);
> > +	dev_dbg(priv->dev, "xvclk rate: %lu Hz\n", priv->clk_rate);
> > +
> > +	if (priv->clk_rate < 6000000 || priv->clk_rate > 27000000)
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * Enable power and detect the device.
> > +	 *
> > +	 * The driver supports runtime PM, but needs to work when runtime PM is
> > +	 * disabled in the kernel. To that end, power it on manually here.
> > +	 */
> > +	ret = ov1063x_power_on(priv);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ov1063x_detect(priv);
> > +	if (ret)
> > +		goto err_power;
> > +
> > +	/* Initialize the subdev and its controls. */
> > +	sd = &priv->subdev;
> > +	v4l2_i2c_subdev_init(sd, client, &ov1063x_subdev_ops);
> > +	v4l2_i2c_subdev_set_name(sd, client, priv->name, NULL);
> > +
> > +	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
> > +		     V4L2_SUBDEV_FL_HAS_EVENTS;
> > +
> > +	v4l2_ctrl_handler_init(&priv->hdl, 3);
> > +	v4l2_ctrl_new_std(&priv->hdl, &ov1063x_ctrl_ops,
> > +			  V4L2_CID_VFLIP, 0, 1, 1, 0);
> > +	v4l2_ctrl_new_std(&priv->hdl, &ov1063x_ctrl_ops,
> > +			  V4L2_CID_HFLIP, 0, 1, 1, 0);
> > +	v4l2_ctrl_new_std_menu_items(&priv->hdl, &ov1063x_ctrl_ops,
> > +				     V4L2_CID_TEST_PATTERN,
> > +				     ARRAY_SIZE(ov1063x_test_pattern_menu) - 1,
> > +				     0, 0, ov1063x_test_pattern_menu);
> > +
> > +	if (priv->hdl.error) {
> > +		ret = priv->hdl.error;
> > +		goto err_power;
> > +	}
> > +
> > +	sd->ctrl_handler = &priv->hdl;
> > +
> > +	/* Default framerate */
> > +	priv->fps_numerator = 30;
> > +	priv->fps_denominator = 1;
> > +	ov1063x_init_cfg(&priv->subdev, NULL);
> > +
> > +	/* Initialize the media entity. */
> > +	priv->pad.flags = MEDIA_PAD_FL_SOURCE;
> > +	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
> > +	ret = media_entity_pads_init(&sd->entity, 1, &priv->pad);
> > +	if (ret < 0)
> > +		goto err_ctrls;
> > +
> > +	/*
> > +	 * Enable runtime PM. As the device has been powered manually, mark it
> > +	 * as active, and increase the usage count without resuming the device.
> > +	 */
> > +	pm_runtime_set_active(priv->dev);
> > +	pm_runtime_get_noresume(priv->dev);
> > +	pm_runtime_enable(priv->dev);
> > +
> > +	/*
> > +	 * Enable autosuspend as it can help avoiding costly power transitions
> > +	 * when reconfiguring the sensor.
> > +	 */
> > +	pm_runtime_set_autosuspend_delay(priv->dev, 1000);
> > +	pm_runtime_use_autosuspend(priv->dev);
> > +
> > +	/*
> > +	 * At this point the device is powered on and active from a runtime PM
> > +	 * point of view, but hasn't gone through the full initialization
> > +	 * performed by the runtime resume operation. Suspend it synchronously
> > +	 * to turn the power off, ensuring proper initialization will take
> > +	 * place before the first usage.
> > +	 */
> > +	pm_runtime_put_sync(priv->dev);
> > +
> > +	/*
> > +	 * In case runtime PM is disabled in the kernel, the device remains
> > +	 * active and needs to be fully initialized at this point.
> > +	 */
> > +	if (!pm_runtime_status_suspended(priv->dev)) {
> > +		ret = ov1063x_power_on_init(priv);
> > +		if (ret < 0)
> > +			goto err_pm;
> > +	}
> > +
> > +	/* Finally, register the subdev. */
> > +	ret = v4l2_async_register_subdev(sd);
> > +	if (ret < 0)
> > +		goto err_pm;
> > +
> > +	dev_info(priv->dev, "%s probed\n", priv->name);
> > +
> > +	return 0;
> > +
> > +err_pm:
> > +	pm_runtime_disable(priv->dev);
> > +	media_entity_cleanup(&priv->subdev.entity);
> > +err_ctrls:
> > +	v4l2_ctrl_handler_free(&priv->hdl);
> > +err_power:
> > +	if (!pm_runtime_status_suspended(priv->dev))
> > +		ov1063x_power_off(priv);
> > +	return ret;
> > +}
> > +
> > +static int ov1063x_remove(struct i2c_client *client)
> > +{
> > +	struct ov1063x_priv *priv = i2c_get_clientdata(client);
> > +
> > +	v4l2_ctrl_handler_free(&priv->hdl);
> > +	v4l2_async_unregister_subdev(&priv->subdev);
> > +	media_entity_cleanup(&priv->subdev.entity);
> > +
> > +	/*
> > +	 * Disable runtime PM. In case runtime PM is disabled in the kernel,
> > +	 * make sure to turn power off manually.
> > +	 */
> > +	pm_runtime_disable(priv->dev);
> > +	if (!pm_runtime_status_suspended(priv->dev))
> > +		ov1063x_power_off(priv);
> > +	pm_runtime_set_suspended(priv->dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id ov1063x_dt_id[] = {
> > +	{ .compatible = "ovti,ov10635" },
> > +	{ .compatible = "ovti,ov10633" },
> > +	{ /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, ov1063x_dt_id);
> > +
> > +static struct i2c_driver ov1063x_i2c_driver = {
> > +	.driver = {
> > +		.name = "ov1063x",
> > +		.of_match_table = of_match_ptr(ov1063x_dt_id),
> > +		.pm = &ov1063x_pm_ops,
> > +	},
> > +	.probe_new = ov1063x_probe,
> > +	.remove = ov1063x_remove,
> > +};
> > +
> > +module_i2c_driver(ov1063x_i2c_driver);
> > +
> > +MODULE_DESCRIPTION("Camera Sensor Driver for OmniVision OV10633/OV10635");
> > +MODULE_AUTHOR("Texas Instruments Inc.");
> > +MODULE_LICENSE("GPL v2");
> 
> "GPL"

Ack.

> > diff --git a/drivers/media/i2c/ov1063x_regs.h b/drivers/media/i2c/ov1063x_regs.h
> > new file mode 100644
> > index 000000000000..43a0ca1d1367
> > --- /dev/null
> > +++ b/drivers/media/i2c/ov1063x_regs.h
> > @@ -0,0 +1,626 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * OmniVision OV1063x Camera Driver
> > + *
> > + * Copyright (C) 2018 Texas Instruments Incorporated -  http://www.ti.com/
> > + * Copyright (C) 2020 Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
> > + */
> > +
> > +struct ov1063x_reg {
> > +	u32	reg;
> > +	u32	val;
> > +};
> > +
> > +static const struct ov1063x_reg ov1063x_regs_default[] = {
> > +	/* Register configuration for full resolution : 1280x720 */
> > +	{ OV1063X_SC_CMMN_MISC_CTRL, 0x02 |
> > +				     OV1063X_SC_CMMN_MISC_CTRL_CEN_GLOBAL_O },
> > +	{ OV1063X_SC_CMMN_PAD, 0x02 },
> > +	{ OV1063X_HORIZ_COLORCORRECT, 0x0c },
> > +	{ OV1063X_REG_8BIT(0x6901), 0x01 },
> > +	{ OV1063X_SC_CMMN_SCLK2X_SEL, OV1063X_SC_CMMN_SCLK2X_SEL_DIV4 },
> > +	{ OV1063X_AEC_PK_MANUAL, OV1063X_AEC_PK_MANUAL_DELAY },
> > +	{ OV1063X_SC_CMMN_PWDN_CTRL2, 0x20 |
> > +				      OV1063X_SC_CMMN_PWDN_CTRL2_RST_DIG1 |
> > +				      OV1063X_SC_CMMN_PWDN_CTRL2_RST_DIG2 |
> > +				      OV1063X_SC_CMMN_PWDN_CTRL2_RST_ISP |
> > +				      OV1063X_SC_CMMN_PWDN_CTRL2_SEQUENCE },
> > +	{ OV1063X_SC_CMMN_CORE_CTRL1, 0x03 },
> > +	/*
> > +	 * For 15fps
> > +	 *
> > +	 * XVCLK: 9MHz
> > +	 * Pre divider: 1
> > +	 * Multiplier: 32
> > +	 * Divider: 8
> > +	 * SCLK: 36MHz
> > +	 */
> > +	{ OV1063X_SC_CMMN_PLL_CTRL0, OV1063X_SC_CMMN_PLL_SCLK_CP(0) |
> > +				     OV1063X_SC_CMMN_PLL_SCLK_MULTI(32) },
> > +	{ OV1063X_SC_CMMN_PLL_CTRL1, OV1063X_SC_CMMN_PLL_SCLK_PRE_DIV(0) |
> > +				     OV1063X_SC_CMMN_PLL_SCLK_CP2(0) |
> > +				     OV1063X_SC_CMMN_PLL_SCLK_DIV(3) },
> > +	{ OV1063X_SC_CMMN_PLL_CTRL2, OV1063X_SC_CMMN_PLL_SCLK_CP(0) |
> > +				     OV1063X_SC_CMMN_PLL_SCLK_MULTI(32) },
> > +	{ OV1063X_SC_CMMN_PLL_CTRL3, OV1063X_SC_CMMN_PLL_PCLK_BYPASS |
> > +				     OV1063X_SC_CMMN_PLL_SCLK_PRE_DIV(1) |
> > +				     OV1063X_SC_CMMN_PLL_SCLK_CP2(0) |
> > +				     OV1063X_SC_CMMN_PLL_SCLK_DIV(1) },
> > +	{ OV1063X_ANA_ADC1, 0x74 },
> > +	{ OV1063X_ANA_ADC2, 0x2b },
> > +	{ OV1063X_ANA_ANALOG3, 0x00 },
> > +	{ OV1063X_ANA_ANALOG2, 0x67 },
> > +	{ OV1063X_ANA_PWC4, 0xba },
> > +	{ OV1063X_ANA_ADC3, 0x2f },
> > +	{ OV1063X_ANA_ADC4, 0x00 },
> > +	{ OV1063X_ANA_PWC1, 0xa8 },
> > +	{ OV1063X_ANA_PWC2, 0x16 },
> > +	{ OV1063X_SENSOR_EQ_GOLOW, 0x10 },
> > +	{ OV1063X_SENSOR_BITSW_GO, 0x0001 },
> > +	{ OV1063X_FORMAT_CTRL00, OV1063X_FORMAT_UYVY },
> > +	{ OV1063X_SC_CMMN_PCLK_DIV_CTRL, 1 },
> > +	{ OV1063X_SC_CMMN_CORE_CTRL_3, OV1063X_SC_CMMN_CORE_CTRL_PCLK_SEC },
> > +	{ OV1063X_SC_CMMN_CLOCK_SEL, 0x0b },
> > +	{ OV1063X_SENSOR_RSTGOLOW, 0x0d },
> > +	{ OV1063X_SENSOR_HLDWIDTH, 0x20 },
> > +	{ OV1063X_SENSOR_TXWIDTH, 0x15 },
> > +	{ OV1063X_SENSOR_REG9, 0x28 },
> > +	{ OV1063X_SENSOR_REGD, 0x00 },
> > +	{ OV1063X_SENSOR_RSTYZ_GOLOW, 32 },
> > +	{ OV1063X_SENSOR_REG15, 0x04 },
> > +	{ OV1063X_TIMING_CTRL1D, OV1063X_TIMING_CTRL1D_WDR },
> > +	{ OV1063X_TIMING_CTRL1C, 0 },
> > +	{ OV1063X_REG_8BIT(0x3824), 0x10 },
> > +	{ OV1063X_TIMING_CTRL15, OV1063X_TIMING_CTRL15_BLACK_LINE_HREF |
> > +				 OV1063X_TIMING_CTRL15_BLACK_LINES(12) },
> > +	{ OV1063X_TIMING_X_END_ADDR, 1311 },
> > +	{ OV1063X_TIMING_X_START_ADDR, 0 },
> > +	{ OV1063X_TIMING_Y_END_ADDR, 769 },
> > +	{ OV1063X_TIMING_Y_START_ADDR, 46 },
> > +	{ OV1063X_TIMING_X_OUTPUT_SIZE, 1280 },
> > +	{ OV1063X_TIMING_Y_OUTPUT_SIZE, 720 },
> > +	{ OV1063X_TIMING_HTS, 1782 },
> > +	{ OV1063X_TIMING_VTS, 748 },
> > +	{ OV1063X_TIMING_ISP_X_WIN, 8 },
> > +	{ OV1063X_VSTART_OFFSET, 12 },
> > +	{ OV1063X_ANA_ARRAY1, 0x60 |
> > +			      OV1063X_ANA_ARRAY1_FULL |
> > +			      OV1063X_ANA_ARRAY1_DELAY(3) },
> > +	{ OV1063X_ISP_RW05, OV1063X_ISP_RW05_SUB_AVG },
> > +	{ OV1063X_AEC_CTRLD5, 8 * 1024 * 1024 },
> > +	{ OV1063X_AEC_CTRLD9, 8 * 1024 * 1024 },
> > +	{ OV1063X_AEC_CTRLE8, 127 },
> > +	{ OV1063X_AEC_CTRLEA, 127 },
> > +	{ OV1063X_GAIN_AWB_MAN_GAIN_B_LONG, 128 },
> > +	{ OV1063X_GAIN_AWB_MAN_GAIN_GB_LONG, 128 },
> > +	{ OV1063X_GAIN_AWB_MAN_GAIN_GR_LONG, 128 },
> > +	{ OV1063X_GAIN_AWB_MAN_GAIN_R_LONG, 128 },
> > +	{ OV1063X_GAIN_AWB_MAN_OFFSET_B_LONG, 0 },
> > +	{ OV1063X_GAIN_AWB_MAN_OFFSET_GB_LONG, 0 },
> > +	{ OV1063X_GAIN_AWB_MAN_OFFSET_GR_LONG, 0 },
> > +	{ OV1063X_GAIN_AWB_MAN_OFFSET_R_LONG, 0 },
> > +	{ OV1063X_GAIN_AWB_MAN_GAIN_B_SHORT, 128 },
> > +	{ OV1063X_GAIN_AWB_MAN_GAIN_GB_SHORT, 128 },
> > +	{ OV1063X_GAIN_AWB_MAN_GAIN_GR_SHORT, 128 },
> > +	{ OV1063X_GAIN_AWB_MAN_GAIN_R_SHORT, 128 },
> > +	{ OV1063X_GAIN_AWB_MAN_OFFSET_B_SHORT, 0 },
> > +	{ OV1063X_GAIN_AWB_MAN_OFFSET_GB_SHORT, 0 },
> > +	{ OV1063X_GAIN_AWB_MAN_OFFSET_GR_SHORT, 0 },
> > +	{ OV1063X_GAIN_AWB_MAN_OFFSET_R_SHORT, 0 },
> > +	{ OV1063X_AEC_CTRLD0, OV1063X_AEC_CTRLD0_R_MAN_EN(0) },
> > +	{ OV1063X_ISP_RW06, OV1063X_ISP_RW06_YUV_MODE_MAN(2) |
> > +			    OV1063X_ISP_RW06_YUV_MODE_MAN_EN },
> > +	{ OV1063X_AEC_CTRL07, 0 },
> > +	{ OV1063X_CIP_HFREQ_COEF_SHORT, 0x06 },
> > +	{ OV1063X_CIP_MAX_SHARPEN_LONG, 0x08 },
> > +	{ OV1063X_CIP_SHARPEN_ALPHA_LONG, 0x12 },
> > +	{ OV1063X_CIP_SHARPEN_ALPHA_SHORT, 0x12 },
> > +	{ OV1063X_CIP_UNSHARPEN_MASK_LONG(0), 0x06 },
> > +	{ OV1063X_CIP_UNSHARPEN_MASK_LONG(1), 0x20 },
> > +	{ OV1063X_CIP_UNSHARPEN_MASK_SHORT(0), 0x06 },
> > +	{ OV1063X_CIP_UNSHARPEN_MASK_SHORT(1), 0x20 },
> > +	{ OV1063X_CIP_MAX_SHARPEN_SHORT, 0x04 },
> > +	{ OV1063X_LLF_MAX_LOW_LEVEL, 255 },
> > +	{ OV1063X_AWB_M_X_LONG, 0x76 },
> > +	{ OV1063X_AWB_M_Y_LONG, 0x47 },
> > +	{ OV1063X_AWB_L_K_LONG, 0xef },
> > +	{ OV1063X_AWB_H_K_LONG, 0xc9 },
> > +	{ OV1063X_AWB_H_LMT_LONG, 0x49 },
> > +	{ OV1063X_AWB_L_LMT_LONG, 0x30 },
> > +	{ OV1063X_REG_8BIT(0x558f), 0x67 },
> > +	{ OV1063X_REG_8BIT(0x5590), 0x3f },
> > +	{ OV1063X_AWB_DATA_ULMT_LONG, 0xf0 },
> > +	{ OV1063X_AWB_DATA_LLMT_LONG, 0x10 },
> > +	{ OV1063X_AWB_M_X_SHORT, 0x6d },
> > +	{ OV1063X_AWB_M_Y_SHORT, 0x55 },
> > +	{ OV1063X_AWB_L_K_SHORT, 0xc3 },
> > +	{ OV1063X_AWB_H_K_SHORT, 0xb5 },
> > +	{ OV1063X_AWB_H_LMT_SHORT, 0x43 },
> > +	{ OV1063X_AWB_L_LMT_SHORT, 0x38 },
> > +	{ OV1063X_REG_8BIT(0x55a8), 0x5f },
> > +	{ OV1063X_REG_8BIT(0x55a9), 0x4b },
> > +	{ OV1063X_AWB_DATA_ULMT_SHORT, 0xf0 },
> > +	{ OV1063X_AWB_DATA_LLMT_SHORT, 0x10 },
> > +	{ OV1063X_AWB_CT_CTRL1, OV1063X_AWB_CT_CTRL1_GAIN_STEP_NORMAL(1) |
> > +				OV1063X_AWB_CT_CTRL1_GAIN_STEP_FAST(1) |
> > +				OV1063X_AWB_CT_CTRL1_SCALE_LONG_2X |
> > +				0x02 },
> > +	{ OV1063X_REG_8BIT(0x5300), 0x01 },
> > +	{ OV1063X_REG_8BIT(0x5301), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5302), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5303), 0x0e },
> > +	{ OV1063X_REG_8BIT(0x5304), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5305), 0x0e },
> > +	{ OV1063X_REG_8BIT(0x5306), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5307), 0x36 },
> > +	{ OV1063X_REG_8BIT(0x5308), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5309), 0xd9 },
> > +	{ OV1063X_REG_8BIT(0x530a), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x530b), 0x0f },
> > +	{ OV1063X_REG_8BIT(0x530c), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x530d), 0x2c },
> > +	{ OV1063X_REG_8BIT(0x530e), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x530f), 0x59 },
> > +	{ OV1063X_REG_8BIT(0x5310), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5311), 0x7b },
> > +	{ OV1063X_REG_8BIT(0x5312), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5313), 0x22 },
> > +	{ OV1063X_REG_8BIT(0x5314), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5315), 0xd5 },
> > +	{ OV1063X_REG_8BIT(0x5316), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5317), 0x13 },
> > +	{ OV1063X_REG_8BIT(0x5318), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5319), 0x18 },
> > +	{ OV1063X_REG_8BIT(0x531a), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x531b), 0x26 },
> > +	{ OV1063X_REG_8BIT(0x531c), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x531d), 0xdc },
> > +	{ OV1063X_REG_8BIT(0x531e), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x531f), 0x02 },
> > +	{ OV1063X_REG_8BIT(0x5320), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5321), 0x24 },
> > +	{ OV1063X_REG_8BIT(0x5322), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5323), 0x56 },
> > +	{ OV1063X_REG_8BIT(0x5324), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5325), 0x85 },
> > +	{ OV1063X_REG_8BIT(0x5326), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5327), 0x20 },
> > +	{ OV1063X_AEC_WIN_LEFT_LONG, 320 },
> > +	{ OV1063X_AEC_WIN_LEFT_SHORT, 320 },
> > +	{ OV1063X_AEC_WIN_TOP_LONG, 250 },
> > +	{ OV1063X_AEC_WIN_TOP_SHORT, 250 },
> > +	{ OV1063X_AEC_WIN_WIDTH_LONG, 640 },
> > +	{ OV1063X_AEC_WIN_WIDTH_SHORT, 640 },
> > +	{ OV1063X_AEC_WIN_HEIGHT_LONG, 300 },
> > +	{ OV1063X_AEC_WIN_HEIGHT_SHORT, 300 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(0), 1 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(1), 1 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(2), 1 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(3), 1 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(4), 3 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(5), 3 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(6), 3 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(7), 5 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(8), 9 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(9), 5 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(10), 5 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(11), 5 },
> > +	{ OV1063X_AEC_WEIGHT_SHORT(12), 5 },
> > +	{ OV1063X_AEC_FINAL_SATURATE_THRESH, 128 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_LONG(0), 1 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_LONG(1), 3 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_LONG(2), 6 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_LONG(3), 10 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_LONG(4), 14 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_LONG(5), 18 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_LONG(6), 22 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_LONG(0), 2 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_LONG(1), 4 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_LONG(2), 8 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_LONG(3), 12 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_LONG(4), 18 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_LONG(5), 24 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_LONG(6), 30 },
> > +	{ OV1063X_DNS_GBGR_EXTRA_SHORT, 4 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_SHORT(0), 1 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_SHORT(1), 3 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_SHORT(2), 6 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_SHORT(3), 10 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_SHORT(4), 14 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_SHORT(5), 18 },
> > +	{ OV1063X_DNS_NOISE_Y_LIST_SHORT(6), 22 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_SHORT(0), 3 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_SHORT(1), 4 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_SHORT(2), 8 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_SHORT(3), 12 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_SHORT(4), 18 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_SHORT(5), 24 },
> > +	{ OV1063X_DNS_NOISE_UV_LIST_SHORT(6), 30 },
> > +	{ OV1063X_VFIFO_LLEN_FIRS1_SEL, 0x00 }, /* 8-bit YUV mode */
> > +	{ OV1063X_VFIFO_LINE_LENGTH_MAN, 1905 },
> > +	{ OV1063X_VFIFO_HSYNC_START_POSITION, 624 },
> > +	{ OV1063X_VFIFO_HSYNC_CTRL, OV1063X_VFIFO_HSYNC_CTRL_HEADER_WIDTH(0) |
> > +				    OV1063X_VFIFO_HSYNC_CTRL_TRAILER_WIDTH(0) },
> > +	{ OV1063X_ROI_CTRL0, OV1063X_ROI_CTRL0_EN_3 |
> > +			     OV1063X_ROI_CTRL0_EN_2 |
> > +			     OV1063X_ROI_CTRL0_EN_1 },
> > +	{ OV1063X_DVP_MOD_SEL, OV1063X_DVP_MOD_SEL_CCIR_F },
> > +	{ OV1063X_DVP_VSYNC_WIDTH, 1 },
> > +	{ OV1063X_DVP_HSYVSY_NEG_WIDTH, 0 },
> > +	{ OV1063X_DVP_VSYNC_MODE, OV1063X_DVP_VSYNC_MODE_VSYNCOUT_SEL(0) },
> > +	/*
> > +	 * Non-overlapping HSYNC-VSYNC.
> > +	 * Therefore do not set the VSYNC delay registers.
> > +	 */
> > +	{ OV1063X_DVP_EOF_VSYNC_DELAY, 0 },
> > +	{ OV1063X_LINE_NUM, 8 },
> > +	{ OV1063X_BLC_CTRL05, OV1063X_BLC_CTRL05_REMOVE_BLACK_LINE |
> > +			      OV1063X_BLC_CTRL05_ONE_MAN_OFFSET_MODE },
> > +	{ OV1063X_START_LINE, 4 },
> > +	{ OV1063X_BLC_AVG_CTRL1, 0x20 },
> > +	{ OV1063X_BLC_AVG_CTRL2, 0x22 },
> > +	{ OV1063X_BLC_OFFSET_TOP_LIMIT, 1948 },
> > +	{ OV1063X_BLC_CTRL5A, 0x00 },
> > +	{ OV1063X_FC_R2, 2 },
> > +	{ OV1063X_SC_CMMN_CORE_CTRL_2, OV1063X_SC_CMMN_CORE_CTRL_CLK_SWITCH },
> > +	{ OV1063X_STREAM_MODE, OV1063X_STREAM_MODE_ON },
> > +	{ OV1063X_STREAM_MODE, OV1063X_STREAM_MODE_ON },
> > +	{ OV1063X_REG_8BIT(0x6f0e), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x6f0f), 0x00 },
> > +	{ OV1063X_VFIFO_EMBD_LINE_CTRL, OV1063X_VFIFO_EMBD_LINE_CTRL_SOF_CLR_RAM },
> > +	{ OV1063X_VFIFO_EMBD_LINE_NUM, 1 },
> > +	{ OV1063X_REG_8BIT(0x4610), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x4611), 0x01 },
> > +	{ OV1063X_REG_8BIT(0x4612), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x4613), 0x01 },
> > +	{ OV1063X_VFIFO_LLEN_FIRS1_SEL, 0x00 },
> > +	{ OV1063X_VFIFO_READ_START, 8 },
> > +	{ OV1063X_EMB_SIZE_MANU_EN, 0 },
> > +	{ OV1063X_EMB_SIZE_MANU, 1536 },
> > +	{ OV1063X_GAIN_AWB_CTRL32, 0 },
> > +	{ OV1063X_REG_8BIT(0x3510), 0x00 },
> > +	{ OV1063X_AEC_PK_MAN_DONE, 0 },
> > +	{ OV1063X_EMB_LINE_EN, 0 },
> > +	{ OV1063X_REG_8BIT(0x6f0d), 0x00 },
> > +	{ OV1063X_ISP_RW00, OV1063X_ISP_RW00_COLOR_MATRIX_EN |
> > +			    OV1063X_ISP_RW00_COLOR_INTERP_EN |
> > +			    OV1063X_ISP_RW00_DENOISE_EN |
> > +			    OV1063X_ISP_RW00_WHITE_DPC_EN |
> > +			    OV1063X_ISP_RW00_BLACK_DPC_EN |
> > +			    OV1063X_ISP_RW00_AWB_STATS_EN |
> > +			    OV1063X_ISP_RW00_AWB_GAIN_EN |
> > +			    OV1063X_ISP_RW00_LSC_EN },
> > +	{ OV1063X_ISP_RW01, OV1063X_ISP_RW01_DATA_WEIGHT_SYNC_EN |
> > +			    OV1063X_ISP_RW01_DARK_LEVEL_FILTER_EN |
> > +			    OV1063X_ISP_RW01_BUFFER_CONTROL_EN |
> > +			    OV1063X_ISP_RW01_AEC_EN |
> > +			    OV1063X_ISP_RW01_TONE_MAPPING_EN |
> > +			    OV1063X_ISP_RW01_NORMALIZE_EN |
> > +			    OV1063X_ISP_RW01_LONG_SHORT_COMB_EN },
> > +	{ OV1063X_ISP_RW02, 0xf0 |
> > +			    OV1063X_ISP_RW02_DIGITAL_GAIN_EN |
> > +			    OV1063X_ISP_RW02_WINDOW_BORDER_CUT_EN |
> > +			    OV1063X_ISP_RW02_DITHERING_EN },
> > +	{ OV1063X_ISP_CTRL3D, 0 },
> > +	{ OV1063X_AEC_TARGET_NUM, OV1063X_AEC_TARGET_NUM_AA_MODE },
> > +	{ OV1063X_AEC_LS_SENS_RATIO, 1024 },
> > +	{ OV1063X_AEC_NONWDR_EN, 0 },
> > +	{ OV1063X_AEC_NONWDR_SWITCH, 0 },
> > +	{ OV1063X_AEC_FIXED_RATIO_EN, 0 },
> > +	{ OV1063X_AEC_GP_MODE_EN, 0 },
> > +	{ OV1063X_AEC_NIGHT_MODE_EN, 0 },
> > +	{ OV1063X_AEC_NIGHT_MODE_CTRL, 0 },
> > +	{ OV1063X_AEC_NONLINEAR_GAIN_EN, 0 },
> > +	{ OV1063X_AEC_MANU_GAMMA_EN, 0 },
> > +	{ OV1063X_AEC_HOLD_BAND_EN, 0 },
> > +	{ OV1063X_AEC_BAND_FILTER_FLAG, OV1063X_AEC_BAND_FILTER_FLAG_0HZ },
> > +	{ OV1063X_AEC_BAND_FILTER_EN, 0 },
> > +	{ OV1063X_AEC_BAND_FILTER_SHORT, 0 },
> > +	{ OV1063X_AEC_LESS_1BAND_EN, 1 },
> > +	{ OV1063X_AEC_LESS_1BAND_SHORT, 1 },
> > +	{ OV1063X_AEC_LOG_TARGET(0), 0x8800 },
> > +	{ OV1063X_AEC_LOG_TARGET(1), 0x8a00 },
> > +	{ OV1063X_AEC_LOG_TARGET(2), 0x8600 },
> > +	{ OV1063X_AEC_TARGET_LONG(0), 0x40 },
> > +	{ OV1063X_AEC_TARGET_LONG(1), 0x50 },
> > +	{ OV1063X_AEC_TARGET_LONG(2), 0x30 },
> > +	{ OV1063X_AEC_TARGET_SHORT(0), 0x28 },
> > +	{ OV1063X_AEC_TARGET_SHORT(1), 0x60 },
> > +	{ OV1063X_AEC_TARGET_SHORT(2), 0x40 },
> > +	{ OV1063X_AEC_MAX_SHORT_LE, 0x01380000 },
> > +	{ OV1063X_AEC_MAX_GAIN_LONG, 255 },
> > +	{ OV1063X_AEC_MAX_GAIN_SHORT, 64 },
> > +	{ OV1063X_AEC_MIN_GAIN_LONG, 24 },
> > +	{ OV1063X_AEC_MIN_GAIN_SHORT, 24 },
> > +	{ OV1063X_AEC_MAX_EXP_LONG, 11904 },
> > +	{ OV1063X_AEC_MAX_EXP_SHORT, 11904 },
> > +	{ OV1063X_AEC_MIN_EXP_LONG, 4 },
> > +	{ OV1063X_AEC_MIN_EXP_SHORT, 4 },
> > +	{ OV1063X_AEC_FIXED_RATIO, 0x07 },
> > +	{ OV1063X_AEC_GP_MODE_RATIO_B2A, 0x20 },
> > +	{ OV1063X_AEC_GP_MODE_RATIO_C2A, 0x08 },
> > +	{ OV1063X_AEC_MIN_GAMMA_LIST(0), 512 },
> > +	{ OV1063X_AEC_MIN_GAMMA_LIST(1), 512 },
> > +	{ OV1063X_AEC_MIN_GAMMA_LIST(2), 512 },
> > +	{ OV1063X_AEC_MAX_GAMMA_LIST(0), 308 },
> > +	{ OV1063X_AEC_MAX_GAMMA_LIST(1), 1024 },
> > +	{ OV1063X_AEC_MAX_GAMMA_LIST(2), 1536 },
> > +	{ OV1063X_AEC_DR_LIST(0), 16 },
> > +	{ OV1063X_AEC_DR_LIST(1), 64 },
> > +	{ OV1063X_AEC_DR_LIST(2), 128 },
> > +	{ OV1063X_AEC_BAND_VALUE_60HZ, 3328 },
> > +	{ OV1063X_AEC_BAND_VALUE_50HZ, 4032 },
> > +	{ OV1063X_REG_8BIT(0xc4b4), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc4b5), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc4b6), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc4b7), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc4b8), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc4b9), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc4ba), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc4bb), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc4be), 0x02 },
> > +	{ OV1063X_REG_8BIT(0xc4bf), 0x33 },
> > +	{ OV1063X_REG_8BIT(0xc4c8), 0x03 },
> > +	{ OV1063X_REG_8BIT(0xc4c9), 0xd0 },
> > +	{ OV1063X_REG_8BIT(0xc4ca), 0x0e },
> > +	{ OV1063X_REG_8BIT(0xc4cb), 0x00 },
> > +	{ OV1063X_AWB_SIMPLE_MIN_NUM, 3665 },
> > +	{ OV1063X_AWB_CT_MIN_NUM, 3665 },
> > +	{ OV1063X_REG_8BIT(0xc4d0), 0x04 },
> > +	{ OV1063X_REG_8BIT(0xc4d1), 0x80 },
> > +	{ OV1063X_REG_8BIT(0xc4e0), 0x04 },
> > +	{ OV1063X_REG_8BIT(0xc4e1), 0x02 },
> > +	{ OV1063X_REG_8BIT(0xc4e2), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc4e4), 0x10 },
> > +	{ OV1063X_REG_8BIT(0xc4e5), 0x20 },
> > +	{ OV1063X_REG_8BIT(0xc4e6), 0x30 },
> > +	{ OV1063X_REG_8BIT(0xc4e7), 0x40 },
> > +	{ OV1063X_REG_8BIT(0xc4e8), 0x50 },
> > +	{ OV1063X_REG_8BIT(0xc4e9), 0x60 },
> > +	{ OV1063X_REG_8BIT(0xc4ea), 0x70 },
> > +	{ OV1063X_REG_8BIT(0xc4eb), 0x80 },
> > +	{ OV1063X_REG_8BIT(0xc4ec), 0x90 },
> > +	{ OV1063X_REG_8BIT(0xc4ed), 0xa0 },
> > +	{ OV1063X_REG_8BIT(0xc4ee), 0xb0 },
> > +	{ OV1063X_REG_8BIT(0xc4ef), 0xc0 },
> > +	{ OV1063X_REG_8BIT(0xc4f0), 0xd0 },
> > +	{ OV1063X_REG_8BIT(0xc4f1), 0xe0 },
> > +	{ OV1063X_REG_8BIT(0xc4f2), 0xf0 },
> > +	{ OV1063X_REG_8BIT(0xc4f3), 0x80 },
> > +	{ OV1063X_REG_8BIT(0xc4f4), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc4f5), 0x20 },
> > +	{ OV1063X_REG_8BIT(0xc4f6), 0x02 },
> > +	{ OV1063X_REG_8BIT(0xc4f7), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc4f8), 0x04 },
> > +	{ OV1063X_REG_8BIT(0xc4f9), 0x0b },
> > +	{ OV1063X_REG_8BIT(0xc4fa), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc4fb), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc4fc), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc4fd), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc4fe), 0x04 },
> > +	{ OV1063X_REG_8BIT(0xc4ff), 0x02 },
> > +	{ OV1063X_REG_8BIT(0xc500), 0x68 },
> > +	{ OV1063X_REG_8BIT(0xc501), 0x74 },
> > +	{ OV1063X_REG_8BIT(0xc502), 0x70 },
> > +	{ OV1063X_REG_8BIT(0xc503), 0x80 },
> > +	{ OV1063X_REG_8BIT(0xc504), 0x05 },
> > +	{ OV1063X_REG_8BIT(0xc505), 0x80 },
> > +	{ OV1063X_REG_8BIT(0xc506), 0x03 },
> > +	{ OV1063X_REG_8BIT(0xc507), 0x80 },
> > +	{ OV1063X_REG_8BIT(0xc508), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc509), 0xc0 },
> > +	{ OV1063X_REG_8BIT(0xc50a), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc50b), 0xa0 },
> > +	{ OV1063X_REG_8BIT(0xc50c), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc50d), 0x2c },
> > +	{ OV1063X_REG_8BIT(0xc50e), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc50f), 0x0a },
> > +	{ OV1063X_REG_8BIT(0xc510), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc511), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc512), 0xe5 },
> > +	{ OV1063X_REG_8BIT(0xc513), 0x14 },
> > +	{ OV1063X_REG_8BIT(0xc514), 0x04 },
> > +	{ OV1063X_REG_8BIT(0xc515), 0x00 },
> > +	{ OV1063X_VTS_ADDR, 840 },
> > +	{ OV1063X_HTS_ADDR, 1904 },
> > +	{ OV1063X_REG_8BIT(0xc2e0), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc2e1), 0x51 },
> > +	{ OV1063X_REG_8BIT(0xc2e2), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc2e3), 0xd6 },
> > +	{ OV1063X_REG_8BIT(0xc2e4), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc2e5), 0x5e },
> > +	{ OV1063X_REG_8BIT(0xc2e9), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc2ea), 0x7a },
> > +	{ OV1063X_REG_8BIT(0xc2eb), 0x90 },
> > +	{ OV1063X_REG_8BIT(0xc2ed), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc2ee), 0x7a },
> > +	{ OV1063X_REG_8BIT(0xc2ef), 0x64 },
> > +	{ OV1063X_REG_8BIT(0xc308), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc309), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc30a), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc30c), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc30d), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc30e), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc30f), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc310), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc311), 0x60 },
> > +	{ OV1063X_REG_8BIT(0xc312), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc313), 0x08 },
> > +	{ OV1063X_REG_8BIT(0xc314), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc315), 0x7f },
> > +	{ OV1063X_REG_8BIT(0xc316), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc317), 0x0b },
> > +	{ OV1063X_REG_8BIT(0xc318), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc319), 0x0c },
> > +	{ OV1063X_REG_8BIT(0xc31a), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc31b), 0xe0 },
> > +	{ OV1063X_REG_8BIT(0xc31c), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc31d), 0x14 },
> > +	{ OV1063X_REG_8BIT(0xc31e), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc31f), 0xc5 },
> > +	{ OV1063X_REG_8BIT(0xc320), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc321), 0x4b },
> > +	{ OV1063X_REG_8BIT(0xc322), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc323), 0xf0 },
> > +	{ OV1063X_REG_8BIT(0xc324), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc325), 0xe8 },
> > +	{ OV1063X_REG_8BIT(0xc326), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc327), 0x46 },
> > +	{ OV1063X_REG_8BIT(0xc328), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc329), 0xd2 },
> > +	{ OV1063X_REG_8BIT(0xc32a), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc32b), 0xe4 },
> > +	{ OV1063X_REG_8BIT(0xc32c), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc32d), 0xbb },
> > +	{ OV1063X_REG_8BIT(0xc32e), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc32f), 0x61 },
> > +	{ OV1063X_REG_8BIT(0xc330), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc331), 0xf9 },
> > +	{ OV1063X_REG_8BIT(0xc332), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc333), 0xd9 },
> > +	{ OV1063X_REG_8BIT(0xc334), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc335), 0x2e },
> > +	{ OV1063X_REG_8BIT(0xc336), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc337), 0xb1 },
> > +	{ OV1063X_REG_8BIT(0xc338), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc339), 0x64 },
> > +	{ OV1063X_REG_8BIT(0xc33a), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc33b), 0xeb },
> > +	{ OV1063X_REG_8BIT(0xc33c), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc33d), 0xe8 },
> > +	{ OV1063X_REG_8BIT(0xc33e), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc33f), 0x48 },
> > +	{ OV1063X_REG_8BIT(0xc340), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc341), 0xd0 },
> > +	{ OV1063X_REG_8BIT(0xc342), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc343), 0xed },
> > +	{ OV1063X_REG_8BIT(0xc344), 0xff },
> > +	{ OV1063X_REG_8BIT(0xc345), 0xad },
> > +	{ OV1063X_REG_8BIT(0xc346), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc347), 0x66 },
> > +	{ OV1063X_REG_8BIT(0xc348), 0x01 },
> > +	{ OV1063X_REG_8BIT(0xc349), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x6700), 0x04 },
> > +	{ OV1063X_REG_8BIT(0x6701), 0x7b },
> > +	{ OV1063X_REG_8BIT(0x6702), 0xfd },
> > +	{ OV1063X_REG_8BIT(0x6703), 0xf9 },
> > +	{ OV1063X_REG_8BIT(0x6704), 0x3d },
> > +	{ OV1063X_REG_8BIT(0x6705), 0x71 },
> > +	{ OV1063X_TPM_CTRL0, 0x70 | OV1063X_TPM_CTRL0_CLK_DIV(1) },
> > +	{ OV1063X_REG_8BIT(0x6708), 0x05 },
> > +	{ OV1063X_REG_8BIT(0x3822), 0x50 },
> > +	{ OV1063X_PARI_ADDR_MIN, 0x6f00 },
> > +	{ OV1063X_PARI_ADDR_MAX, 0x6f00 },
> > +	{ OV1063X_GROUP_WRITER_COMMAND, OV1063X_GROUP_WRITER_COMMAND_EN },
> > +};
> > +
> > +static const struct ov1063x_reg ov1063x_regs_bt656[] = {
> > +	{ OV1063X_DVP_MOD_SEL, OV1063X_DVP_MOD_SEL_CCIR_656 },
> > +	{ OV1063X_FORMAT_YMAX, 1016 },
> > +	{ OV1063X_FORMAT_YMIN, 8 },
> > +	{ OV1063X_FORMAT_UMAX, 1016 },
> > +	{ OV1063X_FORMAT_UMIN, 8 },
> > +};
> > +
> > +static const struct ov1063x_reg ov1063x_regs_bt656_10bit[] = {
> > +	{ OV1063X_DVP_MOD_SEL, OV1063X_DVP_MOD_SEL_CCIR_656 },
> > +	{ OV1063X_FORMAT_YMAX, 1022 },
> > +	{ OV1063X_FORMAT_YMIN, 2 },
> > +	{ OV1063X_FORMAT_UMAX, 1022 },
> > +	{ OV1063X_FORMAT_UMIN, 2 },
> > +};
> > +
> > +static const struct ov1063x_reg ov1063x_regs_vert_no_sub[] = {
> > +	{ OV1063X_TIMING_CTRL1C, 0 },
> > +	{ OV1063X_VSTART_OFFSET, 12 },
> > +	{ OV1063X_START_LINE, 4 },
> > +	{ OV1063X_LINE_NUM, 8 },
> > +	{ OV1063X_BLC_AVG_CTRL1, 0x20 },
> > +	{ OV1063X_BLC_AVG_CTRL2, 0x22 },
> > +	{ OV1063X_REG_8BIT(0x6e47), 0x0c },
> > +	{ OV1063X_REG_8BIT(0x4610), 0x05 },
> > +	{ OV1063X_REG_8BIT(0x4613), 0x10 },
> > +};
> > +
> > +static const struct ov1063x_reg ov1063x_regs_vert_sub2[] = {
> > +	{ OV1063X_TIMING_CTRL1C, OV1063X_TIMING_CTRL1C_VSUB2 },
> > +	{ OV1063X_VSTART_OFFSET, 6 },
> > +	{ OV1063X_START_LINE, 2 },
> > +	{ OV1063X_LINE_NUM, 2 },
> > +	{ OV1063X_BLC_AVG_CTRL1, 0x10 },
> > +	{ OV1063X_BLC_AVG_CTRL2, 0x11 },
> > +	{ OV1063X_REG_8BIT(0x6e47), 0x06 },
> > +	{ OV1063X_REG_8BIT(0x4610), 0x03 },
> > +	{ OV1063X_REG_8BIT(0x4613), 0x0a },
> > +};
> > +
> > +/*
> > + * Datasheet highlight the following sequence to enable and disable
> > + * Test Pattern mode i.e. colobar
> > + */
> > +static const struct ov1063x_reg ov1063x_regs_colorbar_enable[] = {
> > +	{ OV1063X_GAIN_AWB_CTRL32, OV1063X_GAIN_AWB_CTRL32_MANUAL_EN },
> > +	{ OV1063X_AEC_CTRLD0, OV1063X_AEC_CTRLD0_R_MAN_EN(1) },
> > +	{ OV1063X_REG_8BIT(0x5300), 0x01 }, { OV1063X_REG_8BIT(0x5301), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5302), 0x00 }, { OV1063X_REG_8BIT(0x5303), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5304), 0x00 }, { OV1063X_REG_8BIT(0x5305), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5306), 0x00 }, { OV1063X_REG_8BIT(0x5307), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5308), 0x01 }, { OV1063X_REG_8BIT(0x5309), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x530a), 0x00 }, { OV1063X_REG_8BIT(0x530b), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x530c), 0x00 }, { OV1063X_REG_8BIT(0x530d), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x530e), 0x00 }, { OV1063X_REG_8BIT(0x530f), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5310), 0x01 }, { OV1063X_REG_8BIT(0x5311), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5312), 0x00 }, { OV1063X_REG_8BIT(0x5313), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5314), 0x01 }, { OV1063X_REG_8BIT(0x5315), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5316), 0x00 }, { OV1063X_REG_8BIT(0x5317), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5318), 0x00 }, { OV1063X_REG_8BIT(0x5319), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x531a), 0x00 }, { OV1063X_REG_8BIT(0x531b), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x531c), 0x01 }, { OV1063X_REG_8BIT(0x531d), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x531e), 0x00 }, { OV1063X_REG_8BIT(0x531f), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5320), 0x00 }, { OV1063X_REG_8BIT(0x5321), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5322), 0x00 }, { OV1063X_REG_8BIT(0x5323), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5324), 0x01 }, { OV1063X_REG_8BIT(0x5325), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5326), 0x00 }, { OV1063X_REG_8BIT(0x5327), 0x00 },
> > +	{ OV1063X_REG_8BIT(0xc2ea), 0x80 }, { OV1063X_REG_8BIT(0xc2eb), 0x80 },
> > +	{ OV1063X_ISP_RW00, OV1063X_ISP_RW00_COLOR_INTERP_EN |
> > +			    OV1063X_ISP_RW00_DENOISE_EN |
> > +			    OV1063X_ISP_RW00_WHITE_DPC_EN |
> > +			    OV1063X_ISP_RW00_BLACK_DPC_EN |
> > +			    OV1063X_ISP_RW00_LSC_EN },
> > +};
> > +
> > +static const struct ov1063x_reg ov1063x_regs_colorbar_disable[] = {
> > +	{ OV1063X_ISP_CTRL3D, 0 },
> > +	{ OV1063X_ISP_CTRL3E, 0 },
> > +	{ OV1063X_GAIN_AWB_CTRL32, 0 },
> > +	{ OV1063X_AEC_CTRLD0, OV1063X_AEC_CTRLD0_R_MAN_EN(0) },
> > +	{ OV1063X_REG_8BIT(0x5300), 0x01 }, { OV1063X_REG_8BIT(0x5301), 0x00 },
> > +	{ OV1063X_REG_8BIT(0x5302), 0x00 }, { OV1063X_REG_8BIT(0x5303), 0x0e },
> > +	{ OV1063X_REG_8BIT(0x5304), 0x00 }, { OV1063X_REG_8BIT(0x5305), 0x0e },
> > +	{ OV1063X_REG_8BIT(0x5306), 0x00 }, { OV1063X_REG_8BIT(0x5307), 0x36 },
> > +	{ OV1063X_REG_8BIT(0x5308), 0x00 }, { OV1063X_REG_8BIT(0x5309), 0xd9 },
> > +	{ OV1063X_REG_8BIT(0x530a), 0x00 }, { OV1063X_REG_8BIT(0x530b), 0x0f },
> > +	{ OV1063X_REG_8BIT(0x530c), 0x00 }, { OV1063X_REG_8BIT(0x530d), 0x2c },
> > +	{ OV1063X_REG_8BIT(0x530e), 0x00 }, { OV1063X_REG_8BIT(0x530f), 0x59 },
> > +	{ OV1063X_REG_8BIT(0x5310), 0x00 }, { OV1063X_REG_8BIT(0x5311), 0x7b },
> > +	{ OV1063X_REG_8BIT(0x5312), 0x00 }, { OV1063X_REG_8BIT(0x5313), 0x22 },
> > +	{ OV1063X_REG_8BIT(0x5314), 0x00 }, { OV1063X_REG_8BIT(0x5315), 0xd5 },
> > +	{ OV1063X_REG_8BIT(0x5316), 0x00 }, { OV1063X_REG_8BIT(0x5317), 0x13 },
> > +	{ OV1063X_REG_8BIT(0x5318), 0x00 }, { OV1063X_REG_8BIT(0x5319), 0x18 },
> > +	{ OV1063X_REG_8BIT(0x531a), 0x00 }, { OV1063X_REG_8BIT(0x531b), 0x26 },
> > +	{ OV1063X_REG_8BIT(0x531c), 0x00 }, { OV1063X_REG_8BIT(0x531d), 0xdc },
> > +	{ OV1063X_REG_8BIT(0x531e), 0x00 }, { OV1063X_REG_8BIT(0x531f), 0x02 },
> > +	{ OV1063X_REG_8BIT(0x5320), 0x00 }, { OV1063X_REG_8BIT(0x5321), 0x24 },
> > +	{ OV1063X_REG_8BIT(0x5322), 0x00 }, { OV1063X_REG_8BIT(0x5323), 0x56 },
> > +	{ OV1063X_REG_8BIT(0x5324), 0x00 }, { OV1063X_REG_8BIT(0x5325), 0x85 },
> > +	{ OV1063X_REG_8BIT(0x5326), 0x00 }, { OV1063X_REG_8BIT(0x5327), 0x20 },
> > +	{ OV1063X_REG_8BIT(0xc2ea), 0x7a }, { OV1063X_REG_8BIT(0xc2eb), 0x90 },
> > +	{ OV1063X_ISP_RW00, OV1063X_ISP_RW00_COLOR_MATRIX_EN |
> > +			    OV1063X_ISP_RW00_COLOR_INTERP_EN |
> > +			    OV1063X_ISP_RW00_DENOISE_EN |
> > +			    OV1063X_ISP_RW00_WHITE_DPC_EN |
> > +			    OV1063X_ISP_RW00_BLACK_DPC_EN |
> > +			    OV1063X_ISP_RW00_AWB_STATS_EN |
> > +			    OV1063X_ISP_RW00_AWB_GAIN_EN |
> > +			    OV1063X_ISP_RW00_LSC_EN },
> > +};

-- 
Regards,

Laurent Pinchart




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux