From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AD250C433F5 for ; Wed, 23 Mar 2022 16:12:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238333AbiCWQNt (ORCPT ); Wed, 23 Mar 2022 12:13:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58658 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233715AbiCWQNr (ORCPT ); Wed, 23 Mar 2022 12:13:47 -0400 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 851AD4614E for ; Wed, 23 Mar 2022 09:12:14 -0700 (PDT) Received: by mail-wr1-x431.google.com with SMTP id u16so2832285wru.4 for ; Wed, 23 Mar 2022 09:12:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20210112.gappssmtp.com; s=20210112; h=message-id:date:mime-version:user-agent:subject:content-language :from:to:cc:references:organization:in-reply-to :content-transfer-encoding; bh=HQjkNCPUXR9de6B6yvngM0I4AqH69qWXRMFnNZGTM/I=; b=rYz90tyFgUn8Slzq9Amxsrd5zHb7Y9CIIR7/9ToaVhjrKqzwr82MPQhXy1qeYGYeZV e1PlE2trOjCy1R/EwXnRAGg8bSt/jmmzExXjGQC0dhyGV9Bazrw09J8B0X5LLzw/ae+p MmtyCIlvCE7mgPBYA6wx00sDhciyRaaZtON2Fn2vtmGMuh8ge1QzhDoOwZDIUgrAuFjZ 2L4bkdWKXujAJ731xqRs/Z9AvV6tcrt+vPm/bv98JmJHoHbfmDWtLJjGBWaN0VBmObOg XxZw5Eg4AEB8JY8x+WnXUNbFXbvlFxIB5w4NCGmqrGzNTzT4H9NKGNCotsh8uyl0Vce7 9KgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:from:to:cc:references:organization:in-reply-to :content-transfer-encoding; bh=HQjkNCPUXR9de6B6yvngM0I4AqH69qWXRMFnNZGTM/I=; b=Q+KJrORytDwY9YfQhto9CjGq+kkjKLYEheRwiZFVy1JtjPQwMOUuj8+b3czYHgNLsV 2PtTzu5+OSiN4ixexM02EE5r3uD4MMMK3+2TzHP9mhpcHmxmal1yu7nysC57n/cCD810 RWRCByI+EfTMzKRAQmoZmh4pIYZoxKkfCcNGi7D3S+YOP35E3astM0Q8jJckOS9tpD1W zG2y6cX7d2IxvgfjiB4uPENOPlKUrLoJxtGR4765HfzWzN8/m7yr9+g+DKAQCDUgzsAF HTZWpABUse8XKYcWsX4yKsUTgIjVvk2vXt4Bb63S7I3UKWixJ6jfZQpOjicu7yZ3B4A5 gp7g== X-Gm-Message-State: AOAM533lRAtdwaf8bmrq5bl99q5rwddoeaDOwHgquVRrjBAiUwZdn3O1 mQfYkvJ6wdkoZ+Wa3GIg3HRcJro6QCJWUg== X-Google-Smtp-Source: ABdhPJwXxsrrNmRnTugavkvSQQicrrM2t3cnu+15DpIp+0g4/ojwM6sCGrYZ6SxZGXDiW9ps9KJegA== X-Received: by 2002:adf:a58a:0:b0:1ef:603f:fb58 with SMTP id g10-20020adfa58a000000b001ef603ffb58mr541084wrc.472.1648051932103; Wed, 23 Mar 2022 09:12:12 -0700 (PDT) Received: from ?IPV6:2001:861:44c0:66c0:871b:e667:ca26:e5eb? ([2001:861:44c0:66c0:871b:e667:ca26:e5eb]) by smtp.gmail.com with ESMTPSA id 2-20020a1c1902000000b00380d3873d6asm271585wmz.43.2022.03.23.09.12.11 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 23 Mar 2022 09:12:11 -0700 (PDT) Message-ID: <5a2b6171-e784-e40c-7142-b69d4b99fd77@baylibre.com> Date: Wed, 23 Mar 2022 17:12:10 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0 Subject: Re: [PATCH v2 2/2] media: i2c: Add OV1063x sensor driver Content-Language: en-US From: Neil Armstrong To: Laurent Pinchart , linux-media@vger.kernel.org Cc: Sakari Ailus , Tomi Valkeinen , Benoit Parrot References: <20211206230717.5836-1-laurent.pinchart@ideasonboard.com> <20211206230717.5836-3-laurent.pinchart@ideasonboard.com> Organization: Baylibre In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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 >> Signed-off-by: Benoit Parrot >> Signed-off-by: Laurent Pinchart >> --- >> 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 >> 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 >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/* 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 >> + */ >> + >> +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 }, >> +}; >