summaryrefslogtreecommitdiffstats
path: root/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0506-media-i2c-imagers-add-AR0231-for-new-LVDS-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0506-media-i2c-imagers-add-AR0231-for-new-LVDS-support.patch')
-rw-r--r--bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0506-media-i2c-imagers-add-AR0231-for-new-LVDS-support.patch1843
1 files changed, 1843 insertions, 0 deletions
diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0506-media-i2c-imagers-add-AR0231-for-new-LVDS-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0506-media-i2c-imagers-add-AR0231-for-new-LVDS-support.patch
new file mode 100644
index 00000000..c75293ae
--- /dev/null
+++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0506-media-i2c-imagers-add-AR0231-for-new-LVDS-support.patch
@@ -0,0 +1,1843 @@
+From f113d62d104a24b6035d969bad8cb04af54d7534 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Thu, 30 Apr 2020 10:54:49 +0300
+Subject: [PATCH] media: i2c: imagers: add AR0231 for new LVDS support
+
+This adds AR0231 into new LVDS drivers that support all enabled
+serializers
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ drivers/media/i2c/soc_camera/imagers/Makefile | 1 +
+ drivers/media/i2c/soc_camera/imagers/ar0231.c | 604 +++++++++++++++++++++
+ drivers/media/i2c/soc_camera/imagers/ar0231.h | 35 ++
+ drivers/media/i2c/soc_camera/imagers/ar0231_rev4.h | 344 ++++++++++++
+ drivers/media/i2c/soc_camera/imagers/ar0231_rev6.h | 343 ++++++++++++
+ drivers/media/i2c/soc_camera/imagers/ar0231_rev7.h | 445 +++++++++++++++
+ 5 files changed, 1771 insertions(+)
+ create mode 100644 drivers/media/i2c/soc_camera/imagers/ar0231.c
+ create mode 100644 drivers/media/i2c/soc_camera/imagers/ar0231.h
+ create mode 100644 drivers/media/i2c/soc_camera/imagers/ar0231_rev4.h
+ create mode 100644 drivers/media/i2c/soc_camera/imagers/ar0231_rev6.h
+ create mode 100644 drivers/media/i2c/soc_camera/imagers/ar0231_rev7.h
+
+diff --git a/drivers/media/i2c/soc_camera/imagers/Makefile b/drivers/media/i2c/soc_camera/imagers/Makefile
+index 0d0ff32..eeb36fd 100644
+--- a/drivers/media/i2c/soc_camera/imagers/Makefile
++++ b/drivers/media/i2c/soc_camera/imagers/Makefile
+@@ -1,7 +1,8 @@
+ # SPDX-License-Identifier: GPL-2.0
++obj-$(CONFIG_SOC_CAMERA_OV106XX) += ap0101_ar014x.o
++obj-$(CONFIG_SOC_CAMERA_OV106XX) += ap0201_ar023x.o
++obj-$(CONFIG_SOC_CAMERA_OV106XX) += ar0231.o
+ obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov10635.o
+ obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov2311.o
+ obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov490.o
+-obj-$(CONFIG_SOC_CAMERA_OV106XX) += ap0101_ar014x.o
+-obj-$(CONFIG_SOC_CAMERA_OV106XX) += ap0201_ar023x.o
+ obj-$(CONFIG_SOC_CAMERA_OV106XX) += dummy.o
+diff --git a/drivers/media/i2c/soc_camera/imagers/ar0231.c b/drivers/media/i2c/soc_camera/imagers/ar0231.c
+new file mode 100644
+index 0000000..fc08793
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/imagers/ar0231.c
+@@ -0,0 +1,604 @@
++/*
++ * ON Semiconductor AR0231 sensor camera driver
++ *
++ * Copyright (C) 2018-220 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/of_graph.h>
++#include <linux/videodev2.h>
++
++#include <media/soc_camera.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-ctrls.h>
++
++#include "../gmsl/common.h"
++#include "ar0231.h"
++
++static const int ar0231_i2c_addr[] = {0x10, 0x20};
++
++#define AR0231_PID_REG 0x3000
++#define AR0231_REV_REG 0x31FE
++#define AR0231_PID 0x0354
++
++#define AR0231_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12
++
++struct ar0231_priv {
++ struct v4l2_subdev sd;
++ struct v4l2_ctrl_handler hdl;
++ struct media_pad pad;
++ struct v4l2_rect rect;
++ int init_complete;
++ u8 id[6];
++ /* serializers */
++ int ser_addr;
++ int trigger;
++};
++
++static int trigger = 0;
++module_param(trigger, int, 0644);
++MODULE_PARM_DESC(trigger, " Trigger gpio number (default: 0 - GPIO0) ");
++
++static inline struct ar0231_priv *to_ar0231(const struct i2c_client *client)
++{
++ return container_of(i2c_get_clientdata(client), struct ar0231_priv, sd);
++}
++
++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
++{
++ return &container_of(ctrl->handler, struct ar0231_priv, hdl)->sd;
++}
++
++static int ar0231_set_regs(struct i2c_client *client,
++ const struct ar0231_reg *regs, int nr_regs)
++{
++ int i;
++
++ for (i = 0; i < nr_regs; i++) {
++ if (regs[i].reg == AR0231_DELAY) {
++ mdelay(regs[i].val);
++ continue;
++ }
++
++ reg16_write16(client, regs[i].reg, regs[i].val);
++ }
++
++ return 0;
++}
++
++static void ar0231_otp_id_read(struct i2c_client *client)
++{
++ struct ar0231_priv *priv = to_ar0231(client);
++ int i;
++ u16 val = 0;
++
++ /* read camera id from ar014x OTP memory */
++ reg16_write16(client, 0x3054, 0x400);
++ reg16_write16(client, 0x304a, 0x110);
++ usleep_range(25000, 25500); /* wait 25 ms */
++
++ for (i = 0; i < 6; i += 2) {
++ /* first 4 bytes are equal on all ar014x */
++ reg16_read16(client, 0x3800 + i + 4, &val);
++ priv->id[i] = val >> 8;
++ priv->id[i + 1] = val & 0xff;
++ }
++}
++
++
++static int ar0231_s_stream(struct v4l2_subdev *sd, int enable)
++{
++ return 0;
++}
++
++static int ar0231_set_window(struct v4l2_subdev *sd)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ar0231_priv *priv = to_ar0231(client);
++
++ dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height);
++
++ /* horiz crop start */
++ reg16_write16(client, 0x3004, priv->rect.left + AR0231_X_START);
++ /* horiz crop end */
++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1 + AR0231_X_START);
++ /* vert crop start */
++ reg16_write16(client, 0x3002, priv->rect.top + AR0231_Y_START);
++ /* vert crop end */
++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height - 1 + AR0231_Y_START);
++
++ return 0;
++};
++
++static int ar0231_get_fmt(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_format *format)
++{
++ struct v4l2_mbus_framefmt *mf = &format->format;
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ar0231_priv *priv = to_ar0231(client);
++
++ if (format->pad)
++ return -EINVAL;
++
++ mf->width = priv->rect.width;
++ mf->height = priv->rect.height;
++ mf->code = AR0231_MEDIA_BUS_FMT;
++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
++ mf->field = V4L2_FIELD_NONE;
++
++ return 0;
++}
++
++static int ar0231_set_fmt(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_format *format)
++{
++ struct v4l2_mbus_framefmt *mf = &format->format;
++
++ mf->code = AR0231_MEDIA_BUS_FMT;
++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
++ mf->field = V4L2_FIELD_NONE;
++
++ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
++ cfg->try_fmt = *mf;
++
++ return 0;
++}
++
++static int ar0231_enum_mbus_code(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_mbus_code_enum *code)
++{
++ if (code->pad || code->index > 0)
++ return -EINVAL;
++
++ code->code = AR0231_MEDIA_BUS_FMT;
++
++ return 0;
++}
++
++static int ar0231_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ar0231_priv *priv = to_ar0231(client);
++
++ memcpy(edid->edid, priv->id, 6);
++
++ edid->edid[6] = 0xff;
++ edid->edid[7] = client->addr;
++ edid->edid[8] = AR0231_PID >> 8;
++ edid->edid[9] = AR0231_PID & 0xff;
++
++ return 0;
++}
++
++static int ar0231_set_selection(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_selection *sel)
++{
++ struct v4l2_rect *rect = &sel->r;
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ar0231_priv *priv = to_ar0231(client);
++
++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
++ sel->target != V4L2_SEL_TGT_CROP)
++ return -EINVAL;
++
++ rect->left = ALIGN(rect->left, 2);
++ rect->top = ALIGN(rect->top, 2);
++ rect->width = ALIGN(rect->width, 2);
++ rect->height = ALIGN(rect->height, 2);
++
++ if ((rect->left + rect->width > AR0231_MAX_WIDTH) ||
++ (rect->top + rect->height > AR0231_MAX_HEIGHT))
++ *rect = priv->rect;
++
++ priv->rect.left = rect->left;
++ priv->rect.top = rect->top;
++ priv->rect.width = rect->width;
++ priv->rect.height = rect->height;
++
++ ar0231_set_window(sd);
++
++ return 0;
++}
++
++static int ar0231_get_selection(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_selection *sel)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ar0231_priv *priv = to_ar0231(client);
++
++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
++ return -EINVAL;
++
++ switch (sel->target) {
++ case V4L2_SEL_TGT_CROP_BOUNDS:
++ sel->r.left = 0;
++ sel->r.top = 0;
++ sel->r.width = AR0231_MAX_WIDTH;
++ sel->r.height = AR0231_MAX_HEIGHT;
++ return 0;
++ case V4L2_SEL_TGT_CROP_DEFAULT:
++ sel->r.left = 0;
++ sel->r.top = 0;
++ sel->r.width = AR0231_MAX_WIDTH;
++ sel->r.height = AR0231_MAX_HEIGHT;
++ return 0;
++ case V4L2_SEL_TGT_CROP:
++ sel->r = priv->rect;
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int ar0231_g_mbus_config(struct v4l2_subdev *sd,
++ struct v4l2_mbus_config *cfg)
++{
++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
++ cfg->type = V4L2_MBUS_CSI2;
++
++ return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int ar0231_g_register(struct v4l2_subdev *sd,
++ struct v4l2_dbg_register *reg)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ int ret;
++ __be64 be_val;
++
++ if (!reg->size)
++ reg->size = sizeof(u16);
++ if (reg->size > sizeof(reg->val))
++ reg->size = sizeof(reg->val);
++
++ ret = reg16_read_n(client, (u16)reg->reg, (u8*)&be_val, reg->size);
++ be_val = be_val << ((sizeof(be_val) - reg->size) * 8);
++ reg->val = be64_to_cpu(be_val);
++
++ return ret;
++}
++
++static int ar0231_s_register(struct v4l2_subdev *sd,
++ const struct v4l2_dbg_register *reg)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ u32 size = reg->size;
++ int ret;
++ __be64 be_val;
++
++ if (!size)
++ size = sizeof(u16);
++ if (size > sizeof(reg->val))
++ size = sizeof(reg->val);
++
++ be_val = cpu_to_be64(reg->val);
++ be_val = be_val >> ((sizeof(be_val) - size) * 8);
++ ret = reg16_write_n(client, (u16)reg->reg, (u8*)&be_val, size);
++
++ return ret;
++}
++#endif
++
++static struct v4l2_subdev_core_ops ar0231_core_ops = {
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .g_register = ar0231_g_register,
++ .s_register = ar0231_s_register,
++#endif
++};
++
++static int ar0231_s_ctrl(struct v4l2_ctrl *ctrl)
++{
++ struct v4l2_subdev *sd = to_sd(ctrl);
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ar0231_priv *priv = to_ar0231(client);
++ int ret = -EINVAL;
++ u16 val = 0;
++
++ if (!priv->init_complete)
++ return 0;
++
++ switch (ctrl->id) {
++ case V4L2_CID_BRIGHTNESS:
++ case V4L2_CID_CONTRAST:
++ case V4L2_CID_SATURATION:
++ case V4L2_CID_HUE:
++ case V4L2_CID_GAMMA:
++ case V4L2_CID_SHARPNESS:
++ case V4L2_CID_AUTOGAIN:
++ break;
++ case V4L2_CID_GAIN:
++ /* Digital gain */
++ ret = reg16_write16(client, 0x3308, ctrl->val);
++ break;
++ case V4L2_CID_ANALOGUE_GAIN:
++ /* Analog gain */
++ ret = reg16_write16(client, 0x3366, (ctrl->val << 8) | (ctrl->val << 4) | ctrl->val);
++ break;
++ case V4L2_CID_EXPOSURE:
++ /* T1 exposure */
++ ret = reg16_write16(client, 0x3012, ctrl->val);
++ break;
++ case V4L2_CID_HFLIP:
++ ret = reg16_read16(client, 0x3040, &val);
++ if (ctrl->val)
++ val |= (1 << 14);
++ else
++ val &= ~(1 << 14);
++ ret |= reg16_write16(client, 0x3040, val);
++ break;
++ case V4L2_CID_VFLIP:
++ ret = reg16_read16(client, 0x3040, &val);
++ if (ctrl->val)
++ val |= (1 << 15);
++ else
++ val &= ~(1 << 15);
++ ret |= reg16_write16(client, 0x3040, val);
++ break;
++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
++ ret = 0;
++ break;
++ }
++
++ return ret;
++}
++
++static const struct v4l2_ctrl_ops ar0231_ctrl_ops = {
++ .s_ctrl = ar0231_s_ctrl,
++};
++
++static struct v4l2_subdev_video_ops ar0231_video_ops = {
++ .s_stream = ar0231_s_stream,
++ .g_mbus_config = ar0231_g_mbus_config,
++};
++
++static const struct v4l2_subdev_pad_ops ar0231_subdev_pad_ops = {
++ .get_edid = ar0231_get_edid,
++ .enum_mbus_code = ar0231_enum_mbus_code,
++ .get_selection = ar0231_get_selection,
++ .set_selection = ar0231_set_selection,
++ .get_fmt = ar0231_get_fmt,
++ .set_fmt = ar0231_set_fmt,
++};
++
++static struct v4l2_subdev_ops ar0231_subdev_ops = {
++ .core = &ar0231_core_ops,
++ .video = &ar0231_video_ops,
++ .pad = &ar0231_subdev_pad_ops,
++};
++
++static ssize_t ar0231_otp_id_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev));
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ar0231_priv *priv = to_ar0231(client);
++
++ ar0231_otp_id_read(client);
++
++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n",
++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
++}
++
++static DEVICE_ATTR(otp_id_ar0231, S_IRUGO, ar0231_otp_id_show, NULL);
++
++static int ar0231_initialize(struct i2c_client *client)
++{
++ struct ar0231_priv *priv = to_ar0231(client);
++ u16 val = 0, pid = 0, rev = 0;
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(ar0231_i2c_addr); i++) {
++ setup_i2c_translator(client, priv->ser_addr, ar0231_i2c_addr[i] << 1);
++
++ /* check model ID */
++ reg16_read16(client, AR0231_PID_REG, &pid);
++ if (pid == AR0231_PID)
++ break;
++ }
++
++ if (pid != AR0231_PID) {
++ dev_dbg(&client->dev, "Product ID error %x\n", pid);
++ return -ENODEV;
++ }
++
++ /* check revision */
++ reg16_read16(client, AR0231_REV_REG, &rev);
++ /* Read OTP IDs */
++ ar0231_otp_id_read(client);
++ /* Program wizard registers */
++ switch (get_des_id(client)) {
++ case UB960_ID:
++ ar0231_set_regs(client, ar0231_regs_wizard_rev7, ARRAY_SIZE(ar0231_regs_wizard_rev7));
++ break;
++ case MAX9286_ID:
++ case MAX9296A_ID:
++ case MAX96712_ID:
++ ar0231_set_regs(client, ar0231_regs_wizard_rev6_dvp, ARRAY_SIZE(ar0231_regs_wizard_rev6_dvp));
++ break;
++ }
++ /* Enable trigger */
++ if (priv->trigger >= 0 && priv->trigger < 4) {
++ reg16_write16(client, 0x340A, (~(BIT(priv->trigger) << 4)) & 0xf0);/* GPIO_CONTROL1: GPIOn input enable */
++ reg16_write16(client, 0x340C, (0x2 << 2*priv->trigger)); /* GPIO_CONTROL2: GPIOn is trigger */
++ reg16_write16(client, 0x30CE, 0x0120); /* TRIGGER_MODE */
++ //reg16_write16(client, 0x30DC, 0x0120); /* TRIGGER_DELAY */
++ }
++ /* Enable stream */
++ reg16_read16(client, 0x301a, &val);
++ val |= (1 << 8); /* GPI pins enable */
++ val |= (1 << 2);
++ reg16_write16(client, 0x301a, val);
++
++ dev_info(&client->dev, "ar0231 PID %x (rev%x), res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
++ pid, rev & 0xf, AR0231_MAX_WIDTH, AR0231_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
++ return 0;
++}
++
++static const struct i2c_device_id ar0231_id[] = {
++ { "ar0231", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ar0231_id);
++
++static const struct of_device_id ar0231_of_ids[] = {
++ { .compatible = "onnn,ar0231", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ar0231_of_ids);
++
++static int ar0231_parse_dt(struct device_node *np, struct ar0231_priv *priv)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
++ u32 addrs[2], naddrs;
++
++ naddrs = of_property_count_elems_of_size(np, "reg", sizeof(u32));
++ if (naddrs != 2) {
++ dev_err(&client->dev, "Invalid DT reg property\n");
++ return -EINVAL;
++ }
++
++ if (of_property_read_u32_array(client->dev.of_node, "reg", addrs, naddrs) < 0) {
++ dev_err(&client->dev, "Invalid DT reg property\n");
++ return -EINVAL;
++ }
++
++ priv->ser_addr = addrs[1];
++
++ if (of_property_read_u32(np, "trigger", &priv->trigger))
++ priv->trigger = 0;
++
++ /* module params override dts */
++ if (trigger)
++ priv->trigger = trigger;
++
++ return 0;
++}
++
++static int ar0231_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ struct ar0231_priv *priv;
++ int ret;
++
++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0231_subdev_ops);
++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
++
++ v4l2_ctrl_handler_init(&priv->hdl, 4);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_CONTRAST, 0, 16, 1, 7);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_SATURATION, 0, 7, 1, 2);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_HUE, 0, 23, 1, 12);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_GAMMA, -128, 128, 1, 0);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_SHARPNESS, 0, 10, 1, 3);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0xa);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_EXPOSURE, 1, 0x600, 1, 0x144);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_HFLIP, 0, 1, 1, 0);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops,
++ V4L2_CID_VFLIP, 0, 1, 1, 0);
++ priv->sd.ctrl_handler = &priv->hdl;
++
++ ret = priv->hdl.error;
++ if (ret)
++ goto cleanup;
++
++ v4l2_ctrl_handler_setup(&priv->hdl);
++
++ priv->pad.flags = MEDIA_PAD_FL_SOURCE;
++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR;
++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad);
++ if (ret < 0)
++ goto cleanup;
++
++ ret = ar0231_parse_dt(client->dev.of_node, priv);
++ if (ret)
++ goto cleanup;
++
++ ret = ar0231_initialize(client);
++ if (ret < 0)
++ goto cleanup;
++
++ priv->rect.left = 0;
++ priv->rect.top = 0;
++ priv->rect.width = AR0231_MAX_WIDTH;
++ priv->rect.height = AR0231_MAX_HEIGHT;
++
++ ret = v4l2_async_register_subdev(&priv->sd);
++ if (ret)
++ goto cleanup;
++
++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0231) != 0) {
++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n");
++ goto cleanup;
++ }
++
++ priv->init_complete = 1;
++
++ return 0;
++
++cleanup:
++ media_entity_cleanup(&priv->sd.entity);
++ v4l2_ctrl_handler_free(&priv->hdl);
++ v4l2_device_unregister_subdev(&priv->sd);
++ return ret;
++}
++
++static int ar0231_remove(struct i2c_client *client)
++{
++ struct ar0231_priv *priv = i2c_get_clientdata(client);
++
++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0231);
++ v4l2_async_unregister_subdev(&priv->sd);
++ media_entity_cleanup(&priv->sd.entity);
++ v4l2_ctrl_handler_free(&priv->hdl);
++ v4l2_device_unregister_subdev(&priv->sd);
++
++ return 0;
++}
++
++static struct i2c_driver ar0231_i2c_driver = {
++ .driver = {
++ .name = "ar0231",
++ .of_match_table = ar0231_of_ids,
++ },
++ .probe = ar0231_probe,
++ .remove = ar0231_remove,
++ .id_table = ar0231_id,
++};
++
++module_i2c_driver(ar0231_i2c_driver);
++
++MODULE_DESCRIPTION("SoC Camera driver for AR0231");
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/i2c/soc_camera/imagers/ar0231.h b/drivers/media/i2c/soc_camera/imagers/ar0231.h
+new file mode 100644
+index 0000000..e455b38
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/imagers/ar0231.h
+@@ -0,0 +1,35 @@
++/*
++ * ON Semiconductor AR0231 sensor camera wizard 1928x1208@30/BGGR/BT601
++ *
++ * Copyright (C) 2018-2020 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++//#define AR0231_DISPLAY_PATTERN_FIXED
++//#define AR0231_DISPLAY_PATTERN_COLOR_BAR
++
++#define AR0231_MAX_WIDTH 1920
++#define AR0231_MAX_HEIGHT 1200
++
++#define AR0231_DELAY 0xffff
++
++#define AR0231_SENSOR_WIDTH 1928
++#define AR0231_SENSOR_HEIGHT 1208
++
++#define AR0231_X_START ((AR0231_SENSOR_WIDTH - AR0231_MAX_WIDTH) / 2)
++#define AR0231_Y_START ((AR0231_SENSOR_HEIGHT - AR0231_MAX_HEIGHT) / 2)
++#define AR0231_X_END (AR0231_X_START + AR0231_MAX_WIDTH - 1)
++#define AR0231_Y_END (AR0231_Y_START + AR0231_MAX_HEIGHT - 1)
++
++struct ar0231_reg {
++ u16 reg;
++ u16 val;
++};
++
++#include "ar0231_rev4.h"
++#include "ar0231_rev6.h"
++#include "ar0231_rev7.h"
+diff --git a/drivers/media/i2c/soc_camera/imagers/ar0231_rev4.h b/drivers/media/i2c/soc_camera/imagers/ar0231_rev4.h
+new file mode 100644
+index 0000000..e18b96d
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/imagers/ar0231_rev4.h
+@@ -0,0 +1,344 @@
++/*
++ * ON Semiconductor AR0231 sensor camera wizard 1920x1080@30/BGGR/MIPI
++ *
++ * Copyright (C) 2018-2020 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++static const struct ar0231_reg ar0231_regs_wizard_rev4_dvp[] = {
++{0x301A, 0x0001}, // reset
++{0x301A, 0x10D8}, // Stream off and setup parallel
++{0x3070, 0x0000}, // 1: Solid color test pattern,
++ // 2: Full color bar test pattern,
++ // 3: Fade to grey color bar test pattern,
++ //256: Walking 1 test pattern (12 bit)
++{0x3072, 0x0123}, // R
++{0x3074, 0x0456}, // G(GR row)
++{0x3076, 0x0abc}, // B
++{0x3078, 0x0def}, // G(GB row)
++#ifdef AR0231_DISPLAY_PATTERN_FIXED
++{0x3070, 0x0001},
++#endif
++#ifdef AR0231_DISPLAY_PATTERN_COLOR_BAR
++{0x3070, 0x0002},
++#endif
++
++//Recommended Settings
++{0x3366, 0x6666}, // ANALOG_GAIN
++{0x3056, 0x0080}, // GREEN1_GAIN
++{0x305C, 0x0080}, // GREEN2_GAIN
++{0x3058, 0x0080}, // BLUE_GAIN
++{0x305A, 0x0080}, // RED_GAIN
++{0x3044, 0x0400}, // DARK_CONTROL
++{0x30BA, 0x1021}, // DIGITAL_CTRL
++{0x318E, 0x0200}, // DLO_CONTROL0
++{0x32EA, 0x3C0A}, // RESERVED_MFR_32EA
++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA
++{0x3362, 0x0000}, // DC_GAIN
++{0x3364, 0x0060}, // RESERVED_MFR_3364
++{0x3370, 0x0231}, // DBLC_CONTROL
++{0x3372, 0x700F}, // RESERVED_MFR_3372
++{0x3386, 0x0000}, // RESERVED_MFR_3386
++{0x3C04, 0x0E80}, // RESERVED_MFR_3C04
++{0x3F90, 0x06E1}, // TEMPVSENS0_TMG_CTRL
++{0x3F92, 0x06E1}, // TEMPVSENS1_TMG_CTRL
++{0x3502, 0x0808}, // RESERVED_MFR_3502
++{0x3502, 0x0808}, // RESERVED_MFR_3502
++{0x350E, 0xFF10}, // RESERVED_MFR_350E
++{0x3506, 0x4444}, // RESERVED_MFR_3506
++{0x3508, 0x4444}, // RESERVED_MFR_3508
++{0x350A, 0x4465}, // RESERVED_MFR_350A
++{0x350C, 0x055F}, // RESERVED_MFR_350C
++{0x3230, 0x0317}, // FINE_CORRECTION
++{0x3232, 0x0552}, // FINE_CORRECTION2
++{0x3234, 0x078D}, // FINE_CORRECTION3
++{0x3566, 0x9D38}, // RESERVED_MFR_3566
++{0x3518, 0x1FFE}, // RESERVED_MFR_3518
++{0x3520, 0xC688}, // RESERVED_MFR_3520
++{0x3522, 0x88C0}, // RESERVED_MFR_3522
++{0x3524, 0xC0C6}, // RESERVED_MFR_3524
++{0x352C, 0xC6C6}, // RESERVED_MFR_352C
++{0x3528, 0x0900}, // RESERVED_MFR_3528
++{0x3528, 0x9900}, // RESERVED_MFR_3528
++{0x3528, 0x9909}, // RESERVED_MFR_3528
++{0x3528, 0x9999}, // RESERVED_MFR_3528
++{0x352A, 0x081F}, // RESERVED_MFR_352A
++{0x352E, 0x0001}, // RESERVED_MFR_352E
++{0x352E, 0x0011}, // RESERVED_MFR_352E
++{0x3530, 0x0400}, // RESERVED_MFR_3530
++{0x3530, 0x4400}, // RESERVED_MFR_3530
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF02}, // RESERVED_MFR_3536
++{0x3536, 0xFF06}, // RESERVED_MFR_3536
++{0x3536, 0xFF06}, // RESERVED_MFR_3536
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x353A, 0x9000}, // RESERVED_MFR_353A
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
++{0x3540, 0xC637}, // RESERVED_MFR_3540
++{0x3540, 0xC637}, // RESERVED_MFR_3540
++{0x3540, 0xC637}, // RESERVED_MFR_3540
++{0x3542, 0x584B}, // RESERVED_MFR_3542
++{0x3542, 0x464B}, // RESERVED_MFR_3542
++{0x3544, 0x565A}, // RESERVED_MFR_3544
++{0x3544, 0x4B5A}, // RESERVED_MFR_3544
++{0x3546, 0x545A}, // RESERVED_MFR_3546
++{0x3546, 0x5A5A}, // RESERVED_MFR_3546
++{0x3548, 0x6430}, // RESERVED_MFR_3548
++{0x3556, 0x101F}, // RESERVED_MFR_3556
++{0x3566, 0x9D38}, // RESERVED_MFR_3566
++{0x3566, 0x1D38}, // RESERVED_MFR_3566
++{0x3566, 0x1D28}, // RESERVED_MFR_3566
++{0x3566, 0x1128}, // RESERVED_MFR_3566
++{0x3566, 0x1328}, // RESERVED_MFR_3566
++{0x3566, 0x3328}, // RESERVED_MFR_3566
++
++//Sequencer Update
++{0x2512, 0x8000}, // SEQ_CTRL_PORT
++{0x2510, 0x0905}, // SEQ_DATA_PORT
++{0x2510, 0x3350}, // SEQ_DATA_PORT
++{0x2510, 0x2004}, // SEQ_DATA_PORT
++{0x2510, 0x1460}, // SEQ_DATA_PORT
++{0x2510, 0x1578}, // SEQ_DATA_PORT
++{0x2510, 0x1360}, // SEQ_DATA_PORT
++{0x2510, 0x7B24}, // SEQ_DATA_PORT
++{0x2510, 0xFF24}, // SEQ_DATA_PORT
++{0x2510, 0xFF24}, // SEQ_DATA_PORT
++{0x2510, 0xEA24}, // SEQ_DATA_PORT
++{0x2510, 0x1022}, // SEQ_DATA_PORT
++{0x2510, 0x2410}, // SEQ_DATA_PORT
++{0x2510, 0x155A}, // SEQ_DATA_PORT
++{0x2510, 0x1342}, // SEQ_DATA_PORT
++{0x2510, 0x1400}, // SEQ_DATA_PORT
++{0x2510, 0x24FF}, // SEQ_DATA_PORT
++{0x2510, 0x24FF}, // SEQ_DATA_PORT
++{0x2510, 0x24EA}, // SEQ_DATA_PORT
++{0x2510, 0x2324}, // SEQ_DATA_PORT
++{0x2510, 0x647A}, // SEQ_DATA_PORT
++{0x2510, 0x2404}, // SEQ_DATA_PORT
++{0x2510, 0x052C}, // SEQ_DATA_PORT
++{0x2510, 0x400A}, // SEQ_DATA_PORT
++{0x2510, 0xFF0A}, // SEQ_DATA_PORT
++{0x2510, 0xFF0A}, // SEQ_DATA_PORT
++{0x2510, 0x0408}, // SEQ_DATA_PORT
++{0x2510, 0x3851}, // SEQ_DATA_PORT
++{0x2510, 0x1440}, // SEQ_DATA_PORT
++{0x2510, 0x0004}, // SEQ_DATA_PORT
++{0x2510, 0x0801}, // SEQ_DATA_PORT
++{0x2510, 0x0408}, // SEQ_DATA_PORT
++{0x2510, 0x1180}, // SEQ_DATA_PORT
++{0x2510, 0x15DC}, // SEQ_DATA_PORT
++{0x2510, 0x134C}, // SEQ_DATA_PORT
++{0x2510, 0x1002}, // SEQ_DATA_PORT
++{0x2510, 0x1016}, // SEQ_DATA_PORT
++{0x2510, 0x1181}, // SEQ_DATA_PORT
++{0x2510, 0x1189}, // SEQ_DATA_PORT
++{0x2510, 0x1056}, // SEQ_DATA_PORT
++{0x2510, 0x1210}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x0D08}, // SEQ_DATA_PORT
++{0x2510, 0x0913}, // SEQ_DATA_PORT
++{0x2510, 0x13C8}, // SEQ_DATA_PORT
++{0x2510, 0x092B}, // SEQ_DATA_PORT
++{0x2510, 0x1588}, // SEQ_DATA_PORT
++{0x2510, 0x1388}, // SEQ_DATA_PORT
++{0x2510, 0x090B}, // SEQ_DATA_PORT
++{0x2510, 0x11D9}, // SEQ_DATA_PORT
++{0x2510, 0x091D}, // SEQ_DATA_PORT
++{0x2510, 0x1441}, // SEQ_DATA_PORT
++{0x2510, 0x0903}, // SEQ_DATA_PORT
++{0x2510, 0x1214}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x10D6}, // SEQ_DATA_PORT
++{0x2510, 0x1210}, // SEQ_DATA_PORT
++{0x2510, 0x1212}, // SEQ_DATA_PORT
++{0x2510, 0x1210}, // SEQ_DATA_PORT
++{0x2510, 0x11DD}, // SEQ_DATA_PORT
++{0x2510, 0x11D9}, // SEQ_DATA_PORT
++{0x2510, 0x1056}, // SEQ_DATA_PORT
++{0x2510, 0x090B}, // SEQ_DATA_PORT
++{0x2510, 0x11DB}, // SEQ_DATA_PORT
++{0x2510, 0x0915}, // SEQ_DATA_PORT
++{0x2510, 0x119B}, // SEQ_DATA_PORT
++{0x2510, 0x090F}, // SEQ_DATA_PORT
++{0x2510, 0x11BB}, // SEQ_DATA_PORT
++{0x2510, 0x121A}, // SEQ_DATA_PORT
++{0x2510, 0x1210}, // SEQ_DATA_PORT
++{0x2510, 0x1460}, // SEQ_DATA_PORT
++{0x2510, 0x1250}, // SEQ_DATA_PORT
++{0x2510, 0x1076}, // SEQ_DATA_PORT
++{0x2510, 0x10E6}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x15AB}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x13A8}, // SEQ_DATA_PORT
++{0x2510, 0x1240}, // SEQ_DATA_PORT
++{0x2510, 0x1260}, // SEQ_DATA_PORT
++{0x2510, 0x0923}, // SEQ_DATA_PORT
++{0x2510, 0x158D}, // SEQ_DATA_PORT
++{0x2510, 0x138D}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x0B09}, // SEQ_DATA_PORT
++{0x2510, 0x0108}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x1440}, // SEQ_DATA_PORT
++{0x2510, 0x091D}, // SEQ_DATA_PORT
++{0x2510, 0x1588}, // SEQ_DATA_PORT
++{0x2510, 0x1388}, // SEQ_DATA_PORT
++{0x2510, 0x092D}, // SEQ_DATA_PORT
++{0x2510, 0x1066}, // SEQ_DATA_PORT
++{0x2510, 0x0905}, // SEQ_DATA_PORT
++{0x2510, 0x0C08}, // SEQ_DATA_PORT
++{0x2510, 0x090B}, // SEQ_DATA_PORT
++{0x2510, 0x1441}, // SEQ_DATA_PORT
++{0x2510, 0x090D}, // SEQ_DATA_PORT
++{0x2510, 0x10E6}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x1262}, // SEQ_DATA_PORT
++{0x2510, 0x1260}, // SEQ_DATA_PORT
++{0x2510, 0x11BF}, // SEQ_DATA_PORT
++{0x2510, 0x11BB}, // SEQ_DATA_PORT
++{0x2510, 0x1066}, // SEQ_DATA_PORT
++{0x2510, 0x11FB}, // SEQ_DATA_PORT
++{0x2510, 0x0935}, // SEQ_DATA_PORT
++{0x2510, 0x11BB}, // SEQ_DATA_PORT
++{0x2510, 0x1263}, // SEQ_DATA_PORT
++{0x2510, 0x1260}, // SEQ_DATA_PORT
++{0x2510, 0x1400}, // SEQ_DATA_PORT
++{0x2510, 0x1510}, // SEQ_DATA_PORT
++{0x2510, 0x11B8}, // SEQ_DATA_PORT
++{0x2510, 0x12A0}, // SEQ_DATA_PORT
++{0x2510, 0x1200}, // SEQ_DATA_PORT
++{0x2510, 0x1026}, // SEQ_DATA_PORT
++{0x2510, 0x1000}, // SEQ_DATA_PORT
++{0x2510, 0x1342}, // SEQ_DATA_PORT
++{0x2510, 0x1100}, // SEQ_DATA_PORT
++{0x2510, 0x7A06}, // SEQ_DATA_PORT
++{0x2510, 0x0926}, // SEQ_DATA_PORT
++{0x2510, 0x0507}, // SEQ_DATA_PORT
++{0x2510, 0x0841}, // SEQ_DATA_PORT
++{0x2510, 0x3750}, // SEQ_DATA_PORT
++{0x2510, 0x2C2C}, // SEQ_DATA_PORT
++{0x2510, 0xFE02}, // SEQ_DATA_PORT
++{0x2510, 0xFE14}, // SEQ_DATA_PORT
++{0x3566, 0x3328}, // RESERVED_MFR_3566
++{0x350C, 0x055F}, // RESERVED_MFR_350C
++{0x32D0, 0x3A02}, // RESERVED_MFR_32D0
++{0x32D2, 0x3508}, // RESERVED_MFR_32D2
++{0x32D4, 0x3702}, // RESERVED_MFR_32D4
++{0x32D6, 0x3C04}, // RESERVED_MFR_32D6
++{0x32DC, 0x370A}, // RESERVED_MFR_32DC
++
++//Parallel Timing Setup
++{0x302A, 0x0009}, // VT_PIX_CLK_DIV
++{0x302C, 0x0001}, // VT_SYS_CLK_DIV
++{0x302E, 0x0003}, // PRE_PLL_CLK_DIV
++{0x3030, 0x0058}, // PLL_MULTIPLIER
++{0x3036, 0x0008}, // OP_WORD_CLK_DIV
++{0x3038, 0x0001}, // OP_SYS_CLK_DIV
++{0x30B0, 0x0A00}, // DIGITAL_TEST
++
++//Readout Mode Configuration
++{0x30A2, 0x0001}, // X_ODD_INC_
++{0x30A6, 0x0001}, // Y_ODD_INC_
++{0x3040, 0x0000}, // READ_MODE
++{0x3044, 0x0400}, // DARK_CONTROL
++#ifdef AR0231_EMBEDDED_LINE
++{0x3064, 0x1982}, // SMIA_TEST
++#else
++{0x3064, 0x1802}, // SMIA_TEST
++#endif
++{0x33E0, 0x0880}, // RESERVED_MFR_33E0
++{0x3180, 0x0080}, // RESERVED_MFR_3180
++{0x33E4, 0x0080}, // RESERVED_MFR_33E4
++
++#if 1
++{0x3004, AR0231_X_START}, // X_ADDR_START_
++{0x3008, AR0231_X_END}, // X_ADDR_END_
++{0x3002, AR0231_Y_START}, // Y_ADDR_START_
++{0x3006, AR0231_Y_END}, // Y_ADDR_END_
++{0x3402, 0x0000 | AR0231_MAX_WIDTH}, // X_OUTPUT_CONTROL
++{0x3404, 0x0000 | AR0231_MAX_HEIGHT}, // Y_OUTPUT_CONTROL
++#else
++{0x3004, 0}, // X_ADDR_START_
++{0x3008, 0x0787}, // X_ADDR_END_
++{0x3002, 0x0000}, // Y_ADDR_START_
++{0x3006, 0x04B7}, // Y_ADDR_END_
++{0x3402, 0x0788}, // RESERVED_MFR_3402
++{0x3402, 0x0F10}, // RESERVED_MFR_3402
++{0x3404, 0x0440}, // RESERVED_MFR_3404
++{0x3404, 0x0970}, // RESERVED_MFR_3404
++#endif
++{0x3032, 0x0000}, // SCALING_MODE
++{0x3400, 0x0010}, // RESERVED_MFR_3400
++
++//3exp Timing and Exposure
++{0x3082, 0x0008}, // OPERATION_MODE_CTRL
++{0x30BA, 0x11E2}, // DIGITAL_CTRL
++{0x300A, 0x05AF}, // FRAME_LENGTH_LINES_
++{0x300C, 0x07BA}, // LINE_LENGTH_PCK_
++{0x3042, 0x0000}, // EXTRA_DELAY
++{0x3238, 0x0222}, // EXPOSURE_RATIO
++{0x1008, 0x0374}, // FINE_INTEGRATION_TIME_MIN
++{0x100C, 0x05AF}, // FINE_INTEGRATION_TIME2_MIN
++{0x100E, 0x07EA}, // FINE_INTEGRATION_TIME3_MIN
++{0x1010, 0x0139}, // FINE_INTEGRATION_TIME4_MIN
++{0x3012, 0x0163}, // COARSE_INTEGRATION_TIME_
++{0x3014, 0x06A6}, // FINE_INTEGRATION_TIME_
++{0x321E, 0x06A6}, // FINE_INTEGRATION_TIME2
++{0x3222, 0x06A6}, // FINE_INTEGRATION_TIME3
++{0x30B0, 0x0B02}, // DIGITAL_TEST
++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA
++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
++
++//Parallel HDR 12 bit Output
++{0x31D0, 0x0001}, // COMPANDING
++{0x31AE, 0x0001}, // SERIAL_FORMAT
++{0x31AC, 0x140C}, // DATA_FORMAT_BITS
++
++#if 0 // no need for front only camera
++/* Enable trigger input */
++{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO1 is trigger
++{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO1 is trigger
++{0x30CE, 0x0120}, // TRIGGER_MODE
++//{0x30DC, 0x0120}, // TRIGGER_DELAY
++{0x301A, 0x01D8}, // GPI pins enable
++#endif
++
++{0x301A, 0x01DC}, // RESET_REGISTER - stream on
++
++#if 1
++{0x300A, AR0231_SENSOR_HEIGHT + 225}, // FRAME_LENGTH_LINES_
++{0x300C, AR0231_SENSOR_WIDTH + 120}, // LINE_LENGTH_PCK_
++/* the sequence must be updated to use following timings, now it is a hack */
++{0x1008, 0x0fff}, // FINE_INTEGRATION_TIME_MIN
++{0x100C, 0x0fff}, // FINE_INTEGRATION_TIME2_MIN
++{0x100E, 0x0fff}, // FINE_INTEGRATION_TIME3_MIN
++{0x1010, 0x0fff}, // FINE_INTEGRATION_TIME4_MIN
++#endif
++};
+diff --git a/drivers/media/i2c/soc_camera/imagers/ar0231_rev6.h b/drivers/media/i2c/soc_camera/imagers/ar0231_rev6.h
+new file mode 100644
+index 0000000..b5b8cb2
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/imagers/ar0231_rev6.h
+@@ -0,0 +1,343 @@
++/*
++ * ON Semiconductor AR0231 sensor camera wizard 1920x1080@30/BGGR/MIPI
++ *
++ * Copyright (C) 2018-2020 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++/* Parallel Timing Setup 27MHz In 88 MHz Out */
++static const struct ar0231_reg ar0231_regs_wizard_rev6_dvp[] = {
++{0x301A, 0x0001}, // reset
++{0x301A, 0x10D8}, // Stream off and setup parallel
++{0x3070, 0x0000}, // 1: Solid color test pattern,
++ // 2: Full color bar test pattern,
++ // 3: Fade to grey color bar test pattern,
++ //256: Walking 1 test pattern (12 bit)
++{0x3072, 0x0123}, // R
++{0x3074, 0x0456}, // G(GR row)
++{0x3076, 0x0abc}, // B
++{0x3078, 0x0def}, // G(GB row)
++#ifdef AR0231_DISPLAY_PATTERN_FIXED
++{0x3070, 0x0001},
++#endif
++#ifdef AR0231_DISPLAY_PATTERN_COLOR_BAR
++{0x3070, 0x0002},
++#endif
++
++//Recommended Settings
++{0x3056, 0x0080}, // GREEN1_GAIN
++{0x305C, 0x0080}, // GREEN2_GAIN
++{0x3058, 0x0080}, // BLUE_GAIN
++{0x305A, 0x0080}, // RED_GAIN
++{0x3138, 0x000B}, // OTPM_TCFG_OPT
++{0x3372, 0xF54F}, // RESERVED_MFR_3372
++{0x337A, 0x0D70}, // RESERVED_MFR_337A
++{0x337E, 0x1FFD}, // RESERVED_MFR_337E
++{0x3382, 0x00C0}, // RESERVED_MFR_3382
++{0x3C04, 0x0E80}, // RESERVED_MFR_3C04
++{0x3F90, 0x06E1}, // RESERVED_MFR_3F90
++{0x3F92, 0x06E1}, // RESERVED_MFR_3F92
++{0x350E, 0x1F14}, // RESERVED_MFR_350E
++{0x350E, 0xFF10}, // RESERVED_MFR_350E
++{0x3506, 0x4444}, // RESERVED_MFR_3506
++{0x3508, 0x4444}, // RESERVED_MFR_3508
++{0x350A, 0x4465}, // RESERVED_MFR_350A
++{0x350C, 0x055F}, // RESERVED_MFR_350C
++{0x3566, 0x9D38}, // RESERVED_MFR_3566
++{0x3518, 0x1FFE}, // RESERVED_MFR_3518
++{0x3520, 0xC688}, // RESERVED_MFR_3520
++{0x3522, 0x88C0}, // RESERVED_MFR_3522
++{0x3524, 0xC0C6}, // RESERVED_MFR_3524
++{0x352C, 0xC6C6}, // RESERVED_MFR_352C
++{0x3528, 0x0900}, // RESERVED_MFR_3528
++{0x3528, 0x9900}, // RESERVED_MFR_3528
++{0x3528, 0x9909}, // RESERVED_MFR_3528
++{0x3528, 0x9999}, // RESERVED_MFR_3528
++{0x352A, 0x089F}, // RESERVED_MFR_352A
++{0x352E, 0x0001}, // RESERVED_MFR_352E
++{0x352E, 0x0011}, // RESERVED_MFR_352E
++{0x3530, 0x0400}, // RESERVED_MFR_3530
++{0x3530, 0x4400}, // RESERVED_MFR_3530
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF00}, // RESERVED_MFR_3536
++{0x3536, 0xFF02}, // RESERVED_MFR_3536
++{0x3536, 0xFF06}, // RESERVED_MFR_3536
++{0x3536, 0xFF06}, // RESERVED_MFR_3536
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x3538, 0xFFFF}, // RESERVED_MFR_3538
++{0x353A, 0x9000}, // RESERVED_MFR_353A
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x353C, 0x3F00}, // RESERVED_MFR_353C
++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
++{0x3540, 0xC637}, // RESERVED_MFR_3540
++{0x3540, 0xC637}, // RESERVED_MFR_3540
++{0x3540, 0xC637}, // RESERVED_MFR_3540
++{0x3542, 0x584B}, // RESERVED_MFR_3542
++{0x3542, 0x464B}, // RESERVED_MFR_3542
++{0x3544, 0x565A}, // RESERVED_MFR_3544
++{0x3544, 0x4B5A}, // RESERVED_MFR_3544
++{0x3546, 0x545A}, // RESERVED_MFR_3546
++{0x3546, 0x5A5A}, // RESERVED_MFR_3546
++{0x3548, 0x6400}, // RESERVED_MFR_3548
++{0x3556, 0x101F}, // RESERVED_MFR_3556
++{0x3566, 0x9D38}, // RESERVED_MFR_3566
++{0x3566, 0x1D38}, // RESERVED_MFR_3566
++{0x3566, 0x1D28}, // RESERVED_MFR_3566
++{0x3566, 0x1128}, // RESERVED_MFR_3566
++{0x3566, 0x1328}, // RESERVED_MFR_3566
++{0x3566, 0x3328}, // RESERVED_MFR_3566
++{0x3528, 0xDDDD}, // RESERVED_MFR_3528
++
++//Sequencer Update
++{0x2512, 0x8000}, // SEQ_CTRL_PORT
++{0x2510, 0x0905}, // SEQ_DATA_PORT
++{0x2510, 0x3350}, // SEQ_DATA_PORT
++{0x2510, 0x2004}, // SEQ_DATA_PORT
++{0x2510, 0x1460}, // SEQ_DATA_PORT
++{0x2510, 0x1578}, // SEQ_DATA_PORT
++{0x2510, 0x1360}, // SEQ_DATA_PORT
++{0x2510, 0x7B24}, // SEQ_DATA_PORT
++{0x2510, 0xFF24}, // SEQ_DATA_PORT
++{0x2510, 0xFF24}, // SEQ_DATA_PORT
++{0x2510, 0xEA24}, // SEQ_DATA_PORT
++{0x2510, 0x1022}, // SEQ_DATA_PORT
++{0x2510, 0x2410}, // SEQ_DATA_PORT
++{0x2510, 0x155A}, // SEQ_DATA_PORT
++{0x2510, 0x1342}, // SEQ_DATA_PORT
++{0x2510, 0x1400}, // SEQ_DATA_PORT
++{0x2510, 0x24FF}, // SEQ_DATA_PORT
++{0x2510, 0x24FF}, // SEQ_DATA_PORT
++{0x2510, 0x24EA}, // SEQ_DATA_PORT
++{0x2510, 0x2324}, // SEQ_DATA_PORT
++{0x2510, 0x647A}, // SEQ_DATA_PORT
++{0x2510, 0x2404}, // SEQ_DATA_PORT
++{0x2510, 0x052C}, // SEQ_DATA_PORT
++{0x2510, 0x400A}, // SEQ_DATA_PORT
++{0x2510, 0xFF0A}, // SEQ_DATA_PORT
++{0x2510, 0xFF0A}, // SEQ_DATA_PORT
++{0x2510, 0x1808}, // SEQ_DATA_PORT
++{0x2510, 0x3851}, // SEQ_DATA_PORT
++{0x2510, 0x1440}, // SEQ_DATA_PORT
++{0x2510, 0x0004}, // SEQ_DATA_PORT
++{0x2510, 0x0801}, // SEQ_DATA_PORT
++{0x2510, 0x0408}, // SEQ_DATA_PORT
++{0x2510, 0x1180}, // SEQ_DATA_PORT
++{0x2510, 0x15DC}, // SEQ_DATA_PORT
++{0x2510, 0x134C}, // SEQ_DATA_PORT
++{0x2510, 0x1002}, // SEQ_DATA_PORT
++{0x2510, 0x1016}, // SEQ_DATA_PORT
++{0x2510, 0x1181}, // SEQ_DATA_PORT
++{0x2510, 0x1189}, // SEQ_DATA_PORT
++{0x2510, 0x1056}, // SEQ_DATA_PORT
++{0x2510, 0x1210}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x0D08}, // SEQ_DATA_PORT
++{0x2510, 0x0913}, // SEQ_DATA_PORT
++{0x2510, 0x13C8}, // SEQ_DATA_PORT
++{0x2510, 0x092B}, // SEQ_DATA_PORT
++{0x2510, 0x1588}, // SEQ_DATA_PORT
++{0x2510, 0x1388}, // SEQ_DATA_PORT
++{0x2510, 0x090B}, // SEQ_DATA_PORT
++{0x2510, 0x11D9}, // SEQ_DATA_PORT
++{0x2510, 0x091D}, // SEQ_DATA_PORT
++{0x2510, 0x1441}, // SEQ_DATA_PORT
++{0x2510, 0x0903}, // SEQ_DATA_PORT
++{0x2510, 0x1214}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x10D6}, // SEQ_DATA_PORT
++{0x2510, 0x1210}, // SEQ_DATA_PORT
++{0x2510, 0x1212}, // SEQ_DATA_PORT
++{0x2510, 0x1210}, // SEQ_DATA_PORT
++{0x2510, 0x11DD}, // SEQ_DATA_PORT
++{0x2510, 0x11D9}, // SEQ_DATA_PORT
++{0x2510, 0x1056}, // SEQ_DATA_PORT
++{0x2510, 0x090B}, // SEQ_DATA_PORT
++{0x2510, 0x11DB}, // SEQ_DATA_PORT
++{0x2510, 0x0915}, // SEQ_DATA_PORT
++{0x2510, 0x119B}, // SEQ_DATA_PORT
++{0x2510, 0x090F}, // SEQ_DATA_PORT
++{0x2510, 0x11BB}, // SEQ_DATA_PORT
++{0x2510, 0x121A}, // SEQ_DATA_PORT
++{0x2510, 0x1210}, // SEQ_DATA_PORT
++{0x2510, 0x1460}, // SEQ_DATA_PORT
++{0x2510, 0x1250}, // SEQ_DATA_PORT
++{0x2510, 0x1076}, // SEQ_DATA_PORT
++{0x2510, 0x10E6}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x15AB}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x13A8}, // SEQ_DATA_PORT
++{0x2510, 0x1240}, // SEQ_DATA_PORT
++{0x2510, 0x1260}, // SEQ_DATA_PORT
++{0x2510, 0x0923}, // SEQ_DATA_PORT
++{0x2510, 0x158D}, // SEQ_DATA_PORT
++{0x2510, 0x138D}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x0B09}, // SEQ_DATA_PORT
++{0x2510, 0x0108}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x1440}, // SEQ_DATA_PORT
++{0x2510, 0x091D}, // SEQ_DATA_PORT
++{0x2510, 0x1588}, // SEQ_DATA_PORT
++{0x2510, 0x1388}, // SEQ_DATA_PORT
++{0x2510, 0x092D}, // SEQ_DATA_PORT
++{0x2510, 0x1066}, // SEQ_DATA_PORT
++{0x2510, 0x0905}, // SEQ_DATA_PORT
++{0x2510, 0x0C08}, // SEQ_DATA_PORT
++{0x2510, 0x090B}, // SEQ_DATA_PORT
++{0x2510, 0x1441}, // SEQ_DATA_PORT
++{0x2510, 0x090D}, // SEQ_DATA_PORT
++{0x2510, 0x10E6}, // SEQ_DATA_PORT
++{0x2510, 0x0901}, // SEQ_DATA_PORT
++{0x2510, 0x1262}, // SEQ_DATA_PORT
++{0x2510, 0x1260}, // SEQ_DATA_PORT
++{0x2510, 0x11BF}, // SEQ_DATA_PORT
++{0x2510, 0x11BB}, // SEQ_DATA_PORT
++{0x2510, 0x1066}, // SEQ_DATA_PORT
++{0x2510, 0x11FB}, // SEQ_DATA_PORT
++{0x2510, 0x0935}, // SEQ_DATA_PORT
++{0x2510, 0x11BB}, // SEQ_DATA_PORT
++{0x2510, 0x1263}, // SEQ_DATA_PORT
++{0x2510, 0x1260}, // SEQ_DATA_PORT
++{0x2510, 0x1400}, // SEQ_DATA_PORT
++{0x2510, 0x1510}, // SEQ_DATA_PORT
++{0x2510, 0x11B8}, // SEQ_DATA_PORT
++{0x2510, 0x12A0}, // SEQ_DATA_PORT
++{0x2510, 0x1200}, // SEQ_DATA_PORT
++{0x2510, 0x1026}, // SEQ_DATA_PORT
++{0x2510, 0x1000}, // SEQ_DATA_PORT
++{0x2510, 0x1342}, // SEQ_DATA_PORT
++{0x2510, 0x1100}, // SEQ_DATA_PORT
++{0x2510, 0x7A06}, // SEQ_DATA_PORT
++{0x2510, 0x0915}, // SEQ_DATA_PORT
++{0x2510, 0x0507}, // SEQ_DATA_PORT
++{0x2510, 0x0841}, // SEQ_DATA_PORT
++{0x2510, 0x3750}, // SEQ_DATA_PORT
++{0x2510, 0x2C2C}, // SEQ_DATA_PORT
++{0x2510, 0xFE05}, // SEQ_DATA_PORT
++{0x2510, 0xFE13}, // SEQ_DATA_PORT
++{0x1008, 0x0361}, // FINE_INTEGRATION_TIME_MIN
++{0x100C, 0x0589}, // FINE_INTEGRATION_TIME2_MIN
++{0x100E, 0x07B1}, // FINE_INTEGRATION_TIME3_MIN
++{0x1010, 0x0139}, // FINE_INTEGRATION_TIME4_MIN
++{0x3230, 0x0304}, // FINE_CORRECTION
++{0x3232, 0x052C}, // FINE_CORRECTION2
++{0x3234, 0x0754}, // FINE_CORRECTION3
++{0x3236, 0x00DC}, // FINE_CORRECTION4
++{0x3566, 0x3328}, // RESERVED_MFR_3566
++{0x350C, 0x055F}, // RESERVED_MFR_350C
++{0x32D0, 0x3A02}, // RESERVED_MFR_32D0
++{0x32D2, 0x3508}, // RESERVED_MFR_32D2
++{0x32D4, 0x3702}, // RESERVED_MFR_32D4
++{0x32D6, 0x3C04}, // RESERVED_MFR_32D6
++{0x32DC, 0x370A}, // RESERVED_MFR_32DC
++
++//Parallel Timing Setup 27MHz In 88 MHz Out
++{0x302A, 0x0009}, // VT_PIX_CLK_DIV
++{0x302C, 0x0001}, // VT_SYS_CLK_DIV
++{0x302E, 0x0003}, // PRE_PLL_CLK_DIV
++{0x3030, 0x0058}, // PLL_MULTIPLIER
++{0x3036, 0x0008}, // OP_WORD_CLK_DIV
++{0x3038, 0x0001}, // OP_SYS_CLK_DIV
++{0x30B0, 0x0B02}, // DIGITAL_TEST
++
++//Readout Mode Configuration
++{0x30A2, 0x0001}, // X_ODD_INC_
++{0x30A6, 0x0001}, // Y_ODD_INC_
++{0x3040, 0x0000}, // READ_MODE
++{0x3082, 0x0008}, // OPERATION_MODE_CTRL
++{0x30BA, 0x11E2}, // DIGITAL_CTRL
++{0x3044, 0x0400}, // DARK_CONTROL
++#ifdef AR0231_EMBEDDED_LINE
++{0x3064, 0x1982}, // SMIA_TEST
++#else
++{0x3064, 0x1802}, // SMIA_TEST
++#endif
++{0x33E0, 0x0880}, // RESERVED_MFR_33E0
++{0x3180, 0x0080}, // RESERVED_MFR_3180
++{0x33E4, 0x0080}, // RESERVED_MFR_33E4
++{0x33E0, 0x0C80}, // RESERVED_MFR_33E0
++
++#if 1
++{0x3004, AR0231_X_START}, // X_ADDR_START_
++{0x3008, AR0231_X_END}, // X_ADDR_END_
++{0x3002, AR0231_Y_START}, // Y_ADDR_START_
++{0x3006, AR0231_Y_END}, // Y_ADDR_END_
++{0x3402, 0x0000 | AR0231_MAX_WIDTH}, // X_OUTPUT_CONTROL
++{0x3404, 0x0000 | AR0231_MAX_HEIGHT}, // Y_OUTPUT_CONTROL
++#else
++{0x3004, 0}, // X_ADDR_START_
++{0x3008, 0x0787}, // X_ADDR_END_
++{0x3002, 0x0000}, // Y_ADDR_START_
++{0x3006, 0x04B7}, // Y_ADDR_END_
++{0x3402, 0x0788}, // RESERVED_MFR_3402
++{0x3402, 0x0F10}, // RESERVED_MFR_3402
++{0x3404, 0x0440}, // RESERVED_MFR_3404
++{0x3404, 0x0970}, // RESERVED_MFR_3404
++#endif
++{0x3032, 0x0000}, // SCALING_MODE
++{0x3400, 0x0010}, // RESERVED_MFR_3400
++
++//3exp Timing and Exposure
++{0x3082, 0x0008}, // OPERATION_MODE_CTRL
++{0x30BA, 0x11E2}, // DIGITAL_CTRL
++{0x300A, 0x05CA}, // FRAME_LENGTH_LINES_
++{0x300C, 0x07BA}, // LINE_LENGTH_PCK_
++{0x3042, 0x0000}, // EXTRA_DELAY
++{0x3238, 0x0222}, // EXPOSURE_RATIO
++{0x3012, 0x0163}, // COARSE_INTEGRATION_TIME_
++{0x3014, 0x08CC}, // FINE_INTEGRATION_TIME_
++{0x321E, 0x08CC}, // FINE_INTEGRATION_TIME2
++{0x3222, 0x0254}, // FINE_INTEGRATION_TIME3
++{0x30B0, 0x0A00}, // DIGITAL_TEST
++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA
++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
++
++//Parallel HDR 12 bit Output
++{0x31D0, 0x0001}, // COMPANDING
++{0x31AE, 0x0001}, // SERIAL_FORMAT
++{0x31AC, 0x140C}, // DATA_FORMAT_BITS
++
++#if 0 // no need for front only camera
++/* Enable trigger input */
++{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO1 is trigger
++{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO1 is trigger
++{0x30CE, 0x0120}, // TRIGGER_MODE
++//{0x30DC, 0x0120}, // TRIGGER_DELAY
++{0x301A, 0x01D8}, // GPI pins enable
++#endif
++
++{0x301A, 0x01DC}, // RESET_REGISTER - stream on
++
++#if 1
++{0x300A, AR0231_SENSOR_HEIGHT + 225}, // FRAME_LENGTH_LINES_
++{0x300C, AR0231_SENSOR_WIDTH + 120}, // LINE_LENGTH_PCK_
++/* the sequence must be updated to use following timings, now it is a hack */
++{0x1008, 0x0fff}, // FINE_INTEGRATION_TIME_MIN
++{0x100C, 0x0fff}, // FINE_INTEGRATION_TIME2_MIN
++{0x100E, 0x0fff}, // FINE_INTEGRATION_TIME3_MIN
++{0x1010, 0x0fff}, // FINE_INTEGRATION_TIME4_MIN
++#endif
++};
+diff --git a/drivers/media/i2c/soc_camera/imagers/ar0231_rev7.h b/drivers/media/i2c/soc_camera/imagers/ar0231_rev7.h
+new file mode 100644
+index 0000000..f3485f5
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/imagers/ar0231_rev7.h
+@@ -0,0 +1,445 @@
++/*
++ * ON Semiconductor AR0231 sensor camera wizard 1928x1208@30/BGGR/MIPI
++ *
++ * Copyright (C) 2018-2020 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++/* 3Exp HDR Full Resolution Mode MIPI 4lane 12bit 30FPS, XCLK=27MHz */
++static const struct ar0231_reg ar0231_regs_wizard_rev7[] = {
++{0x301A, 0x18}, // MIPI, stream OFF
++{AR0231_DELAY, 200}, // Wait 200ms
++
++{0x3070, 0x0000}, // 1: Solid color test pattern,
++ // 2: Full color bar test pattern,
++ // 3: Fade to grey color bar test pattern,
++ //256: Walking 1 test pattern (12 bit)
++{0x3072, 0x0123}, // R
++{0x3074, 0x0456}, // G(GR row)
++{0x3076, 0x0abc}, // B
++{0x3078, 0x0def}, // G(GB row)
++#ifdef AR0231_DISPLAY_PATTERN_FIXED
++{0x3070, 0x0001},
++#endif
++#ifdef AR0231_DISPLAY_PATTERN_COLOR_BAR
++{0x3070, 0x0002},
++#endif
++{AR0231_DELAY, 100}, // Wait 100ms
++
++#if 1 /* Sensor Setup */
++#if 1 /* Recommended Settings */
++{0x3092, 0x0C24},
++{0x337A, 0x0C80},
++{0x3520, 0x1288},
++{0x3522, 0x880C},
++{0x3524, 0x0C12},
++{0x352C, 0x1212},
++{0x354A, 0x007F},
++{0x350C, 0x055C},
++{0x3506, 0x3333},
++{0x3508, 0x3333},
++{0x3100, 0x4000},
++{0x3280, 0x0FA0},
++{0x3282, 0x0FA0},
++{0x3284, 0x0FA0},
++{0x3286, 0x0FA0},
++{0x3288, 0x0FA0},
++{0x328A, 0x0FA0},
++{0x328C, 0x0FA0},
++{0x328E, 0x0FA0},
++{0x3290, 0x0FA0},
++{0x3292, 0x0FA0},
++{0x3294, 0x0FA0},
++{0x3296, 0x0FA0},
++{0x3298, 0x0FA0},
++{0x329A, 0x0FA0},
++{0x329C, 0x0FA0},
++{0x329E, 0x0FA0},
++#endif /* Recommended Settings */
++
++#if 1 /* Sequencer Update */
++{0x2512, 0x8000},
++{0x2510, 0x0905},
++{0x2510, 0x3350},
++{0x2510, 0x2004},
++{0x2510, 0x1460},
++{0x2510, 0x1578},
++{0x2510, 0x0901},
++{0x2510, 0x7B24},
++{0x2510, 0xFF24},
++{0x2510, 0xFF24},
++{0x2510, 0xEA24},
++{0x2510, 0x1022},
++{0x2510, 0x2410},
++{0x2510, 0x155A},
++{0x2510, 0x0901},
++{0x2510, 0x1400},
++{0x2510, 0x24FF},
++{0x2510, 0x24FF},
++{0x2510, 0x24EA},
++{0x2510, 0x2324},
++{0x2510, 0x647A},
++{0x2510, 0x2404},
++{0x2510, 0x052C},
++{0x2510, 0x400A},
++{0x2510, 0xFF0A},
++{0x2510, 0xFF0A},
++{0x2510, 0x1008},
++{0x2510, 0x3851},
++{0x2510, 0x1440},
++{0x2510, 0x0004},
++{0x2510, 0x0801},
++{0x2510, 0x0408},
++{0x2510, 0x1180},
++{0x2510, 0x2652},
++{0x2510, 0x1518},
++{0x2510, 0x0906},
++{0x2510, 0x1348},
++{0x2510, 0x1002},
++{0x2510, 0x1016},
++{0x2510, 0x1181},
++{0x2510, 0x1189},
++{0x2510, 0x1056},
++{0x2510, 0x1210},
++{0x2510, 0x0901},
++{0x2510, 0x0D09},
++{0x2510, 0x1413},
++{0x2510, 0x8809},
++{0x2510, 0x2B15},
++{0x2510, 0x8809},
++{0x2510, 0x0311},
++{0x2510, 0xD909},
++{0x2510, 0x1214},
++{0x2510, 0x4109},
++{0x2510, 0x0312},
++{0x2510, 0x1409},
++{0x2510, 0x0110},
++{0x2510, 0xD612},
++{0x2510, 0x1012},
++{0x2510, 0x1212},
++{0x2510, 0x1011},
++{0x2510, 0xDD11},
++{0x2510, 0xD910},
++{0x2510, 0x5609},
++{0x2510, 0x1511},
++{0x2510, 0xDB09},
++{0x2510, 0x1511},
++{0x2510, 0x9B09},
++{0x2510, 0x0F11},
++{0x2510, 0xBB12},
++{0x2510, 0x1A12},
++{0x2510, 0x1014},
++{0x2510, 0x6012},
++{0x2510, 0x5010},
++{0x2510, 0x7610},
++{0x2510, 0xE609},
++{0x2510, 0x0812},
++{0x2510, 0x4012},
++{0x2510, 0x6009},
++{0x2510, 0x290B},
++{0x2510, 0x0904},
++{0x2510, 0x1440},
++{0x2510, 0x0923},
++{0x2510, 0x15C8},
++{0x2510, 0x13C8},
++{0x2510, 0x092C},
++{0x2510, 0x1588},
++{0x2510, 0x1388},
++{0x2510, 0x0C09},
++{0x2510, 0x0C14},
++{0x2510, 0x4109},
++{0x2510, 0x1112},
++{0x2510, 0x6212},
++{0x2510, 0x6011},
++{0x2510, 0xBF11},
++{0x2510, 0xBB10},
++{0x2510, 0x6611},
++{0x2510, 0xFB09},
++{0x2510, 0x3511},
++{0x2510, 0xBB12},
++{0x2510, 0x6312},
++{0x2510, 0x6014},
++{0x2510, 0x0015},
++{0x2510, 0x0011},
++{0x2510, 0xB812},
++{0x2510, 0xA012},
++{0x2510, 0x0010},
++{0x2510, 0x2610},
++{0x2510, 0x0013},
++{0x2510, 0x0011},
++{0x2510, 0x0008},
++{0x2510, 0x3053},
++{0x2510, 0x4215},
++{0x2510, 0x4013},
++{0x2510, 0x4010},
++{0x2510, 0x0210},
++{0x2510, 0x1611},
++{0x2510, 0x8111},
++{0x2510, 0x8910},
++{0x2510, 0x5612},
++{0x2510, 0x1009},
++{0x2510, 0x010D},
++{0x2510, 0x0815},
++{0x2510, 0xC015},
++{0x2510, 0xD013},
++{0x2510, 0x5009},
++{0x2510, 0x1313},
++{0x2510, 0xD009},
++{0x2510, 0x0215},
++{0x2510, 0xC015},
++{0x2510, 0xC813},
++{0x2510, 0xC009},
++{0x2510, 0x0515},
++{0x2510, 0x8813},
++{0x2510, 0x8009},
++{0x2510, 0x0213},
++{0x2510, 0x8809},
++{0x2510, 0x0411},
++{0x2510, 0xC909},
++{0x2510, 0x0814},
++{0x2510, 0x0109},
++{0x2510, 0x0B11},
++{0x2510, 0xD908},
++{0x2510, 0x1400},
++{0x2510, 0x091A},
++{0x2510, 0x1440},
++{0x2510, 0x0903},
++{0x2510, 0x1214},
++{0x2510, 0x0901},
++{0x2510, 0x10D6},
++{0x2510, 0x1210},
++{0x2510, 0x1212},
++{0x2510, 0x1210},
++{0x2510, 0x11DD},
++{0x2510, 0x11D9},
++{0x2510, 0x1056},
++{0x2510, 0x0917},
++{0x2510, 0x11DB},
++{0x2510, 0x0913},
++{0x2510, 0x11FB},
++{0x2510, 0x0905},
++{0x2510, 0x11BB},
++{0x2510, 0x121A},
++{0x2510, 0x1210},
++{0x2510, 0x1460},
++{0x2510, 0x1250},
++{0x2510, 0x1076},
++{0x2510, 0x10E6},
++{0x2510, 0x0901},
++{0x2510, 0x15A8},
++{0x2510, 0x0901},
++{0x2510, 0x13A8},
++{0x2510, 0x1240},
++{0x2510, 0x1260},
++{0x2510, 0x0925},
++{0x2510, 0x13AD},
++{0x2510, 0x0902},
++{0x2510, 0x0907},
++{0x2510, 0x1588},
++{0x2510, 0x0901},
++{0x2510, 0x138D},
++{0x2510, 0x0B09},
++{0x2510, 0x0914},
++{0x2510, 0x4009},
++{0x2510, 0x0B13},
++{0x2510, 0x8809},
++{0x2510, 0x1C0C},
++{0x2510, 0x0920},
++{0x2510, 0x1262},
++{0x2510, 0x1260},
++{0x2510, 0x11BF},
++{0x2510, 0x11BB},
++{0x2510, 0x1066},
++{0x2510, 0x090A},
++{0x2510, 0x11FB},
++{0x2510, 0x093B},
++{0x2510, 0x11BB},
++{0x2510, 0x1263},
++{0x2510, 0x1260},
++{0x2510, 0x1400},
++{0x2510, 0x1508},
++{0x2510, 0x11B8},
++{0x2510, 0x12A0},
++{0x2510, 0x1200},
++{0x2510, 0x1026},
++{0x2510, 0x1000},
++{0x2510, 0x1300},
++{0x2510, 0x1100},
++{0x2510, 0x437A},
++{0x2510, 0x0609},
++{0x2510, 0x0B05},
++{0x2510, 0x0708},
++{0x2510, 0x4137},
++{0x2510, 0x502C},
++{0x2510, 0x2CFE},
++{0x2510, 0x15FE},
++{0x2510, 0x0C2C},
++
++{0x32e6, 0xe0},
++{0x1008, 0x36f},
++{0x100c, 0x58f},
++{0x100e, 0x7af},
++{0x1010, 0x14f},
++
++{0x3230, 0x312},
++{0x3232, 0x532},
++{0x3234, 0x752},
++{0x3236, 0xf2},
++#endif /* Sequencer Update */
++
++//{0x3566, 0x3328}, // clear bit6
++{0x32D0, 0x3A02},
++{0x32D2, 0x3508},
++{0x32D4, 0x3702},
++{0x32D6, 0x3C04},
++{0x32DC, 0x370A},
++{0x30B0, 0x800}, // clear bit9
++#endif /* Sensor Setup */
++
++#if 1 /* Serial 12-bit Timing Setup */
++/* PCLK=24Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 *2 */
++/* PCLK=24Mhz/2 *44/1/12 *2= 88Mhz - TI serializers */
++{0x302E, 2}, // pre_pll_clk_div
++{0x3030, 44}, // pll_multiplier
++{0x302C, 1}, // vt_sys_clk_div (P1 divider)
++{0x302A, 6}, // vt_pix_clk_div (P2 divider)
++{0x3038, 1}, // op_sys_clk_div (P3 divider)
++{0x3036, 12}, // op_word_clk_div (P4 divider)
++{0x30B0, 0x800}, // digital_test: pll_complete_bypass=0
++#endif /* Serial 12-bit Timing Setup */
++
++#if 1 /* Readout Mode Configuration */
++{0x30A2, 1}, // x_odd_inc_
++{0x30A6, 1}, // y_odd_inc_
++{0x3040, 0}, // read_mode
++//{0x3082, 0x8}, // operation_mode_ctrl
++//{0x30BA, 0x11E2}, // digital_ctrl
++{0x3044, 0x400}, // dark_control
++#ifdef AR0231_EMBEDDED_LINE
++{0x3064, 0x1982}, // SMIA_TEST
++#else
++{0x3064, 0x1802}, // SMIA_TEST
++#endif
++//{0x33E0, 0xC80},
++//{0x3180, 0x80},
++//{0x33E4, 0x80},
++#endif /* Readout Mode Configuration */
++
++#if 1 /* Full Res FOV */
++{0x3004, AR0231_X_START}, // X_ADDR_START_
++{0x3008, AR0231_X_END}, // X_ADDR_END_
++{0x3002, AR0231_Y_START}, // Y_ADDR_START_
++{0x3006, AR0231_Y_END}, // Y_ADDR_END_
++{0x3032, 0x0}, // scaling_mode
++{0x3400, 0x10},
++{0x3402, 0x0000 | AR0231_MAX_WIDTH}, // X_OUTPUT_CONTROL
++{0x3404, 0x0000 | AR0231_MAX_HEIGHT}, // Y_OUTPUT_CONTROL
++#endif /* Full Res FOV */
++
++#if 1 /* 3exp Timing and Exposure */
++{0x3082, 0x8}, // operation_mode_ctrl
++{0x30BA, 0x11E2}, // digital_ctrl: num_exp_max=2
++
++/* Row and Pixel Timing */
++{0x300C, 1674}, // line_length_pck_
++{0x300A, 1314}, // frame_length_lines_
++{0x3042, 0}, // extra_delay
++
++/* Exposure Settings */
++//{0x3238, 0x222}, // exposure_ratio
++{0x3012, 355}, // coarse_integration_time_
++{0x3014, 1874}, // fine_integration_time_
++{0x321E, 1874}, // fine_integration_time2
++{0x3222, 1874}, // fine_integration_time3
++{0x30B0, 0x800}, // digital_test: set bit11
++{0x32EA, 0x3C0E},
++{0x32EC, 0x72A1},
++#endif /* 3exp Timing and Exposure - Serial */
++
++#if 1 /* HDR 12 bit Output */
++{0x31D0, 1}, // companding
++{0x31AC, 0x140C}, // data_format_bits: RAW20, OUT12
++#endif /* HDR 12 bit Output */
++
++#if 1 /* MIPI 12 bit Settings */
++{0x31AE, 0x204}, // serial_format: MIPI 4 lanes
++{0x3342, 0x2c2c}, // default, DT=0x12, DT=0x2C
++{0x3346, 0x2c2c}, // default, DT=0x12, DT=0x2C
++{0x334A, 0x2c2c}, // default, DT=0x12, DT=0x2C
++{0x334E, 0x2c2c}, // default, DT=0x12, DT=0x2C
++//{0x3344, 0x0011}, // default, VC=0
++//{0x3348, 0x0111}, // default, VC=1
++//{0x334C, 0x0211}, // default, VC=2
++//{0x3350, 0x0311}, // default, VC=3
++//{0x31B0, 0x49}, // frame_preamble
++//{0x31B2, 0x33}, // line_preamble
++{0x31B4, 0x2185},
++{0x31B6, 0x1146},
++{0x31B8, 0x3047},
++{0x31BA, 0x186},
++{0x31BC, 0x805},
++#endif /* MIPI 12 bit Settings */
++
++/* FPS = 105MHz / reg0x300A / reg0x300C * (DES_XTAL/27MHz), DES_XTAL=23.5MHz */
++{0x300A, AR0231_SENSOR_HEIGHT + 100}, // Frame_length_Lines
++{0x300C, AR0231_SENSOR_WIDTH + 550}, // Line_length_pck
++{0x3012, 0x144}, //Integration_time
++
++#if 0 /* Enable trigger input */
++{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO0 is trigger
++{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO0 is trigger
++{0x30CE, 0x0120}, // TRIGGER_MODE
++//{0x30DC, 0x0120}, // TRIGGER_DELAY
++{0x301A, 0x0118}, // GPI pins enable
++#endif
++};
++
++/* 3Exp HDR Full Resolution Mode Parallel 12bit 30FPS, XCLK=24MHz */
++static const struct ar0231_reg ar0231_regs_wizard_rev7_dvp[] = {
++#if 1 /* Parallel Timing Setup */
++/* PCLK=24Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 */
++/* PCLK=24Mhz/3 *88/1/8 = 88Mhz - TI serializers */
++{0x302A, 8}, // vt_pix_clk_div (P2 divider)
++{0x302C, 1}, // vt_sys_clk_div (P1 divider)
++{0x302E, 3}, // pre_pll_clk_div
++{0x3030, 88}, // pll_multiplier
++{0x3036, 8}, // op_word_clk_div (P4 divider)
++{0x3038, 1}, // op_sys_clk_div (P3 divider)
++{0x30B0, 0x800}, // digital_test: pll_complete_bypass=0
++#endif
++
++#if 1 /* 3exp Timing and Exposure - Parallel */
++{0x3082, 0x8}, // operation_mode_ctrl
++{0x30BA, 0x11E2}, // digital_ctrl: num_exp_max=2
++
++/* Row and Pixel Timing */
++#if 1
++{0x300A, AR0231_SENSOR_HEIGHT + 225}, // frame_length_lines_
++{0x300C, AR0231_SENSOR_WIDTH + 120}, // line_length_pck_
++#else
++{0x300C, 1978}, // line_length_pck_
++{0x300A, 1482}, // frame_length_lines_
++#endif
++{0x3042, 0}, // extra_delay
++
++/* Exposure Settings */
++//{0x3238, 0x222}, // exposure_ratio
++//{0x3012, 355}, // coarse_integration_time_
++{0x3014, 2178}, // fine_integration_time_
++{0x321E, 2178}, // fine_integration_time2
++{0x3222, 2178}, // fine_integration_time3
++{0x30B0, 0x800}, // digital_test: set bit11
++{0x32EA, 0x3C0E},
++{0x32EC, 0x72A1},
++#endif /* 3exp Timing and Exposure - Parallel */
++
++#if 1 /* Parallel HDR 12 bit Output */
++{0x31AE, 0x001}, // serial_format:
++#endif
++
++{0x301A, 0x01d8}, // RESET_REGISTER parallel pins enable
++};
+--
+2.7.4
+
+