diff mbox series

[v2,2/2] media: i2c: Add OV1063x sensor driver

Message ID 20211206230717.5836-3-laurent.pinchart@ideasonboard.com
State New
Headers show
Series media: Driver for OV1063x camera sensor | expand

Commit Message

Laurent Pinchart Dec. 6, 2021, 11:07 p.m. UTC
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.

[1] http://www.spinics.net/lists/linux-media/msg64347.html

Signed-off-by: Nikhil Devshatwar <nikhil.nd@ti.com>
Signed-off-by: Benoit Parrot <bparrot@ti.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Drop unneeded debug message
- Fix MODULE_LICENSE
- Fix priv pointer retrieval in remove()
- Add more registers macros
- Fix PLL calculation
- Update to subdev state API
- Fix test pattern when starting streaming
---
 MAINTAINERS                      |    2 +
 drivers/media/i2c/Kconfig        |   12 +
 drivers/media/i2c/Makefile       |    1 +
 drivers/media/i2c/ov1063x.c      | 1716 ++++++++++++++++++++++++++++++
 drivers/media/i2c/ov1063x_regs.h |  627 +++++++++++
 5 files changed, 2358 insertions(+)
 create mode 100644 drivers/media/i2c/ov1063x.c
 create mode 100644 drivers/media/i2c/ov1063x_regs.h

Comments

Neil Armstrong March 23, 2022, 4:12 p.m. UTC | #1
On 23/03/2022 15:01, Neil Armstrong wrote:
> Hi Laurent,
> 
> 
> On 07/12/2021 00:07, 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.
>>
>> [1] http://www.spinics.net/lists/linux-media/msg64347.html
>>
>> Signed-off-by: Nikhil Devshatwar <nikhil.nd@ti.com>
>> Signed-off-by: Benoit Parrot <bparrot@ti.com>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> ---
>> Changes since v1:
>>
>> - Drop unneeded debug message
>> - Fix MODULE_LICENSE
>> - Fix priv pointer retrieval in remove()
>> - Add more registers macros
>> - Fix PLL calculation
>> - Update to subdev state API
>> - Fix test pattern when starting streaming
>> ---
>>   MAINTAINERS                      |    2 +
>>   drivers/media/i2c/Kconfig        |   12 +
>>   drivers/media/i2c/Makefile       |    1 +
>>   drivers/media/i2c/ov1063x.c      | 1716 ++++++++++++++++++++++++++++++
>>   drivers/media/i2c/ov1063x_regs.h |  627 +++++++++++
>>   5 files changed, 2358 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 9c7748b160dd..eb24dc54e046 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -14044,6 +14044,8 @@ L:    linux-media@vger.kernel.org
>>   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@linux.intel.com>
>> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
>> index d6a5d4ca439a..7a0d7bd17a3c 100644
>> --- a/drivers/media/i2c/Kconfig
>> +++ b/drivers/media/i2c/Kconfig
>> @@ -1192,6 +1192,18 @@ config VIDEO_OV9734
>>         To compile this driver as a module, choose M here: the
>>         module's name is ov9734.
>> +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 4d4fe08d7a6a..a16299de56c0 100644
>> --- a/drivers/media/i2c/Makefile
>> +++ b/drivers/media/i2c/Makefile
>> @@ -88,6 +88,7 @@ obj-$(CONFIG_VIDEO_OV9282) += ov9282.o
>>   obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
>>   obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
>>   obj-$(CONFIG_VIDEO_OV9734) += ov9734.o
>> +obj-$(CONFIG_VIDEO_OV10633) += ov1063x.o
>>   obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
>>   obj-$(CONFIG_VIDEO_OV13B10) += ov13b10.o
>>   obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
>> diff --git a/drivers/media/i2c/ov1063x.c b/drivers/media/i2c/ov1063x.c
>> new file mode 100644
>> index 000000000000..fb4ef5ea9a9f
>> --- /dev/null
>> +++ b/drivers/media/i2c/ov1063x.c
>> @@ -0,0 +1,1716 @@
>> +// 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@ideasonboard.com>
>> + */
>> +
>> +#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_CLOCK_SEL_SCLK2X    BIT(0)
>> +#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_TIMING_CTRL24            OV1063X_REG_8BIT(0x3824)
>> +#define OV1063X_VSTART_OFFSET            OV1063X_REG_16BIT(0x381e)
>> +#define OV1063X_TIMING_TC_CS_RST        OV1063X_REG_16BIT(0x3832)
>> +#define OV1063X_TIMING_TC_R_RST            OV1063X_REG_16BIT(0x3834)
>> +
>> +#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_EMB_START_PCNT            OV1063X_REG_16BIT(0x4610)
>> +#define OV1063X_EMB_START_LCNT            OV1063X_REG_16BIT(0x4612)
>> +#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_OTP_MANUAL_OFFSET_EN    BIT(7)
>> +#define OV1063X_ISP_RW02_OTP_EN            BIT(6)
>> +#define OV1063X_ISP_RW02_INTER_FRAME_CALC    BIT(5)
>> +#define OV1063X_ISP_RW02_CT_AWB_EN        BIT(4)
>> +#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_SLOPE(n)            OV1063X_REG_8BIT(0x6700 + (n))
>> +#define OV1063X_TPM_OFFSET(n)            OV1063X_REG_8BIT(0x6702 + (n))
>> +#define OV1063X_TPM_CTRL6            OV1063X_REG_8BIT(0x6706)
>> +#define OV1063X_TPM_CTRL6_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,
>> +};
>> +
>> +enum ov1063x_streaming_state {
>> +    OV1063X_STREAM_OFF = 0,
>> +    OV1063X_STREAM_STARTING,
>> +    OV1063X_STREAM_ON,
>> +};
>> +
>> +#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.
>> +     */
>> +    enum ov1063x_streaming_state    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,
>> +    }, {
> 
> I have an issue when 600x400 is requested on the ov10635 from the TI tree VIP
> driver, on the am57xx-evm platform.
> 
> With this resolution (any bus format), output is very dark, we only see very
> bright objects (light bulbs). It seems IPS doesn't drive exposure correctly
> or ISP doesn't have the right parameters.
> 
> But while testing the colorbars, the output is also wrong:
> 
> Command:
> # v4l2-ctl -d1 --set-ctrl test_pattern=1 --set-fmt-video=pixelformat=YUYV,width=600,height=400 --stream-to=out.raw --stream-count=10 --stream-poll --stream-mmap=20
> 
> https://people.freedesktop.org/~narmstrong/ov1065x-600-400-YUYV-colorbar.png
> 
> VIP log is:
> [12324.323181] vin3a: vip_init_port: g_mbus_fmt subdev mbus_code: 2006 fourcc:NV12 size: 600x400
> [12324.323211] vin3a: calc_format_size: fourcc:NV12 size: 600x400 bpl:608 img_size:364800
> [12324.323211] vin3a-0: init_stream fourcc:NV12 size: 600x400 bpl:608 img_size:364800
> [12324.323211] vin3a-0: init_stream vpdma data type: 0x02
> [12324.323242] vin3a-0: vip_init_stream: stream instance 0x00000000c267b000
> [12324.323455] vin3a-0: g_fmt fourcc:NV12 code: 2006 size: 600x400 bpl:608 img_size:364800
> [12324.323455] vin3a-0: g_fmt vpdma data type: 0x02
> [12324.323486] vin3a-0: enum_fmt index:0
> [12324.323486] vin3a-0: enum_fmt fourcc:NV12
> [12324.323486] vin3a-0: enum_fmt index:1
> [12324.323516] vin3a-0: enum_fmt fourcc:UYVY
> [12324.323516] vin3a-0: enum_fmt index:2
> [12324.323516] vin3a-0: enum_fmt fourcc:YUYV
> [12324.323547] vin3a-0: s_fmt input fourcc:YUYV size: 600x400 bpl:0 img_size:364800
> [12324.323547] vin3a-0: try_fmt fourcc:YUYV size: 600x400
> [12324.323547] vin3a-0: try_fmt loop:0 fourcc:YUYV size: 1280x800
> [12324.323577] vin3a-0: try_fmt loop:0 found new larger: 1280x800
> [12324.323577] vin3a-0: try_fmt loop:0 found at least larger: 1280x800
> [12324.323577] vin3a-0: try_fmt loop:0 found new best: 1280x800
> [12324.323577] vin3a-0: try_fmt loop:1 fourcc:YUYV size: 1280x720
> [12324.323608] vin3a-0: try_fmt loop:1 found at least larger: 1280x720
> [12324.323608] vin3a-0: try_fmt loop:1 found new best: 1280x720
> [12324.323608] vin3a-0: try_fmt loop:2 fourcc:YUYV size: 752x480
> [12324.323608] vin3a-0: try_fmt loop:2 found at least larger: 752x480
> [12324.323638] vin3a-0: try_fmt loop:2 found new best: 752x480
> [12324.323638] vin3a-0: try_fmt loop:3 fourcc:YUYV size: 640x480
> [12324.323638] vin3a-0: try_fmt loop:3 found at least larger: 640x480
> [12324.323638] vin3a-0: try_fmt loop:3 found new best: 640x480
> [12324.323669] vin3a-0: try_fmt loop:4 fourcc:YUYV size: 600x400
> [12324.323669] vin3a-0: try_fmt loop:4 found at least larger: 600x400
> [12324.323669] vin3a-0: try_fmt loop:4 found new best: 600x400
> [12324.323669] vin3a-0: try_fmt loop:4 found direct match: 600x400
> [12324.323699] vin3a: calc_format_size: fourcc:YUYV size: 600x400 bpl:1200 img_size:480000
> [12324.323699] vin3a-0: s_fmt try_fmt fourcc:YUYV size: 600x400 bpl:1200 img_size:480000
> [12324.323699] vin3a-0: s_fmt fourcc:YUYV size: 600x400 bpl:1200 img_size:480000
> [12324.323730] vin3a-0: s_fmt pix_to_mbus mbus_code: 2006 size: 600x400
> [12324.323730] vin3a-0: s_fmt subdev fmt mbus_code: 2006 size: 600x400
> [12324.323730] vin3a-0: s_fmt vpdma data type: 0x07
> 
> ov10635 is correctly set with 600x400 and VIP is pass-throught.
> 
> The image & colorbar is OK with any other framesizes requested to ov10635.
> 
> Is this a known issue ?
> 
> Neil
> 
>> +        .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)
>> +{
>> +    unsigned int best_pclk = UINT_MAX;
>> +    unsigned int best_pre_div_x2;
>> +    unsigned int best_mult;
>> +    unsigned int best_div;
>> +    unsigned int best_hts;
>> +    unsigned int max_pre_div_x2;
>> +    unsigned int pre_div_x2;
>> +    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, stored in
>> +     * registers as the index in this list of 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.
>> +     */
>> +
>> +    /*
>> +     * The pre_div_x2 variable stores the pre-div value multiplied by 2, to
>> +     * support the fractional divider 1.5.
>> +     */
>> +    max_pre_div_x2 = min(clk_rate * 2 / (3 * 1000 * 1000), 14U);
>> +
>> +    for (pre_div_x2 = 2; pre_div_x2 <= max_pre_div_x2;
>> +         pre_div_x2 += (pre_div_x2 < 4 ? 1 : 2)) {
>> +        unsigned int clk1 = clk_rate * 2 / pre_div_x2;
>> +        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_x2 = pre_div_x2;
>> +                    best_mult = mult;
>> +                    best_div = div;
>> +                }
>> +            }
>> +        }
>> +    }
>> +
>> +    if (best_pclk == UINT_MAX)
>> +        return -EINVAL;
>> +
>> +    /* Store the mult, pre_div and div as register values. */
>> +    cfg->mult = best_mult;
>> +    cfg->pre_div = best_pre_div_x2 < 4 ? best_pre_div_x2 - 2
>> +             : best_pre_div_x2 / 2;
>> +    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;

HTS calculation seems fishy, with the following change:

=====><========================================================================
--- a/drivers/media/i2c/ov1063x.c
+++ b/drivers/media/i2c/ov1063x.c
@@ -799,7 +799,7 @@ static int ov1063x_configure(struct ov1063x_priv *priv)
         int ret;

         /* Minimum values for HTS anv VTS. */
-       hts = priv->analog_crop.width + 200;
+       hts = priv->analog_crop.width + 210;
=====><========================================================================

I get functional 600x400 framesize.

I got the change from [1], thus not related to the same frame size.

Neil

[1] https://github.com/slawr/linux-stable/commit/8509859572e0f333850f45dd0c1529bed09da051

>> +
>> +    /*
>> +     * 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 || priv->streaming == OV1063X_STREAM_STARTING) {
>> +        /*
>> +         * Only write the full settings when the test pattern was
>> +         * disabled or when we start streaming, 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 == OV1063X_STREAM_OFF)
>> +        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 = OV1063X_STREAM_OFF;
>> +        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 = OV1063X_STREAM_STARTING;
>> +
>> +    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);
>> +
>> +    priv->streaming = OV1063X_STREAM_ON;
>> +
>> +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 = OV1063X_STREAM_OFF;
>> +    }
>> +
>> +    mutex_unlock(priv->hdl.lock);
>> +
>> +    return ret;
>> +}
>> +
>> +static struct v4l2_mbus_framefmt *
>> +__ov1063x_get_pad_format(struct ov1063x_priv *priv,
>> +             struct v4l2_subdev_state *state,
>> +             unsigned int pad, u32 which)
>> +{
>> +    switch (which) {
>> +    case V4L2_SUBDEV_FORMAT_TRY:
>> +        return v4l2_subdev_get_try_format(&priv->subdev, state, pad);
>> +    case V4L2_SUBDEV_FORMAT_ACTIVE:
>> +        return &priv->format;
>> +    default:
>> +        return NULL;
>> +    }
>> +}
>> +
>> +static int ov1063x_init_cfg(struct v4l2_subdev *sd,
>> +                struct v4l2_subdev_state *state)
>> +{
>> +    u32 which = state ? 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, state, 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_state *state,
>> +                  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_state *state,
>> +                    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_state *state,
>> +               struct v4l2_subdev_format *fmt)
>> +{
>> +    struct ov1063x_priv *priv = to_ov1063x(sd);
>> +
>> +    fmt->format = *__ov1063x_get_pad_format(priv, state, fmt->pad,
>> +                        fmt->which);
>> +
>> +    return 0;
>> +}
>> +
>> +static int ov1063x_set_fmt(struct v4l2_subdev *sd,
>> +               struct v4l2_subdev_state *state,
>> +               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];
>> +
>> +    /* 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, state, fmt->pad, fmt->which);
>> +
>> +    mutex_lock(priv->hdl.lock);
>> +
>> +    if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
>> +        priv->streaming != OV1063X_STREAM_OFF) {
>> +        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;
>> +    }
>> +
>> +    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 v4l2_subdev *sd = i2c_get_clientdata(client);
>> +    struct ov1063x_priv *priv = to_ov1063x(sd);
>> +
>> +    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");
>> diff --git a/drivers/media/i2c/ov1063x_regs.h b/drivers/media/i2c/ov1063x_regs.h
>> new file mode 100644
>> index 000000000000..7622de5c9069
>> --- /dev/null
>> +++ b/drivers/media/i2c/ov1063x_regs.h
>> @@ -0,0 +1,627 @@
>> +/* 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@ideasonboard.com>
>> + */
>> +
>> +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, 0x0a | OV1063X_SC_CMMN_CLOCK_SEL_SCLK2X },
>> +    { 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_TIMING_CTRL24, 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_EMB_START_PCNT, 1 },
>> +    { OV1063X_EMB_START_LCNT, 1 },
>> +    { 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, OV1063X_ISP_RW02_OTP_MANUAL_OFFSET_EN |
>> +                OV1063X_ISP_RW02_OTP_EN |
>> +                OV1063X_ISP_RW02_INTER_FRAME_CALC |
>> +                OV1063X_ISP_RW02_CT_AWB_EN |
>> +                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_TPM_SLOPE(0), 4 },
>> +    { OV1063X_TPM_SLOPE(1), 123 },
>> +    { OV1063X_TPM_OFFSET(0), 253 },
>> +    { OV1063X_TPM_OFFSET(1), 249 },
>> +    { OV1063X_TPM_OFFSET(2), 61 },
>> +    { OV1063X_TPM_OFFSET(3), 113 },
>> +    { OV1063X_TPM_CTRL6, 0x70 | OV1063X_TPM_CTRL6_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_EMB_START_PCNT, 1281 },
>> +    { OV1063X_EMB_START_LCNT, 16 },
>> +};
>> +
>> +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_EMB_START_PCNT, 769 },
>> +    { OV1063X_EMB_START_LCNT, 10 },
>> +};
>> +
>> +/*
>> + * 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 },
>> +};
>
Tomi Valkeinen March 24, 2022, 8:48 a.m. UTC | #2
Hi Neil,

On 23/03/2022 18:12, Neil Armstrong wrote:
> On 23/03/2022 15:01, Neil Armstrong wrote:
>> Hi Laurent,
>>
>>
>> On 07/12/2021 00:07, 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.
>>>
>>> [1] http://www.spinics.net/lists/linux-media/msg64347.html
>>>
>>> Signed-off-by: Nikhil Devshatwar <nikhil.nd@ti.com>
>>> Signed-off-by: Benoit Parrot <bparrot@ti.com>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> ---
>>> Changes since v1:
>>>
>>> - Drop unneeded debug message
>>> - Fix MODULE_LICENSE
>>> - Fix priv pointer retrieval in remove()
>>> - Add more registers macros
>>> - Fix PLL calculation
>>> - Update to subdev state API
>>> - Fix test pattern when starting streaming
>>> ---
>>>   MAINTAINERS                      |    2 +
>>>   drivers/media/i2c/Kconfig        |   12 +
>>>   drivers/media/i2c/Makefile       |    1 +
>>>   drivers/media/i2c/ov1063x.c      | 1716 ++++++++++++++++++++++++++++++
>>>   drivers/media/i2c/ov1063x_regs.h |  627 +++++++++++
>>>   5 files changed, 2358 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 9c7748b160dd..eb24dc54e046 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -14044,6 +14044,8 @@ L:    linux-media@vger.kernel.org
>>>   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@linux.intel.com>
>>> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
>>> index d6a5d4ca439a..7a0d7bd17a3c 100644
>>> --- a/drivers/media/i2c/Kconfig
>>> +++ b/drivers/media/i2c/Kconfig
>>> @@ -1192,6 +1192,18 @@ config VIDEO_OV9734
>>>         To compile this driver as a module, choose M here: the
>>>         module's name is ov9734.
>>> +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 4d4fe08d7a6a..a16299de56c0 100644
>>> --- a/drivers/media/i2c/Makefile
>>> +++ b/drivers/media/i2c/Makefile
>>> @@ -88,6 +88,7 @@ obj-$(CONFIG_VIDEO_OV9282) += ov9282.o
>>>   obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
>>>   obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
>>>   obj-$(CONFIG_VIDEO_OV9734) += ov9734.o
>>> +obj-$(CONFIG_VIDEO_OV10633) += ov1063x.o
>>>   obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
>>>   obj-$(CONFIG_VIDEO_OV13B10) += ov13b10.o
>>>   obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
>>> diff --git a/drivers/media/i2c/ov1063x.c b/drivers/media/i2c/ov1063x.c
>>> new file mode 100644
>>> index 000000000000..fb4ef5ea9a9f
>>> --- /dev/null
>>> +++ b/drivers/media/i2c/ov1063x.c
>>> @@ -0,0 +1,1716 @@
>>> +// 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@ideasonboard.com>
>>> + */
>>> +
>>> +#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_CLOCK_SEL_SCLK2X    BIT(0)
>>> +#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_TIMING_CTRL24            OV1063X_REG_8BIT(0x3824)
>>> +#define OV1063X_VSTART_OFFSET            OV1063X_REG_16BIT(0x381e)
>>> +#define OV1063X_TIMING_TC_CS_RST        OV1063X_REG_16BIT(0x3832)
>>> +#define OV1063X_TIMING_TC_R_RST            OV1063X_REG_16BIT(0x3834)
>>> +
>>> +#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_EMB_START_PCNT            OV1063X_REG_16BIT(0x4610)
>>> +#define OV1063X_EMB_START_LCNT            OV1063X_REG_16BIT(0x4612)
>>> +#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_OTP_MANUAL_OFFSET_EN    BIT(7)
>>> +#define OV1063X_ISP_RW02_OTP_EN            BIT(6)
>>> +#define OV1063X_ISP_RW02_INTER_FRAME_CALC    BIT(5)
>>> +#define OV1063X_ISP_RW02_CT_AWB_EN        BIT(4)
>>> +#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_SLOPE(n)            OV1063X_REG_8BIT(0x6700 + (n))
>>> +#define OV1063X_TPM_OFFSET(n)            OV1063X_REG_8BIT(0x6702 + (n))
>>> +#define OV1063X_TPM_CTRL6            OV1063X_REG_8BIT(0x6706)
>>> +#define OV1063X_TPM_CTRL6_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,
>>> +};
>>> +
>>> +enum ov1063x_streaming_state {
>>> +    OV1063X_STREAM_OFF = 0,
>>> +    OV1063X_STREAM_STARTING,
>>> +    OV1063X_STREAM_ON,
>>> +};
>>> +
>>> +#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.
>>> +     */
>>> +    enum ov1063x_streaming_state    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,
>>> +    }, {
>>
>> I have an issue when 600x400 is requested on the ov10635 from the TI 
>> tree VIP
>> driver, on the am57xx-evm platform.
>>
>> With this resolution (any bus format), output is very dark, we only 
>> see very
>> bright objects (light bulbs). It seems IPS doesn't drive exposure 
>> correctly
>> or ISP doesn't have the right parameters.
>>
>> But while testing the colorbars, the output is also wrong:
>>
>> Command:
>> # v4l2-ctl -d1 --set-ctrl test_pattern=1 
>> --set-fmt-video=pixelformat=YUYV,width=600,height=400 
>> --stream-to=out.raw --stream-count=10 --stream-poll --stream-mmap=20
>>
>> https://people.freedesktop.org/~narmstrong/ov1065x-600-400-YUYV-colorbar.png 
>>
>>
>> VIP log is:
>> [12324.323181] vin3a: vip_init_port: g_mbus_fmt subdev mbus_code: 2006 
>> fourcc:NV12 size: 600x400
>> [12324.323211] vin3a: calc_format_size: fourcc:NV12 size: 600x400 
>> bpl:608 img_size:364800
>> [12324.323211] vin3a-0: init_stream fourcc:NV12 size: 600x400 bpl:608 
>> img_size:364800
>> [12324.323211] vin3a-0: init_stream vpdma data type: 0x02
>> [12324.323242] vin3a-0: vip_init_stream: stream instance 
>> 0x00000000c267b000
>> [12324.323455] vin3a-0: g_fmt fourcc:NV12 code: 2006 size: 600x400 
>> bpl:608 img_size:364800
>> [12324.323455] vin3a-0: g_fmt vpdma data type: 0x02
>> [12324.323486] vin3a-0: enum_fmt index:0
>> [12324.323486] vin3a-0: enum_fmt fourcc:NV12
>> [12324.323486] vin3a-0: enum_fmt index:1
>> [12324.323516] vin3a-0: enum_fmt fourcc:UYVY
>> [12324.323516] vin3a-0: enum_fmt index:2
>> [12324.323516] vin3a-0: enum_fmt fourcc:YUYV
>> [12324.323547] vin3a-0: s_fmt input fourcc:YUYV size: 600x400 bpl:0 
>> img_size:364800
>> [12324.323547] vin3a-0: try_fmt fourcc:YUYV size: 600x400
>> [12324.323547] vin3a-0: try_fmt loop:0 fourcc:YUYV size: 1280x800
>> [12324.323577] vin3a-0: try_fmt loop:0 found new larger: 1280x800
>> [12324.323577] vin3a-0: try_fmt loop:0 found at least larger: 1280x800
>> [12324.323577] vin3a-0: try_fmt loop:0 found new best: 1280x800
>> [12324.323577] vin3a-0: try_fmt loop:1 fourcc:YUYV size: 1280x720
>> [12324.323608] vin3a-0: try_fmt loop:1 found at least larger: 1280x720
>> [12324.323608] vin3a-0: try_fmt loop:1 found new best: 1280x720
>> [12324.323608] vin3a-0: try_fmt loop:2 fourcc:YUYV size: 752x480
>> [12324.323608] vin3a-0: try_fmt loop:2 found at least larger: 752x480
>> [12324.323638] vin3a-0: try_fmt loop:2 found new best: 752x480
>> [12324.323638] vin3a-0: try_fmt loop:3 fourcc:YUYV size: 640x480
>> [12324.323638] vin3a-0: try_fmt loop:3 found at least larger: 640x480
>> [12324.323638] vin3a-0: try_fmt loop:3 found new best: 640x480
>> [12324.323669] vin3a-0: try_fmt loop:4 fourcc:YUYV size: 600x400
>> [12324.323669] vin3a-0: try_fmt loop:4 found at least larger: 600x400
>> [12324.323669] vin3a-0: try_fmt loop:4 found new best: 600x400
>> [12324.323669] vin3a-0: try_fmt loop:4 found direct match: 600x400
>> [12324.323699] vin3a: calc_format_size: fourcc:YUYV size: 600x400 
>> bpl:1200 img_size:480000
>> [12324.323699] vin3a-0: s_fmt try_fmt fourcc:YUYV size: 600x400 
>> bpl:1200 img_size:480000
>> [12324.323699] vin3a-0: s_fmt fourcc:YUYV size: 600x400 bpl:1200 
>> img_size:480000
>> [12324.323730] vin3a-0: s_fmt pix_to_mbus mbus_code: 2006 size: 600x400
>> [12324.323730] vin3a-0: s_fmt subdev fmt mbus_code: 2006 size: 600x400
>> [12324.323730] vin3a-0: s_fmt vpdma data type: 0x07
>>
>> ov10635 is correctly set with 600x400 and VIP is pass-throught.
>>
>> The image & colorbar is OK with any other framesizes requested to 
>> ov10635.
>>
>> Is this a known issue ?
>>
>> Neil
>>
>>> +        .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)
>>> +{
>>> +    unsigned int best_pclk = UINT_MAX;
>>> +    unsigned int best_pre_div_x2;
>>> +    unsigned int best_mult;
>>> +    unsigned int best_div;
>>> +    unsigned int best_hts;
>>> +    unsigned int max_pre_div_x2;
>>> +    unsigned int pre_div_x2;
>>> +    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, 
>>> stored in
>>> +     * registers as the index in this list of 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.
>>> +     */
>>> +
>>> +    /*
>>> +     * The pre_div_x2 variable stores the pre-div value multiplied 
>>> by 2, to
>>> +     * support the fractional divider 1.5.
>>> +     */
>>> +    max_pre_div_x2 = min(clk_rate * 2 / (3 * 1000 * 1000), 14U);
>>> +
>>> +    for (pre_div_x2 = 2; pre_div_x2 <= max_pre_div_x2;
>>> +         pre_div_x2 += (pre_div_x2 < 4 ? 1 : 2)) {
>>> +        unsigned int clk1 = clk_rate * 2 / pre_div_x2;
>>> +        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_x2 = pre_div_x2;
>>> +                    best_mult = mult;
>>> +                    best_div = div;
>>> +                }
>>> +            }
>>> +        }
>>> +    }
>>> +
>>> +    if (best_pclk == UINT_MAX)
>>> +        return -EINVAL;
>>> +
>>> +    /* Store the mult, pre_div and div as register values. */
>>> +    cfg->mult = best_mult;
>>> +    cfg->pre_div = best_pre_div_x2 < 4 ? best_pre_div_x2 - 2
>>> +             : best_pre_div_x2 / 2;
>>> +    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;
> 
> HTS calculation seems fishy, with the following change:
> 
> =====><======================================================================== 
> 
> --- a/drivers/media/i2c/ov1063x.c
> +++ b/drivers/media/i2c/ov1063x.c
> @@ -799,7 +799,7 @@ static int ov1063x_configure(struct ov1063x_priv *priv)
>          int ret;
> 
>          /* Minimum values for HTS anv VTS. */
> -       hts = priv->analog_crop.width + 200;
> +       hts = priv->analog_crop.width + 210;
> =====><======================================================================== 
> 
> 
> I get functional 600x400 framesize.
> 
> I got the change from [1], thus not related to the same frame size.
> 
> Neil
> 
> [1] 
> https://github.com/slawr/linux-stable/commit/8509859572e0f333850f45dd0c1529bed09da051 

With a quick test, this helps with both 600x400 and 1280x800 for me. 
Thanks for pointing this out! I'll add this change to my branch. I guess 
this is one of those "this number works better that the other number 
according to my testing, but I don't know why" fixes...

I have stated working on converting VIP to media-controller. That will 
allow us to more easily test different VIP & OV10635 configurations, 
although I fear we'll just find out that there are a lot of problems... 
I can already see that whenever VIP scaling is enabled, I get nothing out.

  Tomi
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 9c7748b160dd..eb24dc54e046 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14044,6 +14044,8 @@  L:	linux-media@vger.kernel.org
 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@linux.intel.com>
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index d6a5d4ca439a..7a0d7bd17a3c 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1192,6 +1192,18 @@  config VIDEO_OV9734
 	  To compile this driver as a module, choose M here: the
 	  module's name is ov9734.
 
+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 4d4fe08d7a6a..a16299de56c0 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -88,6 +88,7 @@  obj-$(CONFIG_VIDEO_OV9282) += ov9282.o
 obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
 obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
 obj-$(CONFIG_VIDEO_OV9734) += ov9734.o
+obj-$(CONFIG_VIDEO_OV10633) += ov1063x.o
 obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
 obj-$(CONFIG_VIDEO_OV13B10) += ov13b10.o
 obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
diff --git a/drivers/media/i2c/ov1063x.c b/drivers/media/i2c/ov1063x.c
new file mode 100644
index 000000000000..fb4ef5ea9a9f
--- /dev/null
+++ b/drivers/media/i2c/ov1063x.c
@@ -0,0 +1,1716 @@ 
+// 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@ideasonboard.com>
+ */
+
+#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_CLOCK_SEL_SCLK2X	BIT(0)
+#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_TIMING_CTRL24			OV1063X_REG_8BIT(0x3824)
+#define OV1063X_VSTART_OFFSET			OV1063X_REG_16BIT(0x381e)
+#define OV1063X_TIMING_TC_CS_RST		OV1063X_REG_16BIT(0x3832)
+#define OV1063X_TIMING_TC_R_RST			OV1063X_REG_16BIT(0x3834)
+
+#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_EMB_START_PCNT			OV1063X_REG_16BIT(0x4610)
+#define OV1063X_EMB_START_LCNT			OV1063X_REG_16BIT(0x4612)
+#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_OTP_MANUAL_OFFSET_EN	BIT(7)
+#define OV1063X_ISP_RW02_OTP_EN			BIT(6)
+#define OV1063X_ISP_RW02_INTER_FRAME_CALC	BIT(5)
+#define OV1063X_ISP_RW02_CT_AWB_EN		BIT(4)
+#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_SLOPE(n)			OV1063X_REG_8BIT(0x6700 + (n))
+#define OV1063X_TPM_OFFSET(n)			OV1063X_REG_8BIT(0x6702 + (n))
+#define OV1063X_TPM_CTRL6			OV1063X_REG_8BIT(0x6706)
+#define OV1063X_TPM_CTRL6_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,
+};
+
+enum ov1063x_streaming_state {
+	OV1063X_STREAM_OFF = 0,
+	OV1063X_STREAM_STARTING,
+	OV1063X_STREAM_ON,
+};
+
+#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.
+	 */
+	enum ov1063x_streaming_state	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)
+{
+	unsigned int best_pclk = UINT_MAX;
+	unsigned int best_pre_div_x2;
+	unsigned int best_mult;
+	unsigned int best_div;
+	unsigned int best_hts;
+	unsigned int max_pre_div_x2;
+	unsigned int pre_div_x2;
+	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, stored in
+	 * registers as the index in this list of 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.
+	 */
+
+	/*
+	 * The pre_div_x2 variable stores the pre-div value multiplied by 2, to
+	 * support the fractional divider 1.5.
+	 */
+	max_pre_div_x2 = min(clk_rate * 2 / (3 * 1000 * 1000), 14U);
+
+	for (pre_div_x2 = 2; pre_div_x2 <= max_pre_div_x2;
+	     pre_div_x2 += (pre_div_x2 < 4 ? 1 : 2)) {
+		unsigned int clk1 = clk_rate * 2 / pre_div_x2;
+		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_x2 = pre_div_x2;
+					best_mult = mult;
+					best_div = div;
+				}
+			}
+		}
+	}
+
+	if (best_pclk == UINT_MAX)
+		return -EINVAL;
+
+	/* Store the mult, pre_div and div as register values. */
+	cfg->mult = best_mult;
+	cfg->pre_div = best_pre_div_x2 < 4 ? best_pre_div_x2 - 2
+		     : best_pre_div_x2 / 2;
+	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 || priv->streaming == OV1063X_STREAM_STARTING) {
+		/*
+		 * Only write the full settings when the test pattern was
+		 * disabled or when we start streaming, 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 == OV1063X_STREAM_OFF)
+		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 = OV1063X_STREAM_OFF;
+		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 = OV1063X_STREAM_STARTING;
+
+	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);
+
+	priv->streaming = OV1063X_STREAM_ON;
+
+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 = OV1063X_STREAM_OFF;
+	}
+
+	mutex_unlock(priv->hdl.lock);
+
+	return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+__ov1063x_get_pad_format(struct ov1063x_priv *priv,
+			 struct v4l2_subdev_state *state,
+			 unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(&priv->subdev, state, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &priv->format;
+	default:
+		return NULL;
+	}
+}
+
+static int ov1063x_init_cfg(struct v4l2_subdev *sd,
+			    struct v4l2_subdev_state *state)
+{
+	u32 which = state ? 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, state, 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_state *state,
+				  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_state *state,
+				    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_state *state,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct ov1063x_priv *priv = to_ov1063x(sd);
+
+	fmt->format = *__ov1063x_get_pad_format(priv, state, fmt->pad,
+						fmt->which);
+
+	return 0;
+}
+
+static int ov1063x_set_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_state *state,
+			   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];
+
+	/* 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, state, fmt->pad, fmt->which);
+
+	mutex_lock(priv->hdl.lock);
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
+	    priv->streaming != OV1063X_STREAM_OFF) {
+		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;
+	}
+
+	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 v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov1063x_priv *priv = to_ov1063x(sd);
+
+	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");
diff --git a/drivers/media/i2c/ov1063x_regs.h b/drivers/media/i2c/ov1063x_regs.h
new file mode 100644
index 000000000000..7622de5c9069
--- /dev/null
+++ b/drivers/media/i2c/ov1063x_regs.h
@@ -0,0 +1,627 @@ 
+/* 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@ideasonboard.com>
+ */
+
+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, 0x0a | OV1063X_SC_CMMN_CLOCK_SEL_SCLK2X },
+	{ 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_TIMING_CTRL24, 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_EMB_START_PCNT, 1 },
+	{ OV1063X_EMB_START_LCNT, 1 },
+	{ 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, OV1063X_ISP_RW02_OTP_MANUAL_OFFSET_EN |
+			    OV1063X_ISP_RW02_OTP_EN |
+			    OV1063X_ISP_RW02_INTER_FRAME_CALC |
+			    OV1063X_ISP_RW02_CT_AWB_EN |
+			    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_TPM_SLOPE(0), 4 },
+	{ OV1063X_TPM_SLOPE(1), 123 },
+	{ OV1063X_TPM_OFFSET(0), 253 },
+	{ OV1063X_TPM_OFFSET(1), 249 },
+	{ OV1063X_TPM_OFFSET(2), 61 },
+	{ OV1063X_TPM_OFFSET(3), 113 },
+	{ OV1063X_TPM_CTRL6, 0x70 | OV1063X_TPM_CTRL6_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_EMB_START_PCNT, 1281 },
+	{ OV1063X_EMB_START_LCNT, 16 },
+};
+
+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_EMB_START_PCNT, 769 },
+	{ OV1063X_EMB_START_LCNT, 10 },
+};
+
+/*
+ * 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 },
+};