Hi Laurent,
On 07/12/2021 00:07, Laurent Pinchart wrote:
Add a new V4L2 subdev driver for the OmniVision OV10633 and OV10635
camera sensors. The work is based on the driver from the TI BSP, itself
based on original work by Phil Edworthy posted to the linux-media
mailing list ([1]). This version of the code is a large rewrite of many
parts.
[1] http://www.spinics.net/lists/linux-media/msg64347.html
Signed-off-by: Nikhil Devshatwar <nikhil.nd@xxxxxx>
Signed-off-by: Benoit Parrot <bparrot@xxxxxx>
Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
---
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@xxxxxxxxxxxxxxx
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ov1063x.yaml
+F: drivers/media/i2c/ov1063x.c
+F: drivers/media/i2c/ov1063x_regs.h
OMNIVISION OV13858 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx>
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index d6a5d4ca439a..7a0d7bd17a3c 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1192,6 +1192,18 @@ config VIDEO_OV9734
To compile this driver as a module, choose M here: the
module's name is ov9734.
+config VIDEO_OV10633
+ tristate "OmniVision OV10633/OV10635 sensor support"
+ depends on I2C && VIDEO_V4L2
+ depends on GPIOLIB && OF
+ select MEDIA_CONTROLLER
+ select REGMAP_I2C
+ select V4L2_FWNODE
+ select VIDEO_V4L2_SUBDEV_API
+ help
+ This is a Video4Linux2 driver for the OmniVision
+ OV10633 and OV10635 camera sensors.
+
config VIDEO_OV13858
tristate "OmniVision OV13858 sensor support"
depends on I2C && VIDEO_V4L2
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 4d4fe08d7a6a..a16299de56c0 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_VIDEO_OV9282) += ov9282.o
obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
obj-$(CONFIG_VIDEO_OV9734) += ov9734.o
+obj-$(CONFIG_VIDEO_OV10633) += ov1063x.o
obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
obj-$(CONFIG_VIDEO_OV13B10) += ov13b10.o
obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
diff --git a/drivers/media/i2c/ov1063x.c b/drivers/media/i2c/ov1063x.c
new file mode 100644
index 000000000000..fb4ef5ea9a9f
--- /dev/null
+++ b/drivers/media/i2c/ov1063x.c
@@ -0,0 +1,1716 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * OmniVision OV10633/OV10635 Camera Driver
+ *
+ * Based on the original driver written by Phil Edworthy.
+ * Copyright (C) 2013 Phil Edworthy
+ * Copyright (C) 2013 Renesas Electronics
+ * Copyright (C) 2018 Texas Instruments Incorporated -
http://www.ti.com/
+ * Copyright (C) 2020 Laurent Pinchart
<laurent.pinchart@xxxxxxxxxxxxxxxx>
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+/* Register definitions */
+#define OV1063X_REG_8BIT(n) ((1 << 16) | (n))
+#define OV1063X_REG_16BIT(n) ((2 << 16) | (n))
+#define OV1063X_REG_24BIT(n) ((3 << 16) | (n))
+#define OV1063X_REG_32BIT(n) ((4 << 16) | (n))
+#define OV1063X_REG_SIZE_SHIFT 16
+#define OV1063X_REG_ADDR_MASK 0xffff
+
+#define OV1063X_STREAM_MODE OV1063X_REG_8BIT(0x0100)
+#define OV1063X_STREAM_MODE_ON BIT(0)
+#define OV1063X_SOFTWARE_RESET OV1063X_REG_8BIT(0x0103)
+
+#define OV1063X_SC_CMMN_PLL_CTRL0 OV1063X_REG_8BIT(0x3003)
+#define OV1063X_SC_CMMN_PLL_SCLK_CP(n) ((n) << 6)
+#define OV1063X_SC_CMMN_PLL_SCLK_MULTI(n) ((n) << 0)
+#define OV1063X_SC_CMMN_PLL_CTRL1 OV1063X_REG_8BIT(0x3004)
+#define OV1063X_SC_CMMN_PLL_SCLK_BYPASS BIT(7)
+#define OV1063X_SC_CMMN_PLL_SCLK_PRE_DIV(n) ((n) << 4) /* /1,
/1.5, /2, /3, /4, /5, /6, /7 */
+#define OV1063X_SC_CMMN_PLL_SCLK_CP2(n) ((n) << 3)
+#define OV1063X_SC_CMMN_PLL_SCLK_DIV(n) ((n) << 0) /*
Divider = 2 * (1 + n) */
+#define OV1063X_SC_CMMN_PLL_CTRL2 OV1063X_REG_8BIT(0x3005)
+#define OV1063X_SC_CMMN_PLL_PCLK_CP(n) ((n) << 6)
+#define OV1063X_SC_CMMN_PLL_PCLK_MULTI(n) ((n) << 0)
+#define OV1063X_SC_CMMN_PLL_CTRL3 OV1063X_REG_8BIT(0x3006)
+#define OV1063X_SC_CMMN_PLL_PCLK_BYPASS BIT(7)
+#define OV1063X_SC_CMMN_PLL_PCLK_PRE_DIV(n) ((n) << 4) /* /1,
/1.5, /2, /3, /4, /5, /6, /7 */
+#define OV1063X_SC_CMMN_PLL_PCLK_CP2(n) ((n) << 3)
+#define OV1063X_SC_CMMN_PLL_PCLK_DIV(n) ((n) << 0) /*
Divider = 2 * (1 + n) */
+#define OV1063X_SC_CMMN_PCLK_DIV_CTRL OV1063X_REG_8BIT(0x3007)
+#define OV1063X_PID OV1063X_REG_16BIT(0x300a)
+#define OV1063X_SC_CMMN_SCCB_ID OV1063X_REG_8BIT(0x300c)
+#define OV1063X_SC_CMMN_SCCB_ID_ADDR(n) ((n) << 1)
+#define OV1063X_SC_CMMN_SCCB_ID_SEL BIT(0)
+#define OV1063X_SC_CMMN_PAD OV1063X_REG_8BIT(0x3011)
+#define OV1063X_SC_CMMN_PAD_DRIVE(n) ((n) << 6)
+#define OV1063X_SC_CMMN_CLKRST0 OV1063X_REG_8BIT(0x301a)
+#define OV1063X_SC_CMMN_CLKRST0_SCLK GENMASK(7, 4)
+#define OV1063X_SC_CMMN_CLKRST0_RST GENMASK(3, 0)
+#define OV1063X_SC_CMMN_CLKRST1 OV1063X_REG_8BIT(0x301b)
+#define OV1063X_SC_CMMN_CLKRST1_SCLK GENMASK(7, 4)
+#define OV1063X_SC_CMMN_CLKRST1_RST GENMASK(3, 0)
+#define OV1063X_SC_CMMN_CLKRST2 OV1063X_REG_8BIT(0x301c)
+#define OV1063X_SC_CMMN_CLKRST2_PCLK_DVP BIT(7)
+#define OV1063X_SC_CMMN_CLKRST2_SCLK GENMASK(6, 4)
+#define OV1063X_SC_CMMN_CLKRST2_RST_DVP BIT(3)
+#define OV1063X_SC_CMMN_CLKRST2_RST GENMASK(2, 0)
+#define OV1063X_SC_CMMN_CLOCK_SEL OV1063X_REG_8BIT(0x3020)
+#define OV1063X_SC_CMMN_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;